Easy_CEM - Version 1.0.5

Version Notes

Derived from MageParts CEM

Download this release

Release Info

Developer Magento Core Team
Extension Easy_CEM
Version 1.0.5
Comparing to
See all releases


Version 1.0.5

Files changed (55) hide show
  1. app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit.php +46 -0
  2. app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Form.php +35 -0
  3. app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tab/LostCem.php +82 -0
  4. app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tab/LostLicense.php +82 -0
  5. app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tabs.php +57 -0
  6. app/code/community/Easy/CEM/Block/Adminhtml/Packages.php +49 -0
  7. app/code/community/Easy/CEM/Block/Adminhtml/Packages/Edit.php +125 -0
  8. app/code/community/Easy/CEM/Block/Adminhtml/Packages/Grid.php +114 -0
  9. app/code/community/Easy/CEM/Block/Adminhtml/Packages/Grid/Renderer/UpdateAvailable.php +42 -0
  10. app/code/community/Easy/CEM/Helper/Data.php +24 -0
  11. app/code/community/Easy/CEM/Model/Licenses.php +78 -0
  12. app/code/community/Easy/CEM/Model/Mysql4/Licenses.php +60 -0
  13. app/code/community/Easy/CEM/Model/Mysql4/Licenses/Collection.php +32 -0
  14. app/code/community/Easy/CEM/Model/Mysql4/Packages.php +93 -0
  15. app/code/community/Easy/CEM/Model/Mysql4/Packages/Collection.php +111 -0
  16. app/code/community/Easy/CEM/Model/Mysql4/Services.php +125 -0
  17. app/code/community/Easy/CEM/Model/Mysql4/Services/Collection.php +44 -0
  18. app/code/community/Easy/CEM/Model/Observer.php +81 -0
  19. app/code/community/Easy/CEM/Model/Packages.php +479 -0
  20. app/code/community/Easy/CEM/Model/Services.php +32 -0
  21. app/code/community/Easy/CEM/Model/Soap.php +155 -0
  22. app/code/community/Easy/CEM/Model/Soap/class.nusoap_base.php +984 -0
  23. app/code/community/Easy/CEM/Model/Soap/class.soap_fault.php +90 -0
  24. app/code/community/Easy/CEM/Model/Soap/class.soap_parser.php +639 -0
  25. app/code/community/Easy/CEM/Model/Soap/class.soap_server.php +1073 -0
  26. app/code/community/Easy/CEM/Model/Soap/class.soap_transport_http.php +1305 -0
  27. app/code/community/Easy/CEM/Model/Soap/class.soap_val.php +107 -0
  28. app/code/community/Easy/CEM/Model/Soap/class.soapclient.php +977 -0
  29. app/code/community/Easy/CEM/Model/Soap/class.wsdl.php +1904 -0
  30. app/code/community/Easy/CEM/Model/Soap/class.wsdlcache.php +209 -0
  31. app/code/community/Easy/CEM/Model/Soap/class.xmlschema.php +938 -0
  32. app/code/community/Easy/CEM/Model/Soap/nusoap.php +7993 -0
  33. app/code/community/Easy/CEM/Model/Soap/nusoapmime.php +501 -0
  34. app/code/community/Easy/CEM/Model/System/Config/Source/CEM/Frequency.php +33 -0
  35. app/code/community/Easy/CEM/controllers/Adminhtml/LicensesController.php +281 -0
  36. app/code/community/Easy/CEM/controllers/Adminhtml/PackagesController.php +259 -0
  37. app/code/community/Easy/CEM/controllers/IndexController.php +53 -0
  38. app/code/community/Easy/CEM/etc/config.xml +171 -0
  39. app/code/community/Easy/CEM/etc/system.xml +56 -0
  40. app/code/community/Easy/CEM/sql/cem_setup/mysql4-install-1.0.0.php +93 -0
  41. app/design/adminhtml/default/default/layout/cem.xml +42 -0
  42. app/design/adminhtml/default/default/template/cem/licenses/lostcem.phtml +156 -0
  43. app/design/adminhtml/default/default/template/cem/licenses/lostlicense.phtml +112 -0
  44. app/design/adminhtml/default/default/template/cem/packages/install.phtml +204 -0
  45. app/design/adminhtml/default/default/template/cem/packages/register.phtml +117 -0
  46. app/etc/modules/Easy_CEM.xml +29 -0
  47. app/locale/cs_CZ/Easy_CEM.csv +101 -0
  48. app/locale/en_US/Easy_CEM.csv +99 -0
  49. package.xml +30 -0
  50. skin/adminhtml/default/default/cem/i/extension_icon.gif +0 -0
  51. skin/adminhtml/default/default/cem/i/key_icon.gif +0 -0
  52. skin/adminhtml/default/default/cem/i/lost_key_icon.gif +0 -0
  53. skin/adminhtml/default/default/cem/i/notify_icon.gif +0 -0
  54. skin/adminhtml/default/default/cem/i/package_add_icon.gif +0 -0
  55. skin/adminhtml/default/default/cem/style.css +83 -0
app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Licenses_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->_objectId = 'id';
30
+ $this->_blockGroup = 'cem';
31
+ $this->_controller = 'adminhtml_licenses';
32
+ parent::__construct();
33
+ }
34
+
35
+
36
+ /**
37
+ * Get header text
38
+ *
39
+ * @return string
40
+ */
41
+ public function getHeaderText()
42
+ {
43
+ return Mage::helper('cem')->__('License Management');
44
+ }
45
+
46
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Form.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Licenses_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
22
+ {
23
+
24
+ /**
25
+ * Prepares the form html, the form html elements can be found in the tabs
26
+ */
27
+ protected function _prepareForm()
28
+ {
29
+ $form = new Varien_Data_Form(array('id' => 'edit_form'));
30
+ $form->setUseContainer(true);
31
+ $this->setForm($form);
32
+ return parent::_prepareForm();
33
+ }
34
+
35
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tab/LostCem.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Licenses_Edit_Tab_LostCem extends Mage_Adminhtml_Block_Widget_Form
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ parent::__construct();
30
+ $this->setTemplate('cem/licenses/lostcem.phtml');
31
+ }
32
+
33
+
34
+ /**
35
+ * Prepare layout
36
+ */
37
+ protected function _prepareLayout()
38
+ {
39
+ $this->setChild('lostCemKeyButton',
40
+ $this->getLayout()->createBlock('adminhtml/widget_button')
41
+ ->setData(array(
42
+ 'label' => Mage::helper('cem')->__('OK'),
43
+ 'onclick' => 'lostCem.install();',
44
+ 'class' => 'save f-right'
45
+ ))
46
+ );
47
+
48
+ $this->setChild('backButton',
49
+ $this->getLayout()->createBlock('adminhtml/widget_button')
50
+ ->setData(array(
51
+ 'label' => Mage::helper('cem')->__('Back'),
52
+ 'onclick' => "setLocation('{$this->getUrl('*/*/')}')",
53
+ 'class' => 'back f-right'
54
+ ))
55
+ );
56
+
57
+ return parent::_prepareLayout();
58
+ }
59
+
60
+
61
+ /**
62
+ * Get lost CEM key button (declared in _prepareLayout)
63
+ *
64
+ * @return Mage_Adminhtml_Block_Widget_Button
65
+ */
66
+ public function getLostCemKeyButtonHtml()
67
+ {
68
+ return $this->getChildHtml('lostCemKeyButton');
69
+ }
70
+
71
+
72
+ /**
73
+ * Get backbutton (declared in _prepareLayout)
74
+ *
75
+ * @return Mage_Adminhtml_Block_Widget_Button
76
+ */
77
+ public function getBackButtonHtml()
78
+ {
79
+ return $this->getChildHtml('backButton');
80
+ }
81
+
82
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tab/LostLicense.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Licenses_Edit_Tab_LostLicense extends Mage_Adminhtml_Block_Widget_Form
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ parent::__construct();
30
+ $this->setTemplate('cem/licenses/lostlicense.phtml');
31
+ }
32
+
33
+
34
+ /**
35
+ * Prepare layout
36
+ */
37
+ protected function _prepareLayout()
38
+ {
39
+ $this->setChild('lostLicenseKeyButton',
40
+ $this->getLayout()->createBlock('adminhtml/widget_button')
41
+ ->setData(array(
42
+ 'label' => Mage::helper('cem')->__('OK'),
43
+ 'onclick' => 'lostLicenses.install();',
44
+ 'class' => 'save f-right'
45
+ ))
46
+ );
47
+
48
+ $this->setChild('backButton',
49
+ $this->getLayout()->createBlock('adminhtml/widget_button')
50
+ ->setData(array(
51
+ 'label' => Mage::helper('cem')->__('Back'),
52
+ 'onclick' => "setLocation('{$this->getUrl('*/*/')}')",
53
+ 'class' => 'back f-right'
54
+ ))
55
+ );
56
+
57
+ return parent::_prepareLayout();
58
+ }
59
+
60
+
61
+ /**
62
+ * Get lost License key button (declared in _prepareLayout)
63
+ *
64
+ * @return Mage_Adminhtml_Block_Widget_Button
65
+ */
66
+ public function getLostLicenseKeyButtonHtml()
67
+ {
68
+ return $this->getChildHtml('lostLicenseKeyButton');
69
+ }
70
+
71
+
72
+ /**
73
+ * Get backbutton (declared in _prepareLayout)
74
+ *
75
+ * @return Mage_Adminhtml_Block_Widget_Button
76
+ */
77
+ public function getBackButtonHtml()
78
+ {
79
+ return $this->getChildHtml('backButton');
80
+ }
81
+
82
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Licenses/Edit/Tabs.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Licenses_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ parent::__construct();
30
+ $this->setId('cem_licenses_tabs');
31
+ $this->setDestElementId('edit_form');
32
+ $this->setTitle(Mage::helper('cem')->__('License Management'));
33
+ }
34
+
35
+
36
+ /**
37
+ * Add tabs before writing HTML tabs
38
+ */
39
+ protected function _beforeToHtml()
40
+ {
41
+ $this->addTab('lost_cem_section', array(
42
+ 'label' => Mage::helper('cem')->__('Lost CEM Key'),
43
+ 'title' => Mage::helper('cem')->__('Lost CEM Key'),
44
+ 'content' => $this->getLayout()->createBlock('cem/adminhtml_licenses_edit_tab_lostCem')->toHtml(),
45
+ 'active' => true
46
+ ));
47
+
48
+ $this->addTab('lost_license_section', array(
49
+ 'label' => Mage::helper('cem')->__('Lost License Key'),
50
+ 'title' => Mage::helper('cem')->__('Lost License Key'),
51
+ 'content' => $this->getLayout()->createBlock('cem/adminhtml_licenses_edit_tab_lostLicense')->toHtml()
52
+ ));
53
+
54
+ return parent::_beforeToHtml();
55
+ }
56
+
57
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Packages.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Packages extends Mage_Adminhtml_Block_Widget_Grid_Container
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->_controller = 'adminhtml_packages';
30
+ $this->_blockGroup = 'cem';
31
+ $this->_headerText = Mage::helper('cem')->__('Manage Extensions <span class="powered"><a href="http://www.mageparts.com" target="_blank">Powered by MageParts.com</a></span>');
32
+ $this->_addButtonLabel = Mage::helper('cem')->__('Install New Extension');
33
+
34
+ $this->_addButton('license_management', array(
35
+ 'label' => Mage::helper('cem')->__('License Management'),
36
+ 'onclick' => "setLocation('".$this->getUrl('*/*/licenseManagement')."')",
37
+ 'class' => '',
38
+ ));
39
+
40
+ $this->_addButton('update', array(
41
+ 'label' => Mage::helper('cem')->__('Update Extensions'),
42
+ 'onclick' => "setLocation('".$this->getUrl('*/*/update')."')",
43
+ 'class' => '',
44
+ ));
45
+
46
+ parent::__construct();
47
+ }
48
+
49
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Packages/Edit.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Packages_Edit extends Mage_Adminhtml_Block_Template
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ $this->_controller = 'adminhtml_packages';
30
+ $this->_blockGroup = 'cem';
31
+
32
+ parent::__construct();
33
+
34
+ $this->setTemplate('cem/packages/install.phtml');
35
+ }
36
+
37
+
38
+ public function getHeaderText()
39
+ {
40
+ $package = Mage::registry('cem_package');
41
+ if ($package->getPackageId()) {
42
+ return Mage::helper('cem')->__("Update Extension '%s'", $this->htmlEscape($package->getIdentifier()));
43
+ }
44
+ else {
45
+ return Mage::helper('cem')->__('Install New Extension');
46
+ }
47
+ }
48
+
49
+
50
+ /**
51
+ * Retrieve install url
52
+ */
53
+ public function getInstallUrl()
54
+ {
55
+ return $this->getUrl('*/*/install');
56
+ }
57
+
58
+
59
+ /**
60
+ * Retrieve update url
61
+ */
62
+ public function getUpdateUrl()
63
+ {
64
+ return $this->getUrl('*/*/update');
65
+ }
66
+
67
+
68
+ /**
69
+ * Retrieve package id
70
+ */
71
+ public function getPackageId()
72
+ {
73
+ return Mage::registry('cem_package')->getPackageId();
74
+ }
75
+
76
+
77
+ /**
78
+ * Retrieve package service url
79
+ */
80
+ public function getPackageServiceUrl()
81
+ {
82
+ return Mage::getModel('cem/services')
83
+ ->load(Mage::registry('cem_package')->getServiceId())
84
+ ->getUrl();
85
+ }
86
+
87
+
88
+ /**
89
+ * Retrieve package license key
90
+ */
91
+ public function getPackageLicenseKey()
92
+ {
93
+ return Mage::getModel('cem/licenses')
94
+ ->load(Mage::registry('cem_package')->getLicenseId())
95
+ ->getLicenseKey();
96
+ }
97
+
98
+
99
+ /**
100
+ * Retrieve package identifier
101
+ */
102
+ public function getPackageIdentifier()
103
+ {
104
+ return Mage::registry('cem_package')->getIdentifier();
105
+ }
106
+
107
+
108
+ /**
109
+ * Retrieve rollback identifier
110
+ */
111
+ public function getIdentifierRollback()
112
+ {
113
+ return Mage::registry('cem_package')->getIdentifierRollback();
114
+ }
115
+
116
+
117
+ /**
118
+ * Get package auto update
119
+ */
120
+ public function getPackageAutoUpdate()
121
+ {
122
+ return Mage::registry('cem_package')->getAutoUpdate();
123
+ }
124
+
125
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Packages/Grid.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Packages_Grid extends Mage_Adminhtml_Block_Widget_Grid
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ public function __construct()
28
+ {
29
+ if(!Mage::getModel('cem/packages')->checkCemEmail()) {
30
+ $this->setTemplate('cem/packages/register.phtml');
31
+ }
32
+ else {
33
+ parent::__construct();
34
+ $this->setId('cemPackagesGrid');
35
+ $this->setDefaultSort('title');
36
+ $this->setDefaultDir('ASC');
37
+ }
38
+ }
39
+
40
+
41
+ /**
42
+ * Prepare collection
43
+ */
44
+ protected function _prepareCollection()
45
+ {
46
+ $collection = Mage::getModel('cem/packages')->getCollection();
47
+ /* @var $collection Easy_CEM_Model_Mysql4_Packages_Collection */
48
+ $this->setCollection($collection);
49
+
50
+ return parent::_prepareCollection();
51
+ }
52
+
53
+
54
+ /**
55
+ * Prepare columns
56
+ */
57
+ protected function _prepareColumns()
58
+ {
59
+ // Title column
60
+ $this->addColumn('title', array(
61
+ 'header' => Mage::helper('cms')->__('Title'),
62
+ 'index' => 'title',
63
+ ));
64
+
65
+ // Title column
66
+ $this->addColumn('version', array(
67
+ 'header' => Mage::helper('cem')->__('Version'),
68
+ 'width' => '100px',
69
+ 'index' => 'version',
70
+ ));
71
+
72
+ // Last update date column
73
+ $this->addColumn('last_update', array(
74
+ 'header' => Mage::helper('cem')->__('Updated at'),
75
+ 'width' => '160px',
76
+ 'index' => 'last_update',
77
+ 'type' => 'datetime',
78
+ 'gmtoffset' => true,
79
+ 'default' => ' ---- '
80
+ ));
81
+
82
+ // Has updates
83
+ $this->addColumn('update_available', array(
84
+ 'header' => Mage::helper('cem')->__('Updates Available'),
85
+ 'index' => 'update_available',
86
+ 'width' => '20px',
87
+ 'renderer' => 'cem/adminhtml_packages_grid_renderer_updateAvailable'
88
+ ));
89
+
90
+ return parent::_prepareColumns();
91
+ }
92
+
93
+
94
+ /**
95
+ * Fires after collection has been loaded
96
+ */
97
+ protected function _afterLoadCollection()
98
+ {
99
+ $this->getCollection()->walk('afterLoad');
100
+ parent::_afterLoadCollection();
101
+ }
102
+
103
+
104
+ /**
105
+ * Row click url
106
+ *
107
+ * @return string
108
+ */
109
+ public function getRowUrl($row)
110
+ {
111
+ return $this->getUrl('*/*/edit', array('package_id' => $row->getPackageId()));
112
+ }
113
+
114
+ }
app/code/community/Easy/CEM/Block/Adminhtml/Packages/Grid/Renderer/UpdateAvailable.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Block_Adminhtml_Packages_Grid_Renderer_UpdateAvailable
22
+ extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
23
+ {
24
+ /**
25
+ * Renders grid column
26
+ *
27
+ * @param Varien_Object $row
28
+ * @return string
29
+ */
30
+ public function render(Varien_Object $row)
31
+ {
32
+ switch ($row->getData($this->getColumn()->getIndex())) {
33
+ case 1:
34
+ $class = 'yes';
35
+ break;
36
+ case 0:
37
+ $class = 'no';
38
+ break;
39
+ }
40
+ return '<div class="grid-update-available-' . $class . '"></div>';
41
+ }
42
+ }
app/code/community/Easy/CEM/Helper/Data.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Helper_Data extends Mage_Core_Helper_Abstract
22
+ {
23
+
24
+ }
app/code/community/Easy/CEM/Model/Licenses.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Licenses extends Mage_Core_Model_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/licenses');
30
+ }
31
+
32
+
33
+ /**
34
+ * Validate a email address
35
+ *
36
+ * @param string $email
37
+ * @return boolean
38
+ */
39
+ public function validateEmail( $email )
40
+ {
41
+ // First, we check that there's one @ symbol,
42
+ // and that the lengths are right.
43
+ if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
44
+ // Email invalid because wrong number of characters
45
+ // in one section or wrong number of @ symbols.
46
+ return false;
47
+ }
48
+
49
+ // Split it into sections to make life easier
50
+ $email_array = explode("@", $email);
51
+ $local_array = explode(".", $email_array[0]);
52
+
53
+ for ($i = 0; $i < sizeof($local_array); $i++) {
54
+ if(!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$",$local_array[$i])) {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ // Check if domain is IP. If not,
60
+ // it should be valid domain name
61
+ if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) {
62
+ $domain_array = explode(".", $email_array[1]);
63
+
64
+ if (sizeof($domain_array) < 2) {
65
+ return false; // Not enough parts to domain
66
+ }
67
+
68
+ for ($i = 0; $i < sizeof($domain_array); $i++) {
69
+ if(!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$",$domain_array[$i])) {
70
+ return false;
71
+ }
72
+ }
73
+ }
74
+
75
+ return true;
76
+ }
77
+
78
+ }
app/code/community/Easy/CEM/Model/Mysql4/Licenses.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Licenses extends Mage_Core_Model_Mysql4_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/licenses', 'license_id');
30
+ }
31
+
32
+
33
+ /**
34
+ * Check if a license key already exist
35
+ *
36
+ * @param string $licenseKey
37
+ * @return array
38
+ */
39
+ public function licenseKeyExists( $licenseKey )
40
+ {
41
+ // Read adapter
42
+ $read = $this->_getReadAdapter();
43
+
44
+ // Select
45
+ $select = $read->select()
46
+ ->from($this->getMainTable())
47
+ ->where("license_key='{$licenseKey}'")
48
+ ->limit(1);
49
+
50
+ // Fetch row
51
+ $row = $read->fetchRow($select);
52
+
53
+ if(isset($row['license_id']) && !empty($row['license_id'])) {
54
+ return $row['license_id'];
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+ }
app/code/community/Easy/CEM/Model/Mysql4/Licenses/Collection.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Licenses_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/licenses');
30
+ }
31
+
32
+ }
app/code/community/Easy/CEM/Model/Mysql4/Packages.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Packages extends Mage_Core_Model_Mysql4_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/packages', 'package_id');
30
+ }
31
+
32
+
33
+ /**
34
+ * Check if a license key already has been used
35
+ *
36
+ * @param int $packageId [optional]
37
+ * @return array
38
+ */
39
+ public function licenseUsed( $licenseId, $packageId=0 )
40
+ {
41
+ // Read adapter
42
+ $read = $this->_getReadAdapter();
43
+
44
+ // Select
45
+ $select = $read->select()
46
+ ->from($this->getMainTable())
47
+ ->where("license_id=?",$licenseId)
48
+ ->limit(1);
49
+
50
+ // Package exception
51
+ if(!empty($packageId)) {
52
+ $select->where("package_id != ?",$packageId);
53
+ }
54
+
55
+ // Fetch row
56
+ $row = $read->fetchRow($select);
57
+
58
+ if(isset($row['package_id']) && !empty($row['package_id'])) {
59
+ return true;
60
+ }
61
+
62
+ return false;
63
+ }
64
+
65
+
66
+ /**
67
+ * Check if a package already is installed
68
+ *
69
+ * @param string $identifier
70
+ * @return array
71
+ */
72
+ public function packageIsInstalled( $identifier )
73
+ {
74
+ // Read adapter
75
+ $read = $this->_getReadAdapter();
76
+
77
+ // Select
78
+ $select = $read->select()
79
+ ->from($this->getMainTable())
80
+ ->where("identifier='{$identifier}'")
81
+ ->limit(1);
82
+
83
+ // Fetch row
84
+ $row = $read->fetchRow($select);
85
+
86
+ if(isset($row['package_id']) && !empty($row['package_id'])) {
87
+ return true;
88
+ }
89
+
90
+ return false;
91
+ }
92
+
93
+ }
app/code/community/Easy/CEM/Model/Mysql4/Packages/Collection.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Packages_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/packages');
30
+ }
31
+
32
+
33
+ /**
34
+ * Filter by package identifier
35
+ *
36
+ * @param string $identifier [optional]
37
+ * @return Easy_CEM_Model_Mysql4_Packages_Collection
38
+ */
39
+ public function setIdentifierFilter( $identifier='' )
40
+ {
41
+ if(!empty($identifier)) {
42
+ $this->getSelect()->where('identifier = ?',$identifier);
43
+ }
44
+ return $this;
45
+ }
46
+
47
+
48
+ /**
49
+ * Filter by package id
50
+ *
51
+ * @param int $id [optional]
52
+ * @return Easy_CEM_Model_Mysql4_Packages_Collection
53
+ */
54
+ public function setIdFilter( $id )
55
+ {
56
+ if(!empty($id)) {
57
+ $this->getSelect()->where('package_id= ?',$id);
58
+ }
59
+ return $this;
60
+ }
61
+
62
+
63
+ /**
64
+ * Filter by package auto update option
65
+ *
66
+ * @param int $autoUpdate [optional]
67
+ * @return Easy_CEM_Model_Mysql4_Packages_Collection
68
+ */
69
+ public function setAutoUpdateFilter( $autoUpdate=1 )
70
+ {
71
+ $this->getSelect()->where('auto_update = ?',$autoUpdate);
72
+ return $this;
73
+ }
74
+
75
+
76
+ /**
77
+ * Filter by package module
78
+ *
79
+ * @param int $moduleId [optional]
80
+ * @return Easy_CEM_Model_Mysql4_Packages_Collection
81
+ */
82
+ public function setModuleFilter( $module=0 )
83
+ {
84
+ if(!empty($module)) {
85
+ $this->getSelect()->where('module_id = ?',$module);
86
+ }
87
+ return $this;
88
+ }
89
+
90
+
91
+ /**
92
+ * Include service and license information
93
+ */
94
+ public function joinTables()
95
+ {
96
+ $this->getSelect()->join(
97
+ array('services' => $this->getTable('cem/services')),
98
+ 'main_table.service_id=services.service_id',
99
+ '*'
100
+ );
101
+
102
+ $this->getSelect()->join(
103
+ array('licenses' => $this->getTable('cem/licenses')),
104
+ 'main_table.license_id=licenses.license_id',
105
+ '*'
106
+ );
107
+
108
+ return $this;
109
+ }
110
+
111
+ }
app/code/community/Easy/CEM/Model/Mysql4/Services.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Services extends Mage_Core_Model_Mysql4_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/services', 'service_id');
30
+ }
31
+
32
+
33
+ /**
34
+ * Check if a service url already exists
35
+ *
36
+ * @param string $url
37
+ * @return array
38
+ */
39
+ public function urlExists( $url )
40
+ {
41
+ // Read adapter
42
+ $read = $this->_getReadAdapter();
43
+
44
+ // Select
45
+ $select = $read->select()
46
+ ->from($this->getMainTable())
47
+ ->where("url='{$url}'")
48
+ ->limit(1);
49
+
50
+ // Fetch row
51
+ $row = $read->fetchRow($select);
52
+
53
+ if(isset($row['service_id']) && !empty($row['service_id'])) {
54
+ return $row['service_id'];
55
+ }
56
+
57
+ return false;
58
+ }
59
+
60
+
61
+ /**
62
+ * Retrieve CEM key
63
+ *
64
+ * @param int $serviceId
65
+ * @return string
66
+ */
67
+ public function getCemKey( $serviceId )
68
+ {
69
+ // Read adapter
70
+ $read = $this->_getReadAdapter();
71
+
72
+ // Select
73
+ $select = $read->select()
74
+ ->from($this->getTable("cem/service_keys"))
75
+ ->where("service_id = ?",$serviceId)
76
+ ->limit(1);
77
+
78
+ // Fetch row
79
+ $row = $read->fetchRow($select);
80
+
81
+ if(isset($row['key']) && !empty($row['key'])) {
82
+ return $row['key'];
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+
89
+ /**
90
+ * Retrieve CEM key
91
+ *
92
+ * @param array $data
93
+ * @return boolean
94
+ */
95
+ public function addCemKey( array $data )
96
+ {
97
+ // Read adapter
98
+ $read = $this->_getReadAdapter();
99
+
100
+ // Select
101
+ $select = $read->select()
102
+ ->from($this->getTable("cem/service_keys"))
103
+ ->where("service_id = ?",$data['service_id'])
104
+ ->limit(1);
105
+
106
+ // Fetch row
107
+ $row = $read->fetchRow($select);
108
+
109
+ if($data) {
110
+ if(isset($row['key'])) {
111
+ if($this->_getWriteAdapter()->update($this->getTable('cem/service_keys'), $data, "service_id={$data['service_id']}")) {
112
+ return true;
113
+ }
114
+ }
115
+ else {
116
+ if($this->_getWriteAdapter()->insert($this->getTable('cem/service_keys'), $data)) {
117
+ return true;
118
+ }
119
+ }
120
+ }
121
+
122
+ return false;
123
+ }
124
+
125
+ }
app/code/community/Easy/CEM/Model/Mysql4/Services/Collection.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Mysql4_Services_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/services');
30
+ }
31
+
32
+
33
+ /**
34
+ * Filter services by url
35
+ *
36
+ * @param string $url
37
+ * @return Easy_CEM_Model_Mysql4_Services_Collection
38
+ */
39
+ public function setUrlFilter( $url )
40
+ {
41
+ $this->getSelect()->where('url = ?',$url);
42
+ return $this;
43
+ }
44
+ }
app/code/community/Easy/CEM/Model/Observer.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Observer
22
+ {
23
+
24
+ const XML_FREQUENCY_PATH = 'system/cem/frequency';
25
+
26
+ public function checkUpdate( $schedule )
27
+ {
28
+ if (($this->getFrequency() + $this->getLastUpdate()) > time()) {
29
+ return $this;
30
+ }
31
+
32
+ // Get package module
33
+ $packageModel = Mage::getModel('cem/packages');
34
+
35
+ // Get package collection
36
+ $packages = $packageModel->getCollection()
37
+ ->joinTables();
38
+
39
+ // Update packages
40
+ $update = $packageModel->update($packages);
41
+
42
+ $this->setLastUpdate();
43
+
44
+ return $this;
45
+ }
46
+
47
+
48
+ /**
49
+ * Retrieve Update Frequency
50
+ *
51
+ * @return int
52
+ */
53
+ public function getFrequency()
54
+ {
55
+ return Mage::getStoreConfig(self::XML_FREQUENCY_PATH) * 3600;
56
+ }
57
+
58
+
59
+ /**
60
+ * Retrieve Last update time
61
+ *
62
+ * @return int
63
+ */
64
+ public function getLastUpdate()
65
+ {
66
+ return Mage::app()->loadCache('cem_update_lastcheck');
67
+ }
68
+
69
+
70
+ /**
71
+ * Set last update time (now)
72
+ *
73
+ * @return Easy_CEM_Model_Observer
74
+ */
75
+ public function setLastUpdate()
76
+ {
77
+ Mage::app()->saveCache(time(), 'cem_update_lastcheck');
78
+ return $this;
79
+ }
80
+
81
+ }
app/code/community/Easy/CEM/Model/Packages.php ADDED
@@ -0,0 +1,479 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * Error reporting, don't logg any strict errors here it gives us problems with the PEAR & NuSOAP classes
23
+ */
24
+ //error_reporting(E_ALL);
25
+
26
+ if(!@class_exists("Archive_Tar")) {
27
+ // We need to add the include path to make sure that the file will be loaded properly
28
+ set_include_path((Mage::getBaseDir('base') . DS . 'downloader' . DS . 'pearlib' . DS . 'php') . PS . get_include_path());
29
+ $archiveFile = Mage::getBaseDir('base') . DS . 'downloader' . DS . 'pearlib' . DS . 'php' . DS . 'Archive' . DS . 'Tar.php';
30
+
31
+ if(file_exists($archiveFile)) {
32
+ require_once $archiveFile;
33
+ }
34
+ }
35
+
36
+ class Easy_CEM_Model_Packages extends Mage_Core_Model_Abstract
37
+ {
38
+
39
+ protected $_downloadDir = null;
40
+
41
+
42
+ /**
43
+ * Constructor
44
+ */
45
+ protected function _construct()
46
+ {
47
+ $this->_init('cem/packages');
48
+ }
49
+
50
+
51
+ /**
52
+ * Install a new extension
53
+ *
54
+ * @param string $packageIdentifier
55
+ * @param string $licenseKey
56
+ * @param string $serviceUrl
57
+ * @param boolean $autoUpdate
58
+ * @param int $updatePackageId [optional]
59
+ * @return unknown
60
+ */
61
+ public function install( $packageIdentifier, $licenseKey, $serviceUrl, $autoUpdate, $updatePackageId=0 )
62
+ {
63
+ $tmpFile = '';
64
+
65
+ try {
66
+ // 1. We need these values
67
+ if(!empty($serviceUrl) && !empty($packageIdentifier) && !empty($licenseKey)) {
68
+ // 2. Save new license key or load existsing one
69
+ $licenseModel = Mage::getModel('cem/licenses');
70
+ $newLicenseKey = false;
71
+
72
+ if(!$licenseId = Mage::getResourceModel('cem/licenses')->licenseKeyExists($licenseKey)) {
73
+ // Save new
74
+ if(!$licenseModel->setLicenseKey($licenseKey)->save()) {
75
+ throw new Exception(Mage::helper('cem')->__("Unable to save package information, please try again"));
76
+ }
77
+ $licenseId = $licenseModel->getLicenseId();
78
+ $newLicenseKey = true;
79
+ }
80
+ else {
81
+ // Load existing
82
+ $licenseModel->load($licenseId);
83
+ }
84
+
85
+ // 3. Save new service url or load existing one
86
+ $serviceModel = Mage::getModel('cem/services');
87
+ $newService = false;
88
+
89
+ if(!$serviceId = Mage::getResourceModel('cem/services')->urlExists($serviceUrl)) {
90
+ // Save new
91
+ if(!$serviceModel->setUrl($serviceUrl)->save()) {
92
+ throw new Exception(Mage::helper('cem')->__("Unable to save package information, please try again"));
93
+ }
94
+ $serviceId = $serviceModel->getServiceId();
95
+ $newService = true;
96
+ }
97
+ else {
98
+ // Load existing
99
+ $serviceModel->load($serviceId);
100
+ }
101
+
102
+ // 4. Chck if url exists
103
+ if(!@fopen($serviceUrl,'r')) {
104
+ throw new Exception(Mage::helper('cem')->__("The provided service url is either invalid or unreachable. Make sure that the service url you provided is correct and try again in a few minutes. If the problem consists we advise you to contact your software retailer for assistance."));
105
+ }
106
+
107
+ // 6. Retrieve or create a new CEM key from the repository
108
+ $cem_key = '';
109
+
110
+ if(!$cem_key = Mage::getResourceModel('cem/services')->getCemKey($serviceId)) {
111
+ // Soap call: create new CEM key
112
+ $cemKeyCall = Mage::getModel('cem/soap')->call(
113
+ 'createCemKey',
114
+ array(
115
+ 'email' => Mage::getStoreConfig('system/cem/email'),
116
+ 'clientHostname' => Mage::getStoreConfig('web/unsecure/base_url')
117
+ ),
118
+ $serviceUrl
119
+ );
120
+
121
+ $cem_key = $cemKeyCall->getResults();
122
+
123
+ // Check for soap errors
124
+ if(is_null($cem_key)) {
125
+ if(trim($cemKeyCall->getErrorMessage())=='') {
126
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while the new CEM key was created. Please contact your retailer for assistance."));
127
+ }
128
+ throw new Exception(Mage::helper('cem')->__($cemKeyCall->getErrorMessage()));
129
+ }
130
+
131
+ // Save new CEM key
132
+ if(!empty($cem_key)) {
133
+ if(!Mage::getResourceModel('cem/services')->addCemKey(array('service_id' => $serviceId, 'key' => $cem_key))) {
134
+ throw new Exception(Mage::helper('cem')->__("Unable to save CEM key, please contact your software retailer"));
135
+ }
136
+ }
137
+ else {
138
+ throw new Exception(Mage::helper('cem')->__("CEM key is empty, please contact your retailer"));
139
+ }
140
+ }
141
+
142
+ // 7. Retrieve package information from service repository
143
+ $call = Mage::getModel('cem/soap')->call(
144
+ 'install',
145
+ array(
146
+ 'packageIdentifier' => $packageIdentifier,
147
+ 'licenseKey' => $licenseKey,
148
+ 'cemKey' => $cem_key,
149
+ 'clientHostname' => Mage::getStoreConfig('web/unsecure/base_url')
150
+ ),
151
+ $serviceUrl
152
+ );
153
+
154
+ $response = $call->getResults();
155
+
156
+ if(is_null($response)) {
157
+ if(trim($call->getErrorMessage())=='') {
158
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while installing the extension. Please contact your retailer for assistance."));
159
+ }
160
+ throw new Exception(Mage::helper('cem')->__($call->getErrorMessage()));
161
+ }
162
+
163
+ // 8. Minimum core version checkup
164
+ if(!empty($response['min_core_version']) && (floatval(Mage::getVersion()) < floatval($response['min_core_version']))) {
165
+ $minVersion = number_format($response['min_core_version'],2);
166
+ $maxVersion = number_format($response['max_core_version'],2);
167
+
168
+ if(!empty($response['max_core_version']) && $maxVersion > 0.0) {
169
+ throw new Exception(Mage::helper('cem')->__("The version of your Magento installation is too old to support the requested version of this extension. The minimum required version of Magento is %s, the maximum allowed is %s. The currently installed version of Magento is %s. Please upgrade your Magento installation to meet these requirements and try again. If you require any further assistance we advise you to contact your software retailer.",$minVersion,$maxVersion,Mage::getVersion()));
170
+ }
171
+
172
+ throw new Exception(Mage::helper('cem')->__("The version of your Magento installation is too old to support the requested version of this extension. The minimum required version of Magento is %s. The currently installed version of Magento is %s. Please upgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer.",$minVersion,Mage::getVersion()));
173
+ }
174
+
175
+
176
+ // 9. Maximum core version checkup
177
+ if(!empty($response['max_core_version']) && (floatval(Mage::getVersion()) > floatval($response['max_core_version']))) {
178
+ $maxVersion = number_format($response['max_core_version'],2);
179
+ $minVersion = number_format($response['min_core_version'],2);
180
+
181
+ if(!empty($response['min_core_version']) && $minVersion > 0.0) {
182
+ throw new Exception(Mage::helper('cem')->__("The version of your Magento installation is too new to support the requested version of this extension. You can not use this extension version togheter with a Magento installation with a version above %s or below %s. The currently installed version of Magento is %s. Please downgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer.",$maxVersion,$minVersion,Mage::getVersion()));
183
+ }
184
+
185
+ throw new Exception(Mage::helper('cem')->__("The version of your Magento installation is too new to support the requested version of this extension. You can not use this extension version togheter with a Magento installation with a version higher then %s. The currently installed version of Magento is %s. Please downgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer.",$maxVersion,Mage::getVersion()));
186
+ }
187
+
188
+ // 10. Check writable paths
189
+ $unwritablePaths = array();
190
+
191
+ if(!empty($response['writable_paths'])) {
192
+ foreach (explode(',',$response['writable_paths']) as $p) {
193
+ $path = Mage::getBaseDir('base') . DS . $p;
194
+
195
+ if(!is_writable($path) && !@chmod($path,777)) {
196
+ // This path was not writable
197
+ $unwritablePaths[] = $path;
198
+ }
199
+ }
200
+ }
201
+
202
+ // If there were any paths which weren't writable throw a new exception
203
+ if(!empty($unwritablePaths)) {
204
+ throw new Exception(Mage::helper('cem')->__("Unable to install extension, the following paths needs to be writable: \n\n".implode("\n\n",$unwritablePaths)));
205
+ }
206
+
207
+ // 11. Check if a package of the same type as the retrieved module already exists
208
+ $moduleExists = $this->getCollection()
209
+ ->setModuleFilter($response['module_id']);
210
+
211
+ $data = $moduleExists->getSize()>0 ? $moduleExists->getFirstItem()->getData() : null;
212
+
213
+ if($data) {
214
+ $updatePackageId = $data['package_id'];
215
+ }
216
+
217
+ // 12. Check if the package is already installed
218
+ if(Mage::getResourceModel('cem/packages')->packageIsInstalled($packageIdentifier)) {
219
+ // Get package
220
+ $package = $this->getCollection()
221
+ ->setIdentifierFilter($packageIdentifier)
222
+ ->getFirstItem();
223
+
224
+ // Save auto update option
225
+ $this->load($package->getPackageId())
226
+ ->setAutoUpdate($autoUpdate)
227
+ ->save();
228
+
229
+ // throw exception
230
+ throw new Exception(Mage::helper('cem')->__("This package is already installed"));
231
+ }
232
+
233
+ // 13. Get local download directory
234
+ if(!$dir = $this->getDownloadDirectory()) {
235
+ throw new Exception(Mage::helper('cem')->__("Unable to create / locate temp download directory. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."));
236
+ }
237
+
238
+ // 14. Make sure that the download directory is writable
239
+ if(!is_writable($dir)) {
240
+ throw new Exception(Mage::helper('cem')->__("Unable to install the requested extension. Your var/tmp directory needs to be writable. If you are not sure how to make the directory writable we suggest that you contact your webadministrator for technical support."));
241
+ }
242
+
243
+ // 15. Save package information if package doesn't exists
244
+ if(empty($updatePackageId)) {
245
+ $this->setLicenseId($licenseModel->getLicenseId())
246
+ ->setServiceId($serviceModel->getServiceId())
247
+ ->setIdentifier($response['identifier'])
248
+ ->setTitle($response['title'])
249
+ ->setAutoUpdate($autoUpdate)
250
+ ->setModuleId($response['module_id'])
251
+ ->setVersion($response['version'])
252
+ ->save();
253
+ }
254
+
255
+ // 16. Download remote package
256
+ $file = file_get_contents($response['url']);
257
+
258
+ $tmpFile = $dir . DS . $packageIdentifier . '.tar.gz';
259
+
260
+ if($fp = fopen($tmpFile,'w')) {
261
+ fwrite($fp,$file);
262
+ }
263
+ else {
264
+ throw new Exception(Mage::helper('cem')->__("An error occurred while completing the download of the source package file. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."));
265
+ }
266
+
267
+ fclose($fp);
268
+
269
+ // 17. Install downloaded package
270
+
271
+ // Make sure the PEAR class exists, otherwise we can't extract nothing
272
+ if(!@class_exists("PEAR")) {
273
+ throw new Exception(Mage::helper('cem')->__("PEAR has not been loaded. Unable to extract installation file."));
274
+ }
275
+
276
+ // Make sure the Archive_Tar class exists, otherwise we can't extract nothing
277
+ if(!@class_exists("Archive_Tar")) {
278
+ throw new Exception(Mage::helper('cem')->__("Archive_Tar has not been loaded. Unable to extract installation file."));
279
+ }
280
+
281
+ if($tar = new Archive_Tar($tmpFile,true)) {
282
+ if(!$tar->extract(Mage::getBaseDir('base'))) {
283
+ throw new Exception(Mage::helper('cem')->__("Unable to install package. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."));
284
+ }
285
+ }
286
+ else {
287
+ throw new Exception(Mage::helper('cem')->__("Unable to install package. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."));
288
+ }
289
+
290
+ // 18. Update package information if it already exists
291
+ if(!empty($updatePackageId)) {
292
+ $packageModel = $this->load($updatePackageId);
293
+ $packageModel->setTitle($response['title'])
294
+ ->setIdentifierRollback($packageModel->getIdentifier())
295
+ ->setIdentifier($response['identifier'])
296
+ ->setVersion($response['version'])
297
+ ->setAutoUpdate($autoUpdate)
298
+ ->setUpdateAvailable(0)
299
+ ->setLastUpdate(date("Y-m-d H:i:s",time()))
300
+ ->save();
301
+ }
302
+
303
+ // 19. Report the successfull installation to the repository
304
+ $installCompleted = Mage::getModel('cem/soap')->call(
305
+ 'installCompleted',
306
+ array(
307
+ 'licenseKey' => $licenseKey
308
+ ),
309
+ $serviceUrl
310
+ );
311
+
312
+ // 20. Clear the cache
313
+ if(!Mage::app()->cleanCache()) {
314
+ throw new Exception(Mage::helper('cem')->__("Unable to refresh cache, please refresh the cache manually."));
315
+ }
316
+
317
+ // 21. Delete local install file
318
+ if(!@unlink($tmpFile)) {
319
+ throw new Exception(Mage::helper('cem')->__("The installation was successfull but unable to cleanup installation files. Please make sure that your Magento directory has read and write permissions to avoid this problem in the future."));
320
+ }
321
+
322
+ // 22. Installation complete
323
+ return true;
324
+ }
325
+ }
326
+ catch (Exception $e) {
327
+ // Clean the database tables
328
+ if($newLicenseKey) {
329
+ $licenseModel->delete();
330
+ }
331
+
332
+ // Clean the database tables
333
+ /*if($newService) {
334
+ $serviceModel->delete();
335
+ }*/
336
+
337
+ // Delete temporary downloaded file if any
338
+ if(!empty($tmpFile)) {
339
+ @unlink($tmpFile);
340
+ }
341
+
342
+ // Error
343
+ Mage::unregister('cem_error');
344
+ Mage::register('cem_error',$e->getMessage());
345
+ return;
346
+ }
347
+ }
348
+
349
+
350
+ /**
351
+ * Get information on the latest package in a module
352
+ *
353
+ * @param string $serviceUrl
354
+ * @param int $moduleId
355
+ * @return array
356
+ */
357
+ public function getLatestVersion( $serviceUrl, $moduleId )
358
+ {
359
+ try {
360
+ // Retrieve package information from service repository
361
+ $call = Mage::getModel('cem/soap')->call(
362
+ 'getLatestVersion',
363
+ array(
364
+ 'moduleId' => $moduleId
365
+ ),
366
+ $serviceUrl
367
+ );
368
+
369
+ $response = $call->getResults();
370
+
371
+ // Check for soap errors
372
+ if(is_null($response)) {
373
+ if(trim($call->getErrorMessage())=='') {
374
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while gathering module information. Please contact your retailer for assistance."));
375
+ }
376
+ throw new Exception(Mage::helper('cem')->__($call->getErrorMessage()));
377
+ }
378
+
379
+ return $response[0];
380
+ }
381
+ catch (Exception $e) {
382
+ // Error
383
+ Mage::unregister('cem_error');
384
+ Mage::register('cem_error',$e->getMessage());
385
+ return;
386
+ }
387
+ }
388
+
389
+
390
+ /**
391
+ * Get download directory path
392
+ *
393
+ * @return string
394
+ */
395
+ public function getDownloadDirectory()
396
+ {
397
+ if(is_null($this->_downloadDir)) {
398
+ // Dir
399
+ $dir = Mage::getBaseDir('base') . DS . 'var/tmp';
400
+
401
+ // Does dir exist
402
+ if(!is_dir($dir)) {
403
+ // Attempt to create it
404
+ mkdir($dir,0777);
405
+ }
406
+
407
+ $this->_downloadDir = $dir;
408
+ }
409
+
410
+ return $this->_downloadDir;
411
+ }
412
+
413
+
414
+ /**
415
+ * Set package id
416
+ *
417
+ * @param int $packageId
418
+ * @param boolean $updates
419
+ */
420
+ public function hasUpdates( $packageId, $updates )
421
+ {
422
+ Mage::getModel('cem/packages')
423
+ ->load($packageId)
424
+ ->setUpdateAvailable($updates)
425
+ ->save();
426
+ }
427
+
428
+
429
+ /**
430
+ * Update a list of packages
431
+ *
432
+ * @param Easy_CEM_Model_Mysql4_Packages_Collection $collection
433
+ * @param boolean $force
434
+ * @return int $packagesUpToDate
435
+ */
436
+ public function update( Easy_CEM_Model_Mysql4_Packages_Collection $collection, $force=false )
437
+ {
438
+ $packagesUpToDate = 0;
439
+
440
+ foreach ($collection as $p) {
441
+ $latest = $this->getLatestVersion($p->getUrl(),$p->getModuleId());
442
+
443
+ if($latest['version'] > $p->getVersion()) {
444
+ if($p->getAutoUpdate() || $force) {
445
+ if($this->install($latest['identifier'],$p->getLicenseKey(),$p->getUrl(),$p->getAutoUpdate(),$p->getPackageId())) {
446
+ $packagesUpToDate++;
447
+ }
448
+ else {
449
+ $this->hasUpdates($p->getPackageId(),true);
450
+ $packagesUpToDate++;
451
+ }
452
+ }
453
+ else {
454
+ $this->hasUpdates($p->getPackageId(),true);
455
+ $packagesUpToDate++;
456
+ }
457
+ }
458
+ }
459
+
460
+ return $packagesUpToDate;
461
+ }
462
+
463
+
464
+ /**
465
+ * Check if there is a CEM email in the config already
466
+ */
467
+ public function checkCemEmail()
468
+ {
469
+ $email = Mage::getStoreConfig('system/cem/email');
470
+
471
+ if(!empty($email)) {
472
+ return true;
473
+ }
474
+ else {
475
+ return false;
476
+ }
477
+ }
478
+
479
+ }
app/code/community/Easy/CEM/Model/Services.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_Services extends Mage_Core_Model_Abstract
22
+ {
23
+
24
+ /**
25
+ * Constructor
26
+ */
27
+ protected function _construct()
28
+ {
29
+ $this->_init('cem/services');
30
+ }
31
+
32
+ }
app/code/community/Easy/CEM/Model/Soap.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * Make sure that WSDL files aren't cached to avoid problems.
23
+ */
24
+ ini_set("soap.wsdl_cache_enabled","0");
25
+
26
+ /**
27
+ * Lets load the NuSOAP library
28
+ */
29
+ require_once('Soap/nusoap.php');
30
+
31
+ class Easy_CEM_Model_Soap extends Mage_Core_Model_Abstract
32
+ {
33
+
34
+ /**
35
+ * WSDL URL
36
+ *
37
+ * @param string
38
+ */
39
+ private $_wsdlUrl = '';
40
+
41
+
42
+ /**
43
+ * Results from SOAP call
44
+ *
45
+ * @var string
46
+ */
47
+ private $_results = null;
48
+
49
+
50
+ /**
51
+ * Error message from SOAP call
52
+ *
53
+ * @var unknown_type
54
+ */
55
+ private $_error = '';
56
+
57
+
58
+ /**
59
+ * SOAP fault
60
+ *
61
+ * @var unknown_type
62
+ */
63
+ private $_soapFault = '';
64
+
65
+
66
+
67
+ /**
68
+ * Set WSDL URL
69
+ *
70
+ * @param string $wsdlUrl
71
+ */
72
+ public function setWsdlUrl( $wsdlUrl )
73
+ {
74
+ $this->_wsdlUrl = $wsdlUrl;
75
+ return $this;
76
+ }
77
+
78
+
79
+ /**
80
+ * Create a SOAP call and return results as an array
81
+ *
82
+ * @param string $function
83
+ * @param array $params
84
+ * @param bool $verbose (true to display information about the soap call)
85
+ * @return false|array false for communication error or array if succesful
86
+ */
87
+ public function call( $function, $params, $wsdlUrl='' )
88
+ {
89
+ // Reset old value, to avoid confusion
90
+ $this->_results = '';
91
+ $this->_error = '';
92
+ $this->_soapFault = '';
93
+
94
+ // If no service URL was provided, try taking the one from the global variable
95
+ $wsdlUrl = empty($wsdlUrl) ? $this->_wsdlUrl : $wsdlUrl;
96
+
97
+ // We need a service URL to initiate a call
98
+ if(empty($wsdlUrl)) {
99
+ $this->_error = "No service URL provided. Please contact your softare retailer for assistance";
100
+ }
101
+ else {
102
+ // Create client - server connection
103
+ $client = new nusoap_client($wsdlUrl,'wsdl');
104
+
105
+ // Execute requested SOAP call
106
+ $results = $client->call($function, $params);
107
+
108
+ // Set reuslts
109
+ $this->_results = (!$client->getError() && !$client->faultstring) ? $results : null;
110
+
111
+ // Set error messages
112
+ $this->_error = $client->getError();
113
+ $this->_soapFault = $client->faultstring;
114
+ }
115
+
116
+ // Return this object
117
+ return $this;
118
+ }
119
+
120
+
121
+ /**
122
+ * Return error message
123
+ *
124
+ * @return array
125
+ */
126
+ public function getErrorMessage()
127
+ {
128
+ // Check if there was any SOAP fault (error message from the service)
129
+ if(trim($this->_soapFault)!='') {
130
+ return $this->_soapFault;
131
+ }
132
+
133
+ // Check if there was any error while processing the SOAP call
134
+ if(trim($this->_error)!='') {
135
+ return $this->_error;
136
+ }
137
+
138
+ // There was no errors
139
+ return false;
140
+ }
141
+
142
+
143
+ /**
144
+ * Get results
145
+ *
146
+ * @return string
147
+ */
148
+ public function getResults()
149
+ {
150
+ return $this->_results;
151
+ }
152
+
153
+ }
154
+
155
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.nusoap_base.php ADDED
@@ -0,0 +1,984 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ $Id: class.nusoap_base.php,v 1.51 2007/11/06 15:17:46 snichol Exp $
5
+
6
+ NuSOAP - Web Services Toolkit for PHP
7
+
8
+ Copyright (c) 2002 NuSphere Corporation
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General Public
21
+ License along with this library; if not, write to the Free Software
22
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
+
24
+ The NuSOAP project home is:
25
+ http://sourceforge.net/projects/nusoap/
26
+
27
+ The primary support for NuSOAP is the mailing list:
28
+ nusoap-general@lists.sourceforge.net
29
+
30
+ If you have any questions or comments, please email:
31
+
32
+ Dietrich Ayala
33
+ dietrich@ganx4.com
34
+ http://dietrich.ganx4.com/nusoap
35
+
36
+ NuSphere Corporation
37
+ http://www.nusphere.com
38
+
39
+ */
40
+
41
+ /*
42
+ * Some of the standards implmented in whole or part by NuSOAP:
43
+ *
44
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
45
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
46
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
47
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
48
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
49
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
50
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
51
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
52
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
53
+ */
54
+
55
+ /* load classes
56
+
57
+ // necessary classes
58
+ require_once('class.soapclient.php');
59
+ require_once('class.soap_val.php');
60
+ require_once('class.soap_parser.php');
61
+ require_once('class.soap_fault.php');
62
+
63
+ // transport classes
64
+ require_once('class.soap_transport_http.php');
65
+
66
+ // optional add-on classes
67
+ require_once('class.xmlschema.php');
68
+ require_once('class.wsdl.php');
69
+
70
+ // server class
71
+ require_once('class.soap_server.php');*/
72
+
73
+ // class variable emulation
74
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
75
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
76
+
77
+ /**
78
+ *
79
+ * nusoap_base
80
+ *
81
+ * @author Dietrich Ayala <dietrich@ganx4.com>
82
+ * @author Scott Nichol <snichol@users.sourceforge.net>
83
+ * @version $Id: class.nusoap_base.php,v 1.51 2007/11/06 15:17:46 snichol Exp $
84
+ * @access public
85
+ */
86
+ class nusoap_base {
87
+ /**
88
+ * Identification for HTTP headers.
89
+ *
90
+ * @var string
91
+ * @access private
92
+ */
93
+ var $title = 'NuSOAP';
94
+ /**
95
+ * Version for HTTP headers.
96
+ *
97
+ * @var string
98
+ * @access private
99
+ */
100
+ var $version = '0.7.3';
101
+ /**
102
+ * CVS revision for HTTP headers.
103
+ *
104
+ * @var string
105
+ * @access private
106
+ */
107
+ var $revision = '$Revision: 1.51 $';
108
+ /**
109
+ * Current error string (manipulated by getError/setError)
110
+ *
111
+ * @var string
112
+ * @access private
113
+ */
114
+ var $error_str = '';
115
+ /**
116
+ * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
117
+ *
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $debug_str = '';
122
+ /**
123
+ * toggles automatic encoding of special characters as entities
124
+ * (should always be true, I think)
125
+ *
126
+ * @var boolean
127
+ * @access private
128
+ */
129
+ var $charencoding = true;
130
+ /**
131
+ * the debug level for this instance
132
+ *
133
+ * @var integer
134
+ * @access private
135
+ */
136
+ var $debugLevel;
137
+
138
+ /**
139
+ * set schema version
140
+ *
141
+ * @var string
142
+ * @access public
143
+ */
144
+ var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
145
+
146
+ /**
147
+ * charset encoding for outgoing messages
148
+ *
149
+ * @var string
150
+ * @access public
151
+ */
152
+ var $soap_defencoding = 'ISO-8859-1';
153
+ //var $soap_defencoding = 'UTF-8';
154
+
155
+ /**
156
+ * namespaces in an array of prefix => uri
157
+ *
158
+ * this is "seeded" by a set of constants, but it may be altered by code
159
+ *
160
+ * @var array
161
+ * @access public
162
+ */
163
+ var $namespaces = array(
164
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
165
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
166
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
167
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
168
+ );
169
+
170
+ /**
171
+ * namespaces used in the current context, e.g. during serialization
172
+ *
173
+ * @var array
174
+ * @access private
175
+ */
176
+ var $usedNamespaces = array();
177
+
178
+ /**
179
+ * XML Schema types in an array of uri => (array of xml type => php type)
180
+ * is this legacy yet?
181
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
182
+ * @var array
183
+ * @access public
184
+ */
185
+ var $typemap = array(
186
+ 'http://www.w3.org/2001/XMLSchema' => array(
187
+ 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
188
+ 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
189
+ 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
190
+ // abstract "any" types
191
+ 'anyType'=>'string','anySimpleType'=>'string',
192
+ // derived datatypes
193
+ 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
194
+ 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
195
+ 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
196
+ 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
197
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
198
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
199
+ 'float'=>'double','dateTime'=>'string',
200
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
201
+ 'http://www.w3.org/1999/XMLSchema' => array(
202
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
203
+ 'float'=>'double','dateTime'=>'string',
204
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
205
+ 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
206
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
207
+ 'http://xml.apache.org/xml-soap' => array('Map')
208
+ );
209
+
210
+ /**
211
+ * XML entities to convert
212
+ *
213
+ * @var array
214
+ * @access public
215
+ * @deprecated
216
+ * @see expandEntities
217
+ */
218
+ var $xmlEntities = array('quot' => '"','amp' => '&',
219
+ 'lt' => '<','gt' => '>','apos' => "'");
220
+
221
+ /**
222
+ * constructor
223
+ *
224
+ * @access public
225
+ */
226
+ function nusoap_base() {
227
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
228
+ }
229
+
230
+ /**
231
+ * gets the global debug level, which applies to future instances
232
+ *
233
+ * @return integer Debug level 0-9, where 0 turns off
234
+ * @access public
235
+ */
236
+ function getGlobalDebugLevel() {
237
+ return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
238
+ }
239
+
240
+ /**
241
+ * sets the global debug level, which applies to future instances
242
+ *
243
+ * @param int $level Debug level 0-9, where 0 turns off
244
+ * @access public
245
+ */
246
+ function setGlobalDebugLevel($level) {
247
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
248
+ }
249
+
250
+ /**
251
+ * gets the debug level for this instance
252
+ *
253
+ * @return int Debug level 0-9, where 0 turns off
254
+ * @access public
255
+ */
256
+ function getDebugLevel() {
257
+ return $this->debugLevel;
258
+ }
259
+
260
+ /**
261
+ * sets the debug level for this instance
262
+ *
263
+ * @param int $level Debug level 0-9, where 0 turns off
264
+ * @access public
265
+ */
266
+ function setDebugLevel($level) {
267
+ $this->debugLevel = $level;
268
+ }
269
+
270
+ /**
271
+ * adds debug data to the instance debug string with formatting
272
+ *
273
+ * @param string $string debug data
274
+ * @access private
275
+ */
276
+ function debug($string){
277
+ if ($this->debugLevel > 0) {
278
+ $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
279
+ }
280
+ }
281
+
282
+ /**
283
+ * adds debug data to the instance debug string without formatting
284
+ *
285
+ * @param string $string debug data
286
+ * @access public
287
+ */
288
+ function appendDebug($string){
289
+ if ($this->debugLevel > 0) {
290
+ // it would be nice to use a memory stream here to use
291
+ // memory more efficiently
292
+ $this->debug_str .= $string;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * clears the current debug data for this instance
298
+ *
299
+ * @access public
300
+ */
301
+ function clearDebug() {
302
+ // it would be nice to use a memory stream here to use
303
+ // memory more efficiently
304
+ $this->debug_str = '';
305
+ }
306
+
307
+ /**
308
+ * gets the current debug data for this instance
309
+ *
310
+ * @return debug data
311
+ * @access public
312
+ */
313
+ function &getDebug() {
314
+ // it would be nice to use a memory stream here to use
315
+ // memory more efficiently
316
+ return $this->debug_str;
317
+ }
318
+
319
+ /**
320
+ * gets the current debug data for this instance as an XML comment
321
+ * this may change the contents of the debug data
322
+ *
323
+ * @return debug data as an XML comment
324
+ * @access public
325
+ */
326
+ function &getDebugAsXMLComment() {
327
+ // it would be nice to use a memory stream here to use
328
+ // memory more efficiently
329
+ while (strpos($this->debug_str, '--')) {
330
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
331
+ }
332
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
333
+ return $ret;
334
+ }
335
+
336
+ /**
337
+ * expands entities, e.g. changes '<' to '&lt;'.
338
+ *
339
+ * @param string $val The string in which to expand entities.
340
+ * @access private
341
+ */
342
+ function expandEntities($val) {
343
+ if ($this->charencoding) {
344
+ $val = str_replace('&', '&amp;', $val);
345
+ $val = str_replace("'", '&apos;', $val);
346
+ $val = str_replace('"', '&quot;', $val);
347
+ $val = str_replace('<', '&lt;', $val);
348
+ $val = str_replace('>', '&gt;', $val);
349
+ }
350
+ return $val;
351
+ }
352
+
353
+ /**
354
+ * returns error string if present
355
+ *
356
+ * @return mixed error string or false
357
+ * @access public
358
+ */
359
+ function getError(){
360
+ if($this->error_str != ''){
361
+ return $this->error_str;
362
+ }
363
+ return false;
364
+ }
365
+
366
+ /**
367
+ * sets error string
368
+ *
369
+ * @return boolean $string error string
370
+ * @access private
371
+ */
372
+ function setError($str){
373
+ $this->error_str = $str;
374
+ }
375
+
376
+ /**
377
+ * detect if array is a simple array or a struct (associative array)
378
+ *
379
+ * @param mixed $val The PHP array
380
+ * @return string (arraySimple|arrayStruct)
381
+ * @access private
382
+ */
383
+ function isArraySimpleOrStruct($val) {
384
+ $keyList = array_keys($val);
385
+ foreach ($keyList as $keyListValue) {
386
+ if (!is_int($keyListValue)) {
387
+ return 'arrayStruct';
388
+ }
389
+ }
390
+ return 'arraySimple';
391
+ }
392
+
393
+ /**
394
+ * serializes PHP values in accordance w/ section 5. Type information is
395
+ * not serialized if $use == 'literal'.
396
+ *
397
+ * @param mixed $val The value to serialize
398
+ * @param string $name The name (local part) of the XML element
399
+ * @param string $type The XML schema type (local part) for the element
400
+ * @param string $name_ns The namespace for the name of the XML element
401
+ * @param string $type_ns The namespace for the type of the element
402
+ * @param array $attributes The attributes to serialize as name=>value pairs
403
+ * @param string $use The WSDL "use" (encoded|literal)
404
+ * @param boolean $soapval Whether this is called from soapval.
405
+ * @return string The serialized element, possibly with child elements
406
+ * @access public
407
+ */
408
+ function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
409
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
410
+ $this->appendDebug('value=' . $this->varDump($val));
411
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
412
+
413
+ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
414
+ $this->debug("serialize_val: serialize soapval");
415
+ $xml = $val->serialize($use);
416
+ $this->appendDebug($val->getDebug());
417
+ $val->clearDebug();
418
+ $this->debug("serialize_val of soapval returning $xml");
419
+ return $xml;
420
+ }
421
+ // force valid name if necessary
422
+ if (is_numeric($name)) {
423
+ $name = '__numeric_' . $name;
424
+ } elseif (! $name) {
425
+ $name = 'noname';
426
+ }
427
+ // if name has ns, add ns prefix to name
428
+ $xmlns = '';
429
+ if($name_ns){
430
+ $prefix = 'nu'.rand(1000,9999);
431
+ $name = $prefix.':'.$name;
432
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
433
+ }
434
+ // if type is prefixed, create type prefix
435
+ if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
436
+ // need to fix this. shouldn't default to xsd if no ns specified
437
+ // w/o checking against typemap
438
+ $type_prefix = 'xsd';
439
+ } elseif($type_ns){
440
+ $type_prefix = 'ns'.rand(1000,9999);
441
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
442
+ }
443
+ // serialize attributes if present
444
+ $atts = '';
445
+ if($attributes){
446
+ foreach($attributes as $k => $v){
447
+ $atts .= " $k=\"".$this->expandEntities($v).'"';
448
+ }
449
+ }
450
+ // serialize null value
451
+ if (is_null($val)) {
452
+ $this->debug("serialize_val: serialize null");
453
+ if ($use == 'literal') {
454
+ // TODO: depends on minOccurs
455
+ $xml = "<$name$xmlns$atts/>";
456
+ $this->debug("serialize_val returning $xml");
457
+ return $xml;
458
+ } else {
459
+ if (isset($type) && isset($type_prefix)) {
460
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
461
+ } else {
462
+ $type_str = '';
463
+ }
464
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
465
+ $this->debug("serialize_val returning $xml");
466
+ return $xml;
467
+ }
468
+ }
469
+ // serialize if an xsd built-in primitive type
470
+ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
471
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
472
+ if (is_bool($val)) {
473
+ if ($type == 'boolean') {
474
+ $val = $val ? 'true' : 'false';
475
+ } elseif (! $val) {
476
+ $val = 0;
477
+ }
478
+ } else if (is_string($val)) {
479
+ $val = $this->expandEntities($val);
480
+ }
481
+ if ($use == 'literal') {
482
+ $xml = "<$name$xmlns$atts>$val</$name>";
483
+ $this->debug("serialize_val returning $xml");
484
+ return $xml;
485
+ } else {
486
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
487
+ $this->debug("serialize_val returning $xml");
488
+ return $xml;
489
+ }
490
+ }
491
+ // detect type and serialize
492
+ $xml = '';
493
+ switch(true) {
494
+ case (is_bool($val) || $type == 'boolean'):
495
+ $this->debug("serialize_val: serialize boolean");
496
+ if ($type == 'boolean') {
497
+ $val = $val ? 'true' : 'false';
498
+ } elseif (! $val) {
499
+ $val = 0;
500
+ }
501
+ if ($use == 'literal') {
502
+ $xml .= "<$name$xmlns$atts>$val</$name>";
503
+ } else {
504
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
505
+ }
506
+ break;
507
+ case (is_int($val) || is_long($val) || $type == 'int'):
508
+ $this->debug("serialize_val: serialize int");
509
+ if ($use == 'literal') {
510
+ $xml .= "<$name$xmlns$atts>$val</$name>";
511
+ } else {
512
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
513
+ }
514
+ break;
515
+ case (is_float($val)|| is_double($val) || $type == 'float'):
516
+ $this->debug("serialize_val: serialize float");
517
+ if ($use == 'literal') {
518
+ $xml .= "<$name$xmlns$atts>$val</$name>";
519
+ } else {
520
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
521
+ }
522
+ break;
523
+ case (is_string($val) || $type == 'string'):
524
+ $this->debug("serialize_val: serialize string");
525
+ $val = $this->expandEntities($val);
526
+ if ($use == 'literal') {
527
+ $xml .= "<$name$xmlns$atts>$val</$name>";
528
+ } else {
529
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
530
+ }
531
+ break;
532
+ case is_object($val):
533
+ $this->debug("serialize_val: serialize object");
534
+ if (get_class($val) == 'soapval') {
535
+ $this->debug("serialize_val: serialize soapval object");
536
+ $pXml = $val->serialize($use);
537
+ $this->appendDebug($val->getDebug());
538
+ $val->clearDebug();
539
+ } else {
540
+ if (! $name) {
541
+ $name = get_class($val);
542
+ $this->debug("In serialize_val, used class name $name as element name");
543
+ } else {
544
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
545
+ }
546
+ foreach(get_object_vars($val) as $k => $v){
547
+ $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
548
+ }
549
+ }
550
+ if(isset($type) && isset($type_prefix)){
551
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
552
+ } else {
553
+ $type_str = '';
554
+ }
555
+ if ($use == 'literal') {
556
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
557
+ } else {
558
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
559
+ }
560
+ break;
561
+ break;
562
+ case (is_array($val) || $type):
563
+ // detect if struct or array
564
+ $valueType = $this->isArraySimpleOrStruct($val);
565
+ if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
566
+ $this->debug("serialize_val: serialize array");
567
+ $i = 0;
568
+ if(is_array($val) && count($val)> 0){
569
+ foreach($val as $v){
570
+ if(is_object($v) && get_class($v) == 'soapval'){
571
+ $tt_ns = $v->type_ns;
572
+ $tt = $v->type;
573
+ } elseif (is_array($v)) {
574
+ $tt = $this->isArraySimpleOrStruct($v);
575
+ } else {
576
+ $tt = gettype($v);
577
+ }
578
+ $array_types[$tt] = 1;
579
+ // TODO: for literal, the name should be $name
580
+ $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
581
+ ++$i;
582
+ }
583
+ if(count($array_types) > 1){
584
+ $array_typename = 'xsd:anyType';
585
+ } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
586
+ if ($tt == 'integer') {
587
+ $tt = 'int';
588
+ }
589
+ $array_typename = 'xsd:'.$tt;
590
+ } elseif(isset($tt) && $tt == 'arraySimple'){
591
+ $array_typename = 'SOAP-ENC:Array';
592
+ } elseif(isset($tt) && $tt == 'arrayStruct'){
593
+ $array_typename = 'unnamed_struct_use_soapval';
594
+ } else {
595
+ // if type is prefixed, create type prefix
596
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
597
+ $array_typename = 'xsd:' . $tt;
598
+ } elseif ($tt_ns) {
599
+ $tt_prefix = 'ns' . rand(1000, 9999);
600
+ $array_typename = "$tt_prefix:$tt";
601
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
602
+ } else {
603
+ $array_typename = $tt;
604
+ }
605
+ }
606
+ $array_type = $i;
607
+ if ($use == 'literal') {
608
+ $type_str = '';
609
+ } else if (isset($type) && isset($type_prefix)) {
610
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
611
+ } else {
612
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
613
+ }
614
+ // empty array
615
+ } else {
616
+ if ($use == 'literal') {
617
+ $type_str = '';
618
+ } else if (isset($type) && isset($type_prefix)) {
619
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
620
+ } else {
621
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
622
+ }
623
+ }
624
+ // TODO: for array in literal, there is no wrapper here
625
+ $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
626
+ } else {
627
+ // got a struct
628
+ $this->debug("serialize_val: serialize struct");
629
+ if(isset($type) && isset($type_prefix)){
630
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
631
+ } else {
632
+ $type_str = '';
633
+ }
634
+ if ($use == 'literal') {
635
+ $xml .= "<$name$xmlns$atts>";
636
+ } else {
637
+ $xml .= "<$name$xmlns$type_str$atts>";
638
+ }
639
+ foreach($val as $k => $v){
640
+ // Apache Map
641
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
642
+ $xml .= '<item>';
643
+ $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
644
+ $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
645
+ $xml .= '</item>';
646
+ } else {
647
+ $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
648
+ }
649
+ }
650
+ $xml .= "</$name>";
651
+ }
652
+ break;
653
+ default:
654
+ $this->debug("serialize_val: serialize unknown");
655
+ $xml .= 'not detected, got '.gettype($val).' for '.$val;
656
+ break;
657
+ }
658
+ $this->debug("serialize_val returning $xml");
659
+ return $xml;
660
+ }
661
+
662
+ /**
663
+ * serializes a message
664
+ *
665
+ * @param string $body the XML of the SOAP body
666
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
667
+ * @param array $namespaces optional the namespaces used in generating the body and headers
668
+ * @param string $style optional (rpc|document)
669
+ * @param string $use optional (encoded|literal)
670
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
671
+ * @return string the message
672
+ * @access public
673
+ */
674
+ function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
675
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
676
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
677
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
678
+
679
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
680
+ $this->debug("headers:");
681
+ $this->appendDebug($this->varDump($headers));
682
+ $this->debug("namespaces:");
683
+ $this->appendDebug($this->varDump($namespaces));
684
+
685
+ // serialize namespaces
686
+ $ns_string = '';
687
+ foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
688
+ $ns_string .= " xmlns:$k=\"$v\"";
689
+ }
690
+ if($encodingStyle) {
691
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
692
+ }
693
+
694
+ // serialize headers
695
+ if($headers){
696
+ if (is_array($headers)) {
697
+ $xml = '';
698
+ foreach ($headers as $k => $v) {
699
+ if (is_object($v) && get_class($v) == 'soapval') {
700
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
701
+ } else {
702
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
703
+ }
704
+ }
705
+ $headers = $xml;
706
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
707
+ }
708
+ $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
709
+ }
710
+ // serialize envelope
711
+ return
712
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
713
+ '<SOAP-ENV:Envelope'.$ns_string.">".
714
+ $headers.
715
+ "<SOAP-ENV:Body>".
716
+ $body.
717
+ "</SOAP-ENV:Body>".
718
+ "</SOAP-ENV:Envelope>";
719
+ }
720
+
721
+ /**
722
+ * formats a string to be inserted into an HTML stream
723
+ *
724
+ * @param string $str The string to format
725
+ * @return string The formatted string
726
+ * @access public
727
+ * @deprecated
728
+ */
729
+ function formatDump($str){
730
+ $str = htmlspecialchars($str);
731
+ return nl2br($str);
732
+ }
733
+
734
+ /**
735
+ * contracts (changes namespace to prefix) a qualified name
736
+ *
737
+ * @param string $qname qname
738
+ * @return string contracted qname
739
+ * @access private
740
+ */
741
+ function contractQname($qname){
742
+ // get element namespace
743
+ //$this->xdebug("Contract $qname");
744
+ if (strrpos($qname, ':')) {
745
+ // get unqualified name
746
+ $name = substr($qname, strrpos($qname, ':') + 1);
747
+ // get ns
748
+ $ns = substr($qname, 0, strrpos($qname, ':'));
749
+ $p = $this->getPrefixFromNamespace($ns);
750
+ if ($p) {
751
+ return $p . ':' . $name;
752
+ }
753
+ return $qname;
754
+ } else {
755
+ return $qname;
756
+ }
757
+ }
758
+
759
+ /**
760
+ * expands (changes prefix to namespace) a qualified name
761
+ *
762
+ * @param string $qname qname
763
+ * @return string expanded qname
764
+ * @access private
765
+ */
766
+ function expandQname($qname){
767
+ // get element prefix
768
+ if(strpos($qname,':') && !ereg('^http://',$qname)){
769
+ // get unqualified name
770
+ $name = substr(strstr($qname,':'),1);
771
+ // get ns prefix
772
+ $prefix = substr($qname,0,strpos($qname,':'));
773
+ if(isset($this->namespaces[$prefix])){
774
+ return $this->namespaces[$prefix].':'.$name;
775
+ } else {
776
+ return $qname;
777
+ }
778
+ } else {
779
+ return $qname;
780
+ }
781
+ }
782
+
783
+ /**
784
+ * returns the local part of a prefixed string
785
+ * returns the original string, if not prefixed
786
+ *
787
+ * @param string $str The prefixed string
788
+ * @return string The local part
789
+ * @access public
790
+ */
791
+ function getLocalPart($str){
792
+ if($sstr = strrchr($str,':')){
793
+ // get unqualified name
794
+ return substr( $sstr, 1 );
795
+ } else {
796
+ return $str;
797
+ }
798
+ }
799
+
800
+ /**
801
+ * returns the prefix part of a prefixed string
802
+ * returns false, if not prefixed
803
+ *
804
+ * @param string $str The prefixed string
805
+ * @return mixed The prefix or false if there is no prefix
806
+ * @access public
807
+ */
808
+ function getPrefix($str){
809
+ if($pos = strrpos($str,':')){
810
+ // get prefix
811
+ return substr($str,0,$pos);
812
+ }
813
+ return false;
814
+ }
815
+
816
+ /**
817
+ * pass it a prefix, it returns a namespace
818
+ *
819
+ * @param string $prefix The prefix
820
+ * @return mixed The namespace, false if no namespace has the specified prefix
821
+ * @access public
822
+ */
823
+ function getNamespaceFromPrefix($prefix){
824
+ if (isset($this->namespaces[$prefix])) {
825
+ return $this->namespaces[$prefix];
826
+ }
827
+ //$this->setError("No namespace registered for prefix '$prefix'");
828
+ return false;
829
+ }
830
+
831
+ /**
832
+ * returns the prefix for a given namespace (or prefix)
833
+ * or false if no prefixes registered for the given namespace
834
+ *
835
+ * @param string $ns The namespace
836
+ * @return mixed The prefix, false if the namespace has no prefixes
837
+ * @access public
838
+ */
839
+ function getPrefixFromNamespace($ns) {
840
+ foreach ($this->namespaces as $p => $n) {
841
+ if ($ns == $n || $ns == $p) {
842
+ $this->usedNamespaces[$p] = $n;
843
+ return $p;
844
+ }
845
+ }
846
+ return false;
847
+ }
848
+
849
+ /**
850
+ * returns the time in ODBC canonical form with microseconds
851
+ *
852
+ * @return string The time in ODBC canonical form with microseconds
853
+ * @access public
854
+ */
855
+ function getmicrotime() {
856
+ if (function_exists('gettimeofday')) {
857
+ $tod = gettimeofday();
858
+ $sec = $tod['sec'];
859
+ $usec = $tod['usec'];
860
+ } else {
861
+ $sec = time();
862
+ $usec = 0;
863
+ }
864
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
865
+ }
866
+
867
+ /**
868
+ * Returns a string with the output of var_dump
869
+ *
870
+ * @param mixed $data The variable to var_dump
871
+ * @return string The output of var_dump
872
+ * @access public
873
+ */
874
+ function varDump($data) {
875
+ ob_start();
876
+ var_dump($data);
877
+ $ret_val = ob_get_contents();
878
+ ob_end_clean();
879
+ return $ret_val;
880
+ }
881
+
882
+ /**
883
+ * represents the object as a string
884
+ *
885
+ * @return string
886
+ * @access public
887
+ */
888
+ function __toString() {
889
+ return $this->varDump($this);
890
+ }
891
+ }
892
+
893
+ // XML Schema Datatype Helper Functions
894
+
895
+ //xsd:dateTime helpers
896
+
897
+ /**
898
+ * convert unix timestamp to ISO 8601 compliant date string
899
+ *
900
+ * @param string $timestamp Unix time stamp
901
+ * @param boolean $utc Whether the time stamp is UTC or local
902
+ * @access public
903
+ */
904
+ function timestamp_to_iso8601($timestamp,$utc=true){
905
+ $datestr = date('Y-m-d\TH:i:sO',$timestamp);
906
+ if($utc){
907
+ $eregStr =
908
+ '([0-9]{4})-'. // centuries & years CCYY-
909
+ '([0-9]{2})-'. // months MM-
910
+ '([0-9]{2})'. // days DD
911
+ 'T'. // separator T
912
+ '([0-9]{2}):'. // hours hh:
913
+ '([0-9]{2}):'. // minutes mm:
914
+ '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
915
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
916
+
917
+ if(ereg($eregStr,$datestr,$regs)){
918
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
919
+ }
920
+ return false;
921
+ } else {
922
+ return $datestr;
923
+ }
924
+ }
925
+
926
+ /**
927
+ * convert ISO 8601 compliant date string to unix timestamp
928
+ *
929
+ * @param string $datestr ISO 8601 compliant date string
930
+ * @access public
931
+ */
932
+ function iso8601_to_timestamp($datestr){
933
+ $eregStr =
934
+ '([0-9]{4})-'. // centuries & years CCYY-
935
+ '([0-9]{2})-'. // months MM-
936
+ '([0-9]{2})'. // days DD
937
+ 'T'. // separator T
938
+ '([0-9]{2}):'. // hours hh:
939
+ '([0-9]{2}):'. // minutes mm:
940
+ '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
941
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
942
+ if(ereg($eregStr,$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
+ }
962
+
963
+ /**
964
+ * sleeps some number of microseconds
965
+ *
966
+ * @param string $usec the number of microseconds to sleep
967
+ * @access public
968
+ * @deprecated
969
+ */
970
+ function usleepWindows($usec)
971
+ {
972
+ $start = gettimeofday();
973
+
974
+ do
975
+ {
976
+ $stop = gettimeofday();
977
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
978
+ + $stop['usec'] - $start['usec'];
979
+ }
980
+ while ($timePassed < $usec);
981
+ }
982
+
983
+
984
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soap_fault.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ * Contains information for a SOAP fault.
8
+ * Mainly used for returning faults from deployed functions
9
+ * in a server instance.
10
+ * @author Dietrich Ayala <dietrich@ganx4.com>
11
+ * @version $Id: class.soap_fault.php,v 1.14 2007/04/11 15:49:47 snichol Exp $
12
+ * @access public
13
+ */
14
+ class nusoap_fault extends nusoap_base {
15
+ /**
16
+ * The fault code (client|server)
17
+ * @var string
18
+ * @access private
19
+ */
20
+ var $faultcode;
21
+ /**
22
+ * The fault actor
23
+ * @var string
24
+ * @access private
25
+ */
26
+ var $faultactor;
27
+ /**
28
+ * The fault string, a description of the fault
29
+ * @var string
30
+ * @access private
31
+ */
32
+ var $faultstring;
33
+ /**
34
+ * The fault detail, typically a string or array of string
35
+ * @var mixed
36
+ * @access private
37
+ */
38
+ var $faultdetail;
39
+
40
+ /**
41
+ * constructor
42
+ *
43
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
44
+ * @param string $faultactor only used when msg routed between multiple actors
45
+ * @param string $faultstring human readable error message
46
+ * @param mixed $faultdetail detail, typically a string or array of string
47
+ */
48
+ function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
49
+ parent::nusoap_base();
50
+ $this->faultcode = $faultcode;
51
+ $this->faultactor = $faultactor;
52
+ $this->faultstring = $faultstring;
53
+ $this->faultdetail = $faultdetail;
54
+ }
55
+
56
+ /**
57
+ * serialize a fault
58
+ *
59
+ * @return string The serialization of the fault instance.
60
+ * @access public
61
+ */
62
+ function serialize(){
63
+ $ns_string = '';
64
+ foreach($this->namespaces as $k => $v){
65
+ $ns_string .= "\n xmlns:$k=\"$v\"";
66
+ }
67
+ $return_msg =
68
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
69
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
70
+ '<SOAP-ENV:Body>'.
71
+ '<SOAP-ENV:Fault>'.
72
+ $this->serialize_val($this->faultcode, 'faultcode').
73
+ $this->serialize_val($this->faultactor, 'faultactor').
74
+ $this->serialize_val($this->faultstring, 'faultstring').
75
+ $this->serialize_val($this->faultdetail, 'detail').
76
+ '</SOAP-ENV:Fault>'.
77
+ '</SOAP-ENV:Body>'.
78
+ '</SOAP-ENV:Envelope>';
79
+ return $return_msg;
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Backward compatibility
85
+ */
86
+ class soap_fault extends nusoap_fault {
87
+ }
88
+
89
+
90
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soap_parser.php ADDED
@@ -0,0 +1,639 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ *
8
+ * nusoap_parser class parses SOAP XML messages into native PHP values
9
+ *
10
+ * @author Dietrich Ayala <dietrich@ganx4.com>
11
+ * @author Scott Nichol <snichol@users.sourceforge.net>
12
+ * @version $Id: class.soap_parser.php,v 1.40 2007/04/17 16:34:03 snichol Exp $
13
+ * @access public
14
+ */
15
+ class nusoap_parser extends nusoap_base {
16
+
17
+ var $xml = '';
18
+ var $xml_encoding = '';
19
+ var $method = '';
20
+ var $root_struct = '';
21
+ var $root_struct_name = '';
22
+ var $root_struct_namespace = '';
23
+ var $root_header = '';
24
+ var $document = ''; // incoming SOAP body (text)
25
+ // determines where in the message we are (envelope,header,body,method)
26
+ var $status = '';
27
+ var $position = 0;
28
+ var $depth = 0;
29
+ var $default_namespace = '';
30
+ var $namespaces = array();
31
+ var $message = array();
32
+ var $parent = '';
33
+ var $fault = false;
34
+ var $fault_code = '';
35
+ var $fault_str = '';
36
+ var $fault_detail = '';
37
+ var $depth_array = array();
38
+ var $debug_flag = true;
39
+ var $soapresponse = NULL; // parsed SOAP Body
40
+ var $soapheader = NULL; // parsed SOAP Header
41
+ var $responseHeaders = ''; // incoming SOAP headers (text)
42
+ var $body_position = 0;
43
+ // for multiref parsing:
44
+ // array of id => pos
45
+ var $ids = array();
46
+ // array of id => hrefs => pos
47
+ var $multirefs = array();
48
+ // toggle for auto-decoding element content
49
+ var $decode_utf8 = true;
50
+
51
+ /**
52
+ * constructor that actually does the parsing
53
+ *
54
+ * @param string $xml SOAP message
55
+ * @param string $encoding character encoding scheme of message
56
+ * @param string $method method for which XML is parsed (unused?)
57
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
58
+ * @access public
59
+ */
60
+ function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
61
+ parent::nusoap_base();
62
+ $this->xml = $xml;
63
+ $this->xml_encoding = $encoding;
64
+ $this->method = $method;
65
+ $this->decode_utf8 = $decode_utf8;
66
+
67
+ // Check whether content has been read.
68
+ if(!empty($xml)){
69
+ // Check XML encoding
70
+ $pos_xml = strpos($xml, '<?xml');
71
+ if ($pos_xml !== FALSE) {
72
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
73
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
74
+ $xml_encoding = $res[1];
75
+ if (strtoupper($xml_encoding) != $encoding) {
76
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
77
+ $this->debug($err);
78
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
79
+ $this->setError($err);
80
+ return;
81
+ }
82
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
83
+ } else {
84
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
85
+ }
86
+ } else {
87
+ $this->debug('No encoding specified in XML declaration');
88
+ }
89
+ } else {
90
+ $this->debug('No XML declaration');
91
+ }
92
+ $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
93
+ // Create an XML parser - why not xml_parser_create_ns?
94
+ $this->parser = xml_parser_create($this->xml_encoding);
95
+ // Set the options for parsing the XML data.
96
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
97
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
98
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
99
+ // Set the object for the parser.
100
+ xml_set_object($this->parser, $this);
101
+ // Set the element handlers for the parser.
102
+ xml_set_element_handler($this->parser, 'start_element','end_element');
103
+ xml_set_character_data_handler($this->parser,'character_data');
104
+
105
+ // Parse the XML file.
106
+ if(!xml_parse($this->parser,$xml,true)){
107
+ // Display an error message.
108
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
109
+ xml_get_current_line_number($this->parser),
110
+ xml_error_string(xml_get_error_code($this->parser)));
111
+ $this->debug($err);
112
+ $this->debug("XML payload:\n" . $xml);
113
+ $this->setError($err);
114
+ } else {
115
+ $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
116
+ // get final value
117
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
118
+ // get header value
119
+ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
120
+ $this->soapheader = $this->message[$this->root_header]['result'];
121
+ }
122
+ // resolve hrefs/ids
123
+ if(sizeof($this->multirefs) > 0){
124
+ foreach($this->multirefs as $id => $hrefs){
125
+ $this->debug('resolving multirefs for id: '.$id);
126
+ $idVal = $this->buildVal($this->ids[$id]);
127
+ if (is_array($idVal) && isset($idVal['!id'])) {
128
+ unset($idVal['!id']);
129
+ }
130
+ foreach($hrefs as $refPos => $ref){
131
+ $this->debug('resolving href at pos '.$refPos);
132
+ $this->multirefs[$id][$refPos] = $idVal;
133
+ }
134
+ }
135
+ }
136
+ }
137
+ xml_parser_free($this->parser);
138
+ } else {
139
+ $this->debug('xml was empty, didn\'t parse!');
140
+ $this->setError('xml was empty, didn\'t parse!');
141
+ }
142
+ }
143
+
144
+ /**
145
+ * start-element handler
146
+ *
147
+ * @param resource $parser XML parser object
148
+ * @param string $name element name
149
+ * @param array $attrs associative array of attributes
150
+ * @access private
151
+ */
152
+ function start_element($parser, $name, $attrs) {
153
+ // position in a total number of elements, starting from 0
154
+ // update class level pos
155
+ $pos = $this->position++;
156
+ // and set mine
157
+ $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
158
+ // depth = how many levels removed from root?
159
+ // set mine as current global depth and increment global depth value
160
+ $this->message[$pos]['depth'] = $this->depth++;
161
+
162
+ // else add self as child to whoever the current parent is
163
+ if($pos != 0){
164
+ $this->message[$this->parent]['children'] .= '|'.$pos;
165
+ }
166
+ // set my parent
167
+ $this->message[$pos]['parent'] = $this->parent;
168
+ // set self as current parent
169
+ $this->parent = $pos;
170
+ // set self as current value for this depth
171
+ $this->depth_array[$this->depth] = $pos;
172
+ // get element prefix
173
+ if(strpos($name,':')){
174
+ // get ns prefix
175
+ $prefix = substr($name,0,strpos($name,':'));
176
+ // get unqualified name
177
+ $name = substr(strstr($name,':'),1);
178
+ }
179
+ // set status
180
+ if($name == 'Envelope'){
181
+ $this->status = 'envelope';
182
+ } elseif($name == 'Header' && $this->status = 'envelope'){
183
+ $this->root_header = $pos;
184
+ $this->status = 'header';
185
+ } elseif($name == 'Body' && $this->status = 'envelope'){
186
+ $this->status = 'body';
187
+ $this->body_position = $pos;
188
+ // set method
189
+ } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
190
+ $this->status = 'method';
191
+ $this->root_struct_name = $name;
192
+ $this->root_struct = $pos;
193
+ $this->message[$pos]['type'] = 'struct';
194
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
195
+ }
196
+ // set my status
197
+ $this->message[$pos]['status'] = $this->status;
198
+ // set name
199
+ $this->message[$pos]['name'] = htmlspecialchars($name);
200
+ // set attrs
201
+ $this->message[$pos]['attrs'] = $attrs;
202
+
203
+ // loop through atts, logging ns and type declarations
204
+ $attstr = '';
205
+ foreach($attrs as $key => $value){
206
+ $key_prefix = $this->getPrefix($key);
207
+ $key_localpart = $this->getLocalPart($key);
208
+ // if ns declarations, add to class level array of valid namespaces
209
+ if($key_prefix == 'xmlns'){
210
+ if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
211
+ $this->XMLSchemaVersion = $value;
212
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
213
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
214
+ }
215
+ $this->namespaces[$key_localpart] = $value;
216
+ // set method namespace
217
+ if($name == $this->root_struct_name){
218
+ $this->methodNamespace = $value;
219
+ }
220
+ // if it's a type declaration, set type
221
+ } elseif($key_localpart == 'type'){
222
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
223
+ // do nothing: already processed arrayType
224
+ } else {
225
+ $value_prefix = $this->getPrefix($value);
226
+ $value_localpart = $this->getLocalPart($value);
227
+ $this->message[$pos]['type'] = $value_localpart;
228
+ $this->message[$pos]['typePrefix'] = $value_prefix;
229
+ if(isset($this->namespaces[$value_prefix])){
230
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
231
+ } else if(isset($attrs['xmlns:'.$value_prefix])) {
232
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
233
+ }
234
+ // should do something here with the namespace of specified type?
235
+ }
236
+ } elseif($key_localpart == 'arrayType'){
237
+ $this->message[$pos]['type'] = 'array';
238
+ /* do arrayType ereg here
239
+ [1] arrayTypeValue ::= atype asize
240
+ [2] atype ::= QName rank*
241
+ [3] rank ::= '[' (',')* ']'
242
+ [4] asize ::= '[' length~ ']'
243
+ [5] length ::= nextDimension* Digit+
244
+ [6] nextDimension ::= Digit+ ','
245
+ */
246
+ $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
247
+ if(ereg($expr,$value,$regs)){
248
+ $this->message[$pos]['typePrefix'] = $regs[1];
249
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
250
+ if (isset($this->namespaces[$regs[1]])) {
251
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
252
+ } else if (isset($attrs['xmlns:'.$regs[1]])) {
253
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
254
+ }
255
+ $this->message[$pos]['arrayType'] = $regs[2];
256
+ $this->message[$pos]['arraySize'] = $regs[3];
257
+ $this->message[$pos]['arrayCols'] = $regs[4];
258
+ }
259
+ // specifies nil value (or not)
260
+ } elseif ($key_localpart == 'nil'){
261
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
262
+ // some other attribute
263
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
264
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
265
+ }
266
+
267
+ if ($key == 'xmlns') {
268
+ $this->default_namespace = $value;
269
+ }
270
+ // log id
271
+ if($key == 'id'){
272
+ $this->ids[$value] = $pos;
273
+ }
274
+ // root
275
+ if($key_localpart == 'root' && $value == 1){
276
+ $this->status = 'method';
277
+ $this->root_struct_name = $name;
278
+ $this->root_struct = $pos;
279
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
280
+ }
281
+ // for doclit
282
+ $attstr .= " $key=\"$value\"";
283
+ }
284
+ // get namespace - must be done after namespace atts are processed
285
+ if(isset($prefix)){
286
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
287
+ $this->default_namespace = $this->namespaces[$prefix];
288
+ } else {
289
+ $this->message[$pos]['namespace'] = $this->default_namespace;
290
+ }
291
+ if($this->status == 'header'){
292
+ if ($this->root_header != $pos) {
293
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
294
+ }
295
+ } elseif($this->root_struct_name != ''){
296
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
297
+ }
298
+ }
299
+
300
+ /**
301
+ * end-element handler
302
+ *
303
+ * @param resource $parser XML parser object
304
+ * @param string $name element name
305
+ * @access private
306
+ */
307
+ function end_element($parser, $name) {
308
+ // position of current element is equal to the last value left in depth_array for my depth
309
+ $pos = $this->depth_array[$this->depth--];
310
+
311
+ // get element prefix
312
+ if(strpos($name,':')){
313
+ // get ns prefix
314
+ $prefix = substr($name,0,strpos($name,':'));
315
+ // get unqualified name
316
+ $name = substr(strstr($name,':'),1);
317
+ }
318
+
319
+ // build to native type
320
+ if(isset($this->body_position) && $pos > $this->body_position){
321
+ // deal w/ multirefs
322
+ if(isset($this->message[$pos]['attrs']['href'])){
323
+ // get id
324
+ $id = substr($this->message[$pos]['attrs']['href'],1);
325
+ // add placeholder to href array
326
+ $this->multirefs[$id][$pos] = 'placeholder';
327
+ // add set a reference to it as the result value
328
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
329
+ // build complexType values
330
+ } elseif($this->message[$pos]['children'] != ''){
331
+ // if result has already been generated (struct/array)
332
+ if(!isset($this->message[$pos]['result'])){
333
+ $this->message[$pos]['result'] = $this->buildVal($pos);
334
+ }
335
+ // build complexType values of attributes and possibly simpleContent
336
+ } elseif (isset($this->message[$pos]['xattrs'])) {
337
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
338
+ $this->message[$pos]['xattrs']['!'] = null;
339
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
340
+ if (isset($this->message[$pos]['type'])) {
341
+ $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'] : '');
342
+ } else {
343
+ $parent = $this->message[$pos]['parent'];
344
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
345
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
346
+ } else {
347
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
348
+ }
349
+ }
350
+ }
351
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
352
+ // set value of simpleType (or nil complexType)
353
+ } else {
354
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
355
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
356
+ $this->message[$pos]['xattrs']['!'] = null;
357
+ } elseif (isset($this->message[$pos]['type'])) {
358
+ $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'] : '');
359
+ } else {
360
+ $parent = $this->message[$pos]['parent'];
361
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
362
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
363
+ } else {
364
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
365
+ }
366
+ }
367
+
368
+ /* add value to parent's result, if parent is struct/array
369
+ $parent = $this->message[$pos]['parent'];
370
+ if($this->message[$parent]['type'] != 'map'){
371
+ if(strtolower($this->message[$parent]['type']) == 'array'){
372
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
373
+ } else {
374
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
375
+ }
376
+ }
377
+ */
378
+ }
379
+ }
380
+
381
+ // for doclit
382
+ if($this->status == 'header'){
383
+ if ($this->root_header != $pos) {
384
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
385
+ }
386
+ } elseif($pos >= $this->root_struct){
387
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
388
+ }
389
+ // switch status
390
+ if($pos == $this->root_struct){
391
+ $this->status = 'body';
392
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
393
+ } elseif($name == 'Body'){
394
+ $this->status = 'envelope';
395
+ } elseif($name == 'Header'){
396
+ $this->status = 'envelope';
397
+ } elseif($name == 'Envelope'){
398
+ //
399
+ }
400
+ // set parent back to my parent
401
+ $this->parent = $this->message[$pos]['parent'];
402
+ }
403
+
404
+ /**
405
+ * element content handler
406
+ *
407
+ * @param resource $parser XML parser object
408
+ * @param string $data element content
409
+ * @access private
410
+ */
411
+ function character_data($parser, $data){
412
+ $pos = $this->depth_array[$this->depth];
413
+ if ($this->xml_encoding=='UTF-8'){
414
+ // TODO: add an option to disable this for folks who want
415
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
416
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
417
+ if($this->decode_utf8){
418
+ $data = utf8_decode($data);
419
+ }
420
+ }
421
+ $this->message[$pos]['cdata'] .= $data;
422
+ // for doclit
423
+ if($this->status == 'header'){
424
+ $this->responseHeaders .= $data;
425
+ } else {
426
+ $this->document .= $data;
427
+ }
428
+ }
429
+
430
+ /**
431
+ * get the parsed message (SOAP Body)
432
+ *
433
+ * @return mixed
434
+ * @access public
435
+ * @deprecated use get_soapbody instead
436
+ */
437
+ function get_response(){
438
+ return $this->soapresponse;
439
+ }
440
+
441
+ /**
442
+ * get the parsed SOAP Body (NULL if there was none)
443
+ *
444
+ * @return mixed
445
+ * @access public
446
+ */
447
+ function get_soapbody(){
448
+ return $this->soapresponse;
449
+ }
450
+
451
+ /**
452
+ * get the parsed SOAP Header (NULL if there was none)
453
+ *
454
+ * @return mixed
455
+ * @access public
456
+ */
457
+ function get_soapheader(){
458
+ return $this->soapheader;
459
+ }
460
+
461
+ /**
462
+ * get the unparsed SOAP Header
463
+ *
464
+ * @return string XML or empty if no Header
465
+ * @access public
466
+ */
467
+ function getHeaders(){
468
+ return $this->responseHeaders;
469
+ }
470
+
471
+ /**
472
+ * decodes simple types into PHP variables
473
+ *
474
+ * @param string $value value to decode
475
+ * @param string $type XML type to decode
476
+ * @param string $typens XML type namespace to decode
477
+ * @return mixed PHP value
478
+ * @access private
479
+ */
480
+ function decodeSimple($value, $type, $typens) {
481
+ // TODO: use the namespace!
482
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
483
+ return (string) $value;
484
+ }
485
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
486
+ return (int) $value;
487
+ }
488
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
489
+ return (double) $value;
490
+ }
491
+ if ($type == 'boolean') {
492
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
493
+ return false;
494
+ }
495
+ return (boolean) $value;
496
+ }
497
+ if ($type == 'base64' || $type == 'base64Binary') {
498
+ $this->debug('Decode base64 value');
499
+ return base64_decode($value);
500
+ }
501
+ // obscure numeric types
502
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
503
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
504
+ || $type == 'unsignedInt'
505
+ || $type == 'unsignedShort' || $type == 'unsignedByte') {
506
+ return (int) $value;
507
+ }
508
+ // bogus: parser treats array with no elements as a simple type
509
+ if ($type == 'array') {
510
+ return array();
511
+ }
512
+ // everything else
513
+ return (string) $value;
514
+ }
515
+
516
+ /**
517
+ * builds response structures for compound values (arrays/structs)
518
+ * and scalars
519
+ *
520
+ * @param integer $pos position in node tree
521
+ * @return mixed PHP value
522
+ * @access private
523
+ */
524
+ function buildVal($pos){
525
+ if(!isset($this->message[$pos]['type'])){
526
+ $this->message[$pos]['type'] = '';
527
+ }
528
+ $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
529
+ // if there are children...
530
+ if($this->message[$pos]['children'] != ''){
531
+ $this->debug('in buildVal, there are children');
532
+ $children = explode('|',$this->message[$pos]['children']);
533
+ array_shift($children); // knock off empty
534
+ // md array
535
+ if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
536
+ $r=0; // rowcount
537
+ $c=0; // colcount
538
+ foreach($children as $child_pos){
539
+ $this->debug("in buildVal, got an MD array element: $r, $c");
540
+ $params[$r][] = $this->message[$child_pos]['result'];
541
+ $c++;
542
+ if($c == $this->message[$pos]['arrayCols']){
543
+ $c = 0;
544
+ $r++;
545
+ }
546
+ }
547
+ // array
548
+ } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
549
+ $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
550
+ foreach($children as $child_pos){
551
+ $params[] = &$this->message[$child_pos]['result'];
552
+ }
553
+ // apache Map type: java hashtable
554
+ } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
555
+ $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
556
+ foreach($children as $child_pos){
557
+ $kv = explode("|",$this->message[$child_pos]['children']);
558
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
559
+ }
560
+ // generic compound type
561
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
562
+ } else {
563
+ // Apache Vector type: treat as an array
564
+ $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
565
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
566
+ $notstruct = 1;
567
+ } else {
568
+ $notstruct = 0;
569
+ }
570
+ //
571
+ foreach($children as $child_pos){
572
+ if($notstruct){
573
+ $params[] = &$this->message[$child_pos]['result'];
574
+ } else {
575
+ if (isset($params[$this->message[$child_pos]['name']])) {
576
+ // de-serialize repeated element name into an array
577
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
578
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
579
+ }
580
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
581
+ } else {
582
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
583
+ }
584
+ }
585
+ }
586
+ }
587
+ if (isset($this->message[$pos]['xattrs'])) {
588
+ $this->debug('in buildVal, handling attributes');
589
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
590
+ $params[$n] = $v;
591
+ }
592
+ }
593
+ // handle simpleContent
594
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
595
+ $this->debug('in buildVal, handling simpleContent');
596
+ if (isset($this->message[$pos]['type'])) {
597
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
598
+ } else {
599
+ $parent = $this->message[$pos]['parent'];
600
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
601
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
602
+ } else {
603
+ $params['!'] = $this->message[$pos]['cdata'];
604
+ }
605
+ }
606
+ }
607
+ $ret = is_array($params) ? $params : array();
608
+ $this->debug('in buildVal, return:');
609
+ $this->appendDebug($this->varDump($ret));
610
+ return $ret;
611
+ } else {
612
+ $this->debug('in buildVal, no children, building scalar');
613
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
614
+ if (isset($this->message[$pos]['type'])) {
615
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
616
+ $this->debug("in buildVal, return: $ret");
617
+ return $ret;
618
+ }
619
+ $parent = $this->message[$pos]['parent'];
620
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
621
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
622
+ $this->debug("in buildVal, return: $ret");
623
+ return $ret;
624
+ }
625
+ $ret = $this->message[$pos]['cdata'];
626
+ $this->debug("in buildVal, return: $ret");
627
+ return $ret;
628
+ }
629
+ }
630
+ }
631
+
632
+ /**
633
+ * Backward compatibility
634
+ */
635
+ class soap_parser extends nusoap_parser {
636
+ }
637
+
638
+
639
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soap_server.php ADDED
@@ -0,0 +1,1073 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ *
8
+ * nusoap_server allows the user to create a SOAP server
9
+ * that is capable of receiving messages and returning responses
10
+ *
11
+ * @author Dietrich Ayala <dietrich@ganx4.com>
12
+ * @author Scott Nichol <snichol@users.sourceforge.net>
13
+ * @version $Id: class.soap_server.php,v 1.58 2007/10/30 18:50:30 snichol Exp $
14
+ * @access public
15
+ */
16
+ class nusoap_server extends nusoap_base {
17
+ /**
18
+ * HTTP headers of request
19
+ * @var array
20
+ * @access private
21
+ */
22
+ var $headers = array();
23
+ /**
24
+ * HTTP request
25
+ * @var string
26
+ * @access private
27
+ */
28
+ var $request = '';
29
+ /**
30
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
31
+ * @var string
32
+ * @access public
33
+ */
34
+ var $requestHeaders = '';
35
+ /**
36
+ * SOAP Headers from request (parsed)
37
+ * @var mixed
38
+ * @access public
39
+ */
40
+ var $requestHeader = NULL;
41
+ /**
42
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
43
+ * @var string
44
+ * @access public
45
+ */
46
+ var $document = '';
47
+ /**
48
+ * SOAP payload for request (text)
49
+ * @var string
50
+ * @access public
51
+ */
52
+ var $requestSOAP = '';
53
+ /**
54
+ * requested method namespace URI
55
+ * @var string
56
+ * @access private
57
+ */
58
+ var $methodURI = '';
59
+ /**
60
+ * name of method requested
61
+ * @var string
62
+ * @access private
63
+ */
64
+ var $methodname = '';
65
+ /**
66
+ * method parameters from request
67
+ * @var array
68
+ * @access private
69
+ */
70
+ var $methodparams = array();
71
+ /**
72
+ * SOAP Action from request
73
+ * @var string
74
+ * @access private
75
+ */
76
+ var $SOAPAction = '';
77
+ /**
78
+ * character set encoding of incoming (request) messages
79
+ * @var string
80
+ * @access public
81
+ */
82
+ var $xml_encoding = '';
83
+ /**
84
+ * toggles whether the parser decodes element content w/ utf8_decode()
85
+ * @var boolean
86
+ * @access public
87
+ */
88
+ var $decode_utf8 = true;
89
+
90
+ /**
91
+ * HTTP headers of response
92
+ * @var array
93
+ * @access public
94
+ */
95
+ var $outgoing_headers = array();
96
+ /**
97
+ * HTTP response
98
+ * @var string
99
+ * @access private
100
+ */
101
+ var $response = '';
102
+ /**
103
+ * SOAP headers for response (text or array of soapval or associative array)
104
+ * @var mixed
105
+ * @access public
106
+ */
107
+ var $responseHeaders = '';
108
+ /**
109
+ * SOAP payload for response (text)
110
+ * @var string
111
+ * @access private
112
+ */
113
+ var $responseSOAP = '';
114
+ /**
115
+ * method return value to place in response
116
+ * @var mixed
117
+ * @access private
118
+ */
119
+ var $methodreturn = false;
120
+ /**
121
+ * whether $methodreturn is a string of literal XML
122
+ * @var boolean
123
+ * @access public
124
+ */
125
+ var $methodreturnisliteralxml = false;
126
+ /**
127
+ * SOAP fault for response (or false)
128
+ * @var mixed
129
+ * @access private
130
+ */
131
+ var $fault = false;
132
+ /**
133
+ * text indication of result (for debugging)
134
+ * @var string
135
+ * @access private
136
+ */
137
+ var $result = 'successful';
138
+
139
+ /**
140
+ * assoc array of operations => opData; operations are added by the register()
141
+ * method or by parsing an external WSDL definition
142
+ * @var array
143
+ * @access private
144
+ */
145
+ var $operations = array();
146
+ /**
147
+ * wsdl instance (if one)
148
+ * @var mixed
149
+ * @access private
150
+ */
151
+ var $wsdl = false;
152
+ /**
153
+ * URL for WSDL (if one)
154
+ * @var mixed
155
+ * @access private
156
+ */
157
+ var $externalWSDLURL = false;
158
+ /**
159
+ * whether to append debug to response as XML comment
160
+ * @var boolean
161
+ * @access public
162
+ */
163
+ var $debug_flag = false;
164
+
165
+
166
+ /**
167
+ * constructor
168
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
169
+ *
170
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
171
+ * @access public
172
+ */
173
+ function nusoap_server($wsdl=false){
174
+ parent::nusoap_base();
175
+ // turn on debugging?
176
+ global $debug;
177
+ global $HTTP_SERVER_VARS;
178
+
179
+ if (isset($_SERVER)) {
180
+ $this->debug("_SERVER is defined:");
181
+ $this->appendDebug($this->varDump($_SERVER));
182
+ } elseif (isset($HTTP_SERVER_VARS)) {
183
+ $this->debug("HTTP_SERVER_VARS is defined:");
184
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
185
+ } else {
186
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
187
+ }
188
+
189
+ if (isset($debug)) {
190
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
191
+ $this->debug_flag = $debug;
192
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
193
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
194
+ foreach ($qs as $v) {
195
+ if (substr($v, 0, 6) == 'debug=') {
196
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
197
+ $this->debug_flag = substr($v, 6);
198
+ }
199
+ }
200
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
201
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
202
+ foreach ($qs as $v) {
203
+ if (substr($v, 0, 6) == 'debug=') {
204
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
205
+ $this->debug_flag = substr($v, 6);
206
+ }
207
+ }
208
+ }
209
+
210
+ // wsdl
211
+ if($wsdl){
212
+ $this->debug("In nusoap_server, WSDL is specified");
213
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
214
+ $this->wsdl = $wsdl;
215
+ $this->externalWSDLURL = $this->wsdl->wsdl;
216
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
217
+ } else {
218
+ $this->debug('Create wsdl from ' . $wsdl);
219
+ $this->wsdl = new wsdl($wsdl);
220
+ $this->externalWSDLURL = $wsdl;
221
+ }
222
+ $this->appendDebug($this->wsdl->getDebug());
223
+ $this->wsdl->clearDebug();
224
+ if($err = $this->wsdl->getError()){
225
+ die('WSDL ERROR: '.$err);
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * processes request and returns response
232
+ *
233
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
234
+ * @access public
235
+ */
236
+ function service($data){
237
+ global $HTTP_SERVER_VARS;
238
+
239
+ if (isset($_SERVER['QUERY_STRING'])) {
240
+ $qs = $_SERVER['QUERY_STRING'];
241
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
242
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
243
+ } else {
244
+ $qs = '';
245
+ }
246
+ $this->debug("In service, query string=$qs");
247
+
248
+ if (ereg('wsdl', $qs) ){
249
+ $this->debug("In service, this is a request for WSDL");
250
+ if($this->externalWSDLURL){
251
+ if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
252
+ header('Location: '.$this->externalWSDLURL);
253
+ } else { // assume file
254
+ header("Content-Type: text/xml\r\n");
255
+ $fp = fopen($this->externalWSDLURL, 'r');
256
+ fpassthru($fp);
257
+ }
258
+ } elseif ($this->wsdl) {
259
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
260
+ print $this->wsdl->serialize($this->debug_flag);
261
+ if ($this->debug_flag) {
262
+ $this->debug('wsdl:');
263
+ $this->appendDebug($this->varDump($this->wsdl));
264
+ print $this->getDebugAsXMLComment();
265
+ }
266
+ } else {
267
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
268
+ print "This service does not provide WSDL";
269
+ }
270
+ } elseif ($data == '' && $this->wsdl) {
271
+ $this->debug("In service, there is no data, so return Web description");
272
+ print $this->wsdl->webDescription();
273
+ } else {
274
+ $this->debug("In service, invoke the request");
275
+ $this->parse_request($data);
276
+ if (! $this->fault) {
277
+ $this->invoke_method();
278
+ }
279
+ if (! $this->fault) {
280
+ $this->serialize_return();
281
+ }
282
+ $this->send_response();
283
+ }
284
+ }
285
+
286
+ /**
287
+ * parses HTTP request headers.
288
+ *
289
+ * The following fields are set by this function (when successful)
290
+ *
291
+ * headers
292
+ * request
293
+ * xml_encoding
294
+ * SOAPAction
295
+ *
296
+ * @access private
297
+ */
298
+ function parse_http_headers() {
299
+ global $HTTP_SERVER_VARS;
300
+
301
+ $this->request = '';
302
+ $this->SOAPAction = '';
303
+ if(function_exists('getallheaders')){
304
+ $this->debug("In parse_http_headers, use getallheaders");
305
+ $headers = getallheaders();
306
+ foreach($headers as $k=>$v){
307
+ $k = strtolower($k);
308
+ $this->headers[$k] = $v;
309
+ $this->request .= "$k: $v\r\n";
310
+ $this->debug("$k: $v");
311
+ }
312
+ // get SOAPAction header
313
+ if(isset($this->headers['soapaction'])){
314
+ $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
315
+ }
316
+ // get the character encoding of the incoming request
317
+ if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
318
+ $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
319
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
320
+ $this->xml_encoding = strtoupper($enc);
321
+ } else {
322
+ $this->xml_encoding = 'US-ASCII';
323
+ }
324
+ } else {
325
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
326
+ $this->xml_encoding = 'ISO-8859-1';
327
+ }
328
+ } elseif(isset($_SERVER) && is_array($_SERVER)){
329
+ $this->debug("In parse_http_headers, use _SERVER");
330
+ foreach ($_SERVER as $k => $v) {
331
+ if (substr($k, 0, 5) == 'HTTP_') {
332
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
333
+ } else {
334
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
335
+ }
336
+ if ($k == 'soapaction') {
337
+ // get SOAPAction header
338
+ $k = 'SOAPAction';
339
+ $v = str_replace('"', '', $v);
340
+ $v = str_replace('\\', '', $v);
341
+ $this->SOAPAction = $v;
342
+ } else if ($k == 'content-type') {
343
+ // get the character encoding of the incoming request
344
+ if (strpos($v, '=')) {
345
+ $enc = substr(strstr($v, '='), 1);
346
+ $enc = str_replace('"', '', $enc);
347
+ $enc = str_replace('\\', '', $enc);
348
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
349
+ $this->xml_encoding = strtoupper($enc);
350
+ } else {
351
+ $this->xml_encoding = 'US-ASCII';
352
+ }
353
+ } else {
354
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
355
+ $this->xml_encoding = 'ISO-8859-1';
356
+ }
357
+ }
358
+ $this->headers[$k] = $v;
359
+ $this->request .= "$k: $v\r\n";
360
+ $this->debug("$k: $v");
361
+ }
362
+ } elseif (is_array($HTTP_SERVER_VARS)) {
363
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
364
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
365
+ if (substr($k, 0, 5) == 'HTTP_') {
366
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
367
+ } else {
368
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
369
+ }
370
+ if ($k == 'soapaction') {
371
+ // get SOAPAction header
372
+ $k = 'SOAPAction';
373
+ $v = str_replace('"', '', $v);
374
+ $v = str_replace('\\', '', $v);
375
+ $this->SOAPAction = $v;
376
+ } else if ($k == 'content-type') {
377
+ // get the character encoding of the incoming request
378
+ if (strpos($v, '=')) {
379
+ $enc = substr(strstr($v, '='), 1);
380
+ $enc = str_replace('"', '', $enc);
381
+ $enc = str_replace('\\', '', $enc);
382
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
383
+ $this->xml_encoding = strtoupper($enc);
384
+ } else {
385
+ $this->xml_encoding = 'US-ASCII';
386
+ }
387
+ } else {
388
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
389
+ $this->xml_encoding = 'ISO-8859-1';
390
+ }
391
+ }
392
+ $this->headers[$k] = $v;
393
+ $this->request .= "$k: $v\r\n";
394
+ $this->debug("$k: $v");
395
+ }
396
+ } else {
397
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
398
+ $this->setError("HTTP headers not accessible");
399
+ }
400
+ }
401
+
402
+ /**
403
+ * parses a request
404
+ *
405
+ * The following fields are set by this function (when successful)
406
+ *
407
+ * headers
408
+ * request
409
+ * xml_encoding
410
+ * SOAPAction
411
+ * request
412
+ * requestSOAP
413
+ * methodURI
414
+ * methodname
415
+ * methodparams
416
+ * requestHeaders
417
+ * document
418
+ *
419
+ * This sets the fault field on error
420
+ *
421
+ * @param string $data XML string
422
+ * @access private
423
+ */
424
+ function parse_request($data='') {
425
+ $this->debug('entering parse_request()');
426
+ $this->parse_http_headers();
427
+ $this->debug('got character encoding: '.$this->xml_encoding);
428
+ // uncompress if necessary
429
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
430
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
431
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
432
+ // if decoding works, use it. else assume data wasn't gzencoded
433
+ if (function_exists('gzuncompress')) {
434
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
435
+ $data = $degzdata;
436
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
437
+ $data = $degzdata;
438
+ } else {
439
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
440
+ return;
441
+ }
442
+ } else {
443
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
444
+ return;
445
+ }
446
+ }
447
+ }
448
+ $this->request .= "\r\n".$data;
449
+ $data = $this->parseRequest($this->headers, $data);
450
+ $this->requestSOAP = $data;
451
+ $this->debug('leaving parse_request');
452
+ }
453
+
454
+ /**
455
+ * invokes a PHP function for the requested SOAP method
456
+ *
457
+ * The following fields are set by this function (when successful)
458
+ *
459
+ * methodreturn
460
+ *
461
+ * Note that the PHP function that is called may also set the following
462
+ * fields to affect the response sent to the client
463
+ *
464
+ * responseHeaders
465
+ * outgoing_headers
466
+ *
467
+ * This sets the fault field on error
468
+ *
469
+ * @access private
470
+ */
471
+ function invoke_method() {
472
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
473
+
474
+ if ($this->wsdl) {
475
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
476
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
477
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
478
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
479
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
480
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
481
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
482
+ $this->methodname = $this->opData['name'];
483
+ } else {
484
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
485
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
486
+ return;
487
+ }
488
+ } else {
489
+ $this->debug('in invoke_method, no WSDL to validate method');
490
+ }
491
+
492
+ // if a . is present in $this->methodname, we see if there is a class in scope,
493
+ // which could be referred to. We will also distinguish between two deliminators,
494
+ // to allow methods to be called a the class or an instance
495
+ $class = '';
496
+ $method = '';
497
+ if (strpos($this->methodname, '..') > 0) {
498
+ $delim = '..';
499
+ } else if (strpos($this->methodname, '.') > 0) {
500
+ $delim = '.';
501
+ } else {
502
+ $delim = '';
503
+ }
504
+
505
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
506
+ class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
507
+ // get the class and method name
508
+ $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
509
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
510
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
511
+ }
512
+
513
+ // does method exist?
514
+ if ($class == '') {
515
+ if (!function_exists($this->methodname)) {
516
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
517
+ $this->result = 'fault: method not found';
518
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
519
+ return;
520
+ }
521
+ } else {
522
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
523
+ if (!in_array($method_to_compare, get_class_methods($class))) {
524
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
525
+ $this->result = 'fault: method not found';
526
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
527
+ return;
528
+ }
529
+ }
530
+
531
+ // evaluate message, getting back parameters
532
+ // verify that request parameters match the method's signature
533
+ if(! $this->verify_method($this->methodname,$this->methodparams)){
534
+ // debug
535
+ $this->debug('ERROR: request not verified against method signature');
536
+ $this->result = 'fault: request failed validation against method signature';
537
+ // return fault
538
+ $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
539
+ return;
540
+ }
541
+
542
+ // if there are parameters to pass
543
+ $this->debug('in invoke_method, params:');
544
+ $this->appendDebug($this->varDump($this->methodparams));
545
+ $this->debug("in invoke_method, calling '$this->methodname'");
546
+ if (!function_exists('call_user_func_array')) {
547
+ if ($class == '') {
548
+ $this->debug('in invoke_method, calling function using eval()');
549
+ $funcCall = "\$this->methodreturn = $this->methodname(";
550
+ } else {
551
+ if ($delim == '..') {
552
+ $this->debug('in invoke_method, calling class method using eval()');
553
+ $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
554
+ } else {
555
+ $this->debug('in invoke_method, calling instance method using eval()');
556
+ // generate unique instance name
557
+ $instname = "\$inst_".time();
558
+ $funcCall = $instname." = new ".$class."(); ";
559
+ $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
560
+ }
561
+ }
562
+ if ($this->methodparams) {
563
+ foreach ($this->methodparams as $param) {
564
+ if (is_array($param) || is_object($param)) {
565
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
566
+ return;
567
+ }
568
+ $funcCall .= "\"$param\",";
569
+ }
570
+ $funcCall = substr($funcCall, 0, -1);
571
+ }
572
+ $funcCall .= ');';
573
+ $this->debug('in invoke_method, function call: '.$funcCall);
574
+ @eval($funcCall);
575
+ } else {
576
+ if ($class == '') {
577
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
578
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
579
+ } elseif ($delim == '..') {
580
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
581
+ $call_arg = array ($class, $method);
582
+ } else {
583
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
584
+ $instance = new $class ();
585
+ $call_arg = array(&$instance, $method);
586
+ }
587
+ if (is_array($this->methodparams)) {
588
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
589
+ } else {
590
+ $this->methodreturn = call_user_func_array($call_arg, array());
591
+ }
592
+ }
593
+ $this->debug('in invoke_method, methodreturn:');
594
+ $this->appendDebug($this->varDump($this->methodreturn));
595
+ $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
596
+ }
597
+
598
+ /**
599
+ * serializes the return value from a PHP function into a full SOAP Envelope
600
+ *
601
+ * The following fields are set by this function (when successful)
602
+ *
603
+ * responseSOAP
604
+ *
605
+ * This sets the fault field on error
606
+ *
607
+ * @access private
608
+ */
609
+ function serialize_return() {
610
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
611
+ // if fault
612
+ if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
613
+ $this->debug('got a fault object from method');
614
+ $this->fault = $this->methodreturn;
615
+ return;
616
+ } elseif ($this->methodreturnisliteralxml) {
617
+ $return_val = $this->methodreturn;
618
+ // returned value(s)
619
+ } else {
620
+ $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
621
+ $this->debug('serializing return value');
622
+ if($this->wsdl){
623
+ if (sizeof($this->opData['output']['parts']) > 1) {
624
+ $this->debug('more than one output part, so use the method return unchanged');
625
+ $opParams = $this->methodreturn;
626
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
627
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
628
+ // TODO: verify that it is not already wrapped!
629
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
630
+ // $this->debug('wrap in element named ' . $name);
631
+ //}
632
+ $opParams = array($this->methodreturn);
633
+ }
634
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
635
+ $this->appendDebug($this->wsdl->getDebug());
636
+ $this->wsdl->clearDebug();
637
+ if($errstr = $this->wsdl->getError()){
638
+ $this->debug('got wsdl error: '.$errstr);
639
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
640
+ return;
641
+ }
642
+ } else {
643
+ if (isset($this->methodreturn)) {
644
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
645
+ } else {
646
+ $return_val = '';
647
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
648
+ }
649
+ }
650
+ }
651
+ $this->debug('return value:');
652
+ $this->appendDebug($this->varDump($return_val));
653
+
654
+ $this->debug('serializing response');
655
+ if ($this->wsdl) {
656
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
657
+ if ($this->opData['style'] == 'rpc') {
658
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
659
+ if ($this->opData['output']['use'] == 'literal') {
660
+ // 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
661
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
662
+ } else {
663
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
664
+ }
665
+ } else {
666
+ $this->debug('style is not rpc for serialization: assume document');
667
+ $payload = $return_val;
668
+ }
669
+ } else {
670
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
671
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
672
+ }
673
+ $this->result = 'successful';
674
+ if($this->wsdl){
675
+ //if($this->debug_flag){
676
+ $this->appendDebug($this->wsdl->getDebug());
677
+ // }
678
+ if (isset($opData['output']['encodingStyle'])) {
679
+ $encodingStyle = $opData['output']['encodingStyle'];
680
+ } else {
681
+ $encodingStyle = '';
682
+ }
683
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
684
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
685
+ } else {
686
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
687
+ }
688
+ $this->debug("Leaving serialize_return");
689
+ }
690
+
691
+ /**
692
+ * sends an HTTP response
693
+ *
694
+ * The following fields are set by this function (when successful)
695
+ *
696
+ * outgoing_headers
697
+ * response
698
+ *
699
+ * @access private
700
+ */
701
+ function send_response() {
702
+ $this->debug('Enter send_response');
703
+ if ($this->fault) {
704
+ $payload = $this->fault->serialize();
705
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
706
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
707
+ } else {
708
+ $payload = $this->responseSOAP;
709
+ // Some combinations of PHP+Web server allow the Status
710
+ // to come through as a header. Since OK is the default
711
+ // just do nothing.
712
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
713
+ // $this->outgoing_headers[] = "Status: 200 OK";
714
+ }
715
+ // add debug data if in debug mode
716
+ if(isset($this->debug_flag) && $this->debug_flag){
717
+ $payload .= $this->getDebugAsXMLComment();
718
+ }
719
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
720
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
721
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
722
+ // Let the Web server decide about this
723
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
724
+ $payload = $this->getHTTPBody($payload);
725
+ $type = $this->getHTTPContentType();
726
+ $charset = $this->getHTTPContentTypeCharset();
727
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
728
+ //begin code to compress payload - by John
729
+ // NOTE: there is no way to know whether the Web server will also compress
730
+ // this data.
731
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
732
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
733
+ if (function_exists('gzencode')) {
734
+ if (isset($this->debug_flag) && $this->debug_flag) {
735
+ $payload .= "<!-- Content being gzipped -->";
736
+ }
737
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
738
+ $payload = gzencode($payload);
739
+ } else {
740
+ if (isset($this->debug_flag) && $this->debug_flag) {
741
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
742
+ }
743
+ }
744
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
745
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
746
+ // instead of gzcompress output,
747
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
748
+ if (function_exists('gzdeflate')) {
749
+ if (isset($this->debug_flag) && $this->debug_flag) {
750
+ $payload .= "<!-- Content being deflated -->";
751
+ }
752
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
753
+ $payload = gzdeflate($payload);
754
+ } else {
755
+ if (isset($this->debug_flag) && $this->debug_flag) {
756
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
757
+ }
758
+ }
759
+ }
760
+ }
761
+ //end code
762
+ $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
763
+ reset($this->outgoing_headers);
764
+ foreach($this->outgoing_headers as $hdr){
765
+ header($hdr, false);
766
+ }
767
+ print $payload;
768
+ $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
769
+ }
770
+
771
+ /**
772
+ * takes the value that was created by parsing the request
773
+ * and compares to the method's signature, if available.
774
+ *
775
+ * @param string $operation The operation to be invoked
776
+ * @param array $request The array of parameter values
777
+ * @return boolean Whether the operation was found
778
+ * @access private
779
+ */
780
+ function verify_method($operation,$request){
781
+ if(isset($this->wsdl) && is_object($this->wsdl)){
782
+ if($this->wsdl->getOperationData($operation)){
783
+ return true;
784
+ }
785
+ } elseif(isset($this->operations[$operation])){
786
+ return true;
787
+ }
788
+ return false;
789
+ }
790
+
791
+ /**
792
+ * processes SOAP message received from client
793
+ *
794
+ * @param array $headers The HTTP headers
795
+ * @param string $data unprocessed request data from client
796
+ * @return mixed value of the message, decoded into a PHP type
797
+ * @access private
798
+ */
799
+ function parseRequest($headers, $data) {
800
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
801
+ if (!strstr($headers['content-type'], 'text/xml')) {
802
+ $this->setError('Request not of type text/xml');
803
+ return false;
804
+ }
805
+ if (strpos($headers['content-type'], '=')) {
806
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
807
+ $this->debug('Got response encoding: ' . $enc);
808
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
809
+ $this->xml_encoding = strtoupper($enc);
810
+ } else {
811
+ $this->xml_encoding = 'US-ASCII';
812
+ }
813
+ } else {
814
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
815
+ $this->xml_encoding = 'ISO-8859-1';
816
+ }
817
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
818
+ // parse response, get soap parser obj
819
+ $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
820
+ // parser debug
821
+ $this->debug("parser debug: \n".$parser->getDebug());
822
+ // if fault occurred during message parsing
823
+ if($err = $parser->getError()){
824
+ $this->result = 'fault: error in msg parsing: '.$err;
825
+ $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
826
+ // else successfully parsed request into soapval object
827
+ } else {
828
+ // get/set methodname
829
+ $this->methodURI = $parser->root_struct_namespace;
830
+ $this->methodname = $parser->root_struct_name;
831
+ $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
832
+ $this->debug('calling parser->get_soapbody()');
833
+ $this->methodparams = $parser->get_soapbody();
834
+ // get SOAP headers
835
+ $this->requestHeaders = $parser->getHeaders();
836
+ // get SOAP Header
837
+ $this->requestHeader = $parser->get_soapheader();
838
+ // add document for doclit support
839
+ $this->document = $parser->document;
840
+ }
841
+ }
842
+
843
+ /**
844
+ * gets the HTTP body for the current response.
845
+ *
846
+ * @param string $soapmsg The SOAP payload
847
+ * @return string The HTTP body, which includes the SOAP payload
848
+ * @access private
849
+ */
850
+ function getHTTPBody($soapmsg) {
851
+ return $soapmsg;
852
+ }
853
+
854
+ /**
855
+ * gets the HTTP content type for the current response.
856
+ *
857
+ * Note: getHTTPBody must be called before this.
858
+ *
859
+ * @return string the HTTP content type for the current response.
860
+ * @access private
861
+ */
862
+ function getHTTPContentType() {
863
+ return 'text/xml';
864
+ }
865
+
866
+ /**
867
+ * gets the HTTP content type charset for the current response.
868
+ * returns false for non-text content types.
869
+ *
870
+ * Note: getHTTPBody must be called before this.
871
+ *
872
+ * @return string the HTTP content type charset for the current response.
873
+ * @access private
874
+ */
875
+ function getHTTPContentTypeCharset() {
876
+ return $this->soap_defencoding;
877
+ }
878
+
879
+ /**
880
+ * add a method to the dispatch map (this has been replaced by the register method)
881
+ *
882
+ * @param string $methodname
883
+ * @param string $in array of input values
884
+ * @param string $out array of output values
885
+ * @access public
886
+ * @deprecated
887
+ */
888
+ function add_to_map($methodname,$in,$out){
889
+ $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
890
+ }
891
+
892
+ /**
893
+ * register a service function with the server
894
+ *
895
+ * @param string $name the name of the PHP function, class.method or class..method
896
+ * @param array $in assoc array of input values: key = param name, value = param type
897
+ * @param array $out assoc array of output values: key = param name, value = param type
898
+ * @param mixed $namespace the element namespace for the method or false
899
+ * @param mixed $soapaction the soapaction for the method or false
900
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
901
+ * @param mixed $use optional (encoded|literal) or false
902
+ * @param string $documentation optional Description to include in WSDL
903
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
904
+ * @access public
905
+ */
906
+ function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
907
+ global $HTTP_SERVER_VARS;
908
+
909
+ if($this->externalWSDLURL){
910
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
911
+ }
912
+ if (! $name) {
913
+ die('You must specify a name when you register an operation');
914
+ }
915
+ if (!is_array($in)) {
916
+ die('You must provide an array for operation inputs');
917
+ }
918
+ if (!is_array($out)) {
919
+ die('You must provide an array for operation outputs');
920
+ }
921
+ if(false == $namespace) {
922
+ }
923
+ if(false == $soapaction) {
924
+ if (isset($_SERVER)) {
925
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
926
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
927
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
928
+ } elseif (isset($HTTP_SERVER_VARS)) {
929
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
930
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
931
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
932
+ } else {
933
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
934
+ }
935
+ if ($HTTPS == '1' || $HTTPS == 'on') {
936
+ $SCHEME = 'https';
937
+ } else {
938
+ $SCHEME = 'http';
939
+ }
940
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
941
+ }
942
+ if(false == $style) {
943
+ $style = "rpc";
944
+ }
945
+ if(false == $use) {
946
+ $use = "encoded";
947
+ }
948
+ if ($use == 'encoded' && $encodingStyle = '') {
949
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
950
+ }
951
+
952
+ $this->operations[$name] = array(
953
+ 'name' => $name,
954
+ 'in' => $in,
955
+ 'out' => $out,
956
+ 'namespace' => $namespace,
957
+ 'soapaction' => $soapaction,
958
+ 'style' => $style);
959
+ if($this->wsdl){
960
+ $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
961
+ }
962
+ return true;
963
+ }
964
+
965
+ /**
966
+ * Specify a fault to be returned to the client.
967
+ * This also acts as a flag to the server that a fault has occured.
968
+ *
969
+ * @param string $faultcode
970
+ * @param string $faultstring
971
+ * @param string $faultactor
972
+ * @param string $faultdetail
973
+ * @access public
974
+ */
975
+ function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
976
+ if ($faultdetail == '' && $this->debug_flag) {
977
+ $faultdetail = $this->getDebug();
978
+ }
979
+ $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
980
+ $this->fault->soap_defencoding = $this->soap_defencoding;
981
+ }
982
+
983
+ /**
984
+ * Sets up wsdl object.
985
+ * Acts as a flag to enable internal WSDL generation
986
+ *
987
+ * @param string $serviceName, name of the service
988
+ * @param mixed $namespace optional 'tns' service namespace or false
989
+ * @param mixed $endpoint optional URL of service endpoint or false
990
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
991
+ * @param string $transport optional SOAP transport
992
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
993
+ */
994
+ function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
995
+ {
996
+ global $HTTP_SERVER_VARS;
997
+
998
+ if (isset($_SERVER)) {
999
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
1000
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
1001
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
1002
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
1003
+ } elseif (isset($HTTP_SERVER_VARS)) {
1004
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
1005
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
1006
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
1007
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
1008
+ } else {
1009
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
1010
+ }
1011
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
1012
+ $colon = strpos($SERVER_NAME,":");
1013
+ if ($colon) {
1014
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
1015
+ }
1016
+ if ($SERVER_PORT == 80) {
1017
+ $SERVER_PORT = '';
1018
+ } else {
1019
+ $SERVER_PORT = ':' . $SERVER_PORT;
1020
+ }
1021
+ if(false == $namespace) {
1022
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
1023
+ }
1024
+
1025
+ if(false == $endpoint) {
1026
+ if ($HTTPS == '1' || $HTTPS == 'on') {
1027
+ $SCHEME = 'https';
1028
+ } else {
1029
+ $SCHEME = 'http';
1030
+ }
1031
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
1032
+ }
1033
+
1034
+ if(false == $schemaTargetNamespace) {
1035
+ $schemaTargetNamespace = $namespace;
1036
+ }
1037
+
1038
+ $this->wsdl = new wsdl;
1039
+ $this->wsdl->serviceName = $serviceName;
1040
+ $this->wsdl->endpoint = $endpoint;
1041
+ $this->wsdl->namespaces['tns'] = $namespace;
1042
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
1043
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
1044
+ if ($schemaTargetNamespace != $namespace) {
1045
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
1046
+ }
1047
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
1048
+ if ($style == 'document') {
1049
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
1050
+ }
1051
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
1052
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
1053
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
1054
+ $this->wsdl->bindings[$serviceName.'Binding'] = array(
1055
+ 'name'=>$serviceName.'Binding',
1056
+ 'style'=>$style,
1057
+ 'transport'=>$transport,
1058
+ 'portType'=>$serviceName.'PortType');
1059
+ $this->wsdl->ports[$serviceName.'Port'] = array(
1060
+ 'binding'=>$serviceName.'Binding',
1061
+ 'location'=>$endpoint,
1062
+ 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
1063
+ }
1064
+ }
1065
+
1066
+ /**
1067
+ * Backward compatibility
1068
+ */
1069
+ class soap_server extends nusoap_server {
1070
+ }
1071
+
1072
+
1073
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soap_transport_http.php ADDED
@@ -0,0 +1,1305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ * transport class for sending/receiving data via HTTP and HTTPS
8
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
9
+ *
10
+ * @author Dietrich Ayala <dietrich@ganx4.com>
11
+ * @author Scott Nichol <snichol@users.sourceforge.net>
12
+ * @version $Id: class.soap_transport_http.php,v 1.66 2007/11/06 14:17:53 snichol Exp $
13
+ * @access public
14
+ */
15
+ class soap_transport_http extends nusoap_base {
16
+
17
+ var $url = '';
18
+ var $uri = '';
19
+ var $digest_uri = '';
20
+ var $scheme = '';
21
+ var $host = '';
22
+ var $port = '';
23
+ var $path = '';
24
+ var $request_method = 'POST';
25
+ var $protocol_version = '1.0';
26
+ var $encoding = '';
27
+ var $outgoing_headers = array();
28
+ var $incoming_headers = array();
29
+ var $incoming_cookies = array();
30
+ var $outgoing_payload = '';
31
+ var $incoming_payload = '';
32
+ var $response_status_line; // HTTP response status line
33
+ var $useSOAPAction = true;
34
+ var $persistentConnection = false;
35
+ var $ch = false; // cURL handle
36
+ var $ch_options = array(); // cURL custom options
37
+ var $use_curl = false; // force cURL use
38
+ var $proxy = null; // proxy information (associative array)
39
+ var $username = '';
40
+ var $password = '';
41
+ var $authtype = '';
42
+ var $digestRequest = array();
43
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
44
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
45
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
46
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
47
+ // passphrase: SSL key password/passphrase
48
+ // certpassword: SSL certificate password
49
+ // verifypeer: default is 1
50
+ // verifyhost: default is 1
51
+
52
+ /**
53
+ * constructor
54
+ *
55
+ * @param string $url The URL to which to connect
56
+ * @param array $curl_options User-specified cURL options
57
+ * @param boolean $use_curl Whether to try to force cURL use
58
+ * @access public
59
+ */
60
+ function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
61
+ parent::nusoap_base();
62
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
63
+ $this->appendDebug($this->varDump($curl_options));
64
+ $this->setURL($url);
65
+ if (is_array($curl_options)) {
66
+ $this->ch_options = $curl_options;
67
+ }
68
+ $this->use_curl = $use_curl;
69
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
70
+ $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
71
+ }
72
+
73
+ /**
74
+ * sets a cURL option
75
+ *
76
+ * @param mixed $option The cURL option (always integer?)
77
+ * @param mixed $value The cURL option value
78
+ * @access private
79
+ */
80
+ function setCurlOption($option, $value) {
81
+ $this->debug("setCurlOption option=$option, value=");
82
+ $this->appendDebug($this->varDump($value));
83
+ curl_setopt($this->ch, $option, $value);
84
+ }
85
+
86
+ /**
87
+ * sets an HTTP header
88
+ *
89
+ * @param string $name The name of the header
90
+ * @param string $value The value of the header
91
+ * @access private
92
+ */
93
+ function setHeader($name, $value) {
94
+ $this->outgoing_headers[$name] = $value;
95
+ $this->debug("set header $name: $value");
96
+ }
97
+
98
+ /**
99
+ * unsets an HTTP header
100
+ *
101
+ * @param string $name The name of the header
102
+ * @access private
103
+ */
104
+ function unsetHeader($name) {
105
+ if (isset($this->outgoing_headers[$name])) {
106
+ $this->debug("unset header $name");
107
+ unset($this->outgoing_headers[$name]);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * sets the URL to which to connect
113
+ *
114
+ * @param string $url The URL to which to connect
115
+ * @access private
116
+ */
117
+ function setURL($url) {
118
+ $this->url = $url;
119
+
120
+ $u = parse_url($url);
121
+ foreach($u as $k => $v){
122
+ $this->debug("parsed URL $k = $v");
123
+ $this->$k = $v;
124
+ }
125
+
126
+ // add any GET params to path
127
+ if(isset($u['query']) && $u['query'] != ''){
128
+ $this->path .= '?' . $u['query'];
129
+ }
130
+
131
+ // set default port
132
+ if(!isset($u['port'])){
133
+ if($u['scheme'] == 'https'){
134
+ $this->port = 443;
135
+ } else {
136
+ $this->port = 80;
137
+ }
138
+ }
139
+
140
+ $this->uri = $this->path;
141
+ $this->digest_uri = $this->uri;
142
+
143
+ // build headers
144
+ if (!isset($u['port'])) {
145
+ $this->setHeader('Host', $this->host);
146
+ } else {
147
+ $this->setHeader('Host', $this->host.':'.$this->port);
148
+ }
149
+
150
+ if (isset($u['user']) && $u['user'] != '') {
151
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
152
+ }
153
+ }
154
+
155
+ /**
156
+ * gets the I/O method to use
157
+ *
158
+ * @return string I/O method to use (socket|curl|unknown)
159
+ * @access private
160
+ */
161
+ function io_method() {
162
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
163
+ return 'curl';
164
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
165
+ return 'socket';
166
+ return 'unknown';
167
+ }
168
+
169
+ /**
170
+ * establish an HTTP connection
171
+ *
172
+ * @param integer $timeout set connection timeout in seconds
173
+ * @param integer $response_timeout set response timeout in seconds
174
+ * @return boolean true if connected, false if not
175
+ * @access private
176
+ */
177
+ function connect($connection_timeout=0,$response_timeout=30){
178
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
179
+ // "regular" socket.
180
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
181
+ // loaded), and until PHP5 stream_get_wrappers is not available.
182
+ // if ($this->scheme == 'https') {
183
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
184
+ // if (extension_loaded('openssl')) {
185
+ // $this->scheme = 'ssl';
186
+ // $this->debug('Using SSL over OpenSSL');
187
+ // }
188
+ // }
189
+ // }
190
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
191
+ if ($this->io_method() == 'socket') {
192
+ if (!is_array($this->proxy)) {
193
+ $host = $this->host;
194
+ $port = $this->port;
195
+ } else {
196
+ $host = $this->proxy['host'];
197
+ $port = $this->proxy['port'];
198
+ }
199
+
200
+ // use persistent connection
201
+ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
202
+ if (!feof($this->fp)) {
203
+ $this->debug('Re-use persistent connection');
204
+ return true;
205
+ }
206
+ fclose($this->fp);
207
+ $this->debug('Closed persistent connection at EOF');
208
+ }
209
+
210
+ // munge host if using OpenSSL
211
+ if ($this->scheme == 'ssl') {
212
+ $host = 'ssl://' . $host;
213
+ }
214
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
215
+
216
+ // open socket
217
+ if($connection_timeout > 0){
218
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
219
+ } else {
220
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
221
+ }
222
+
223
+ // test pointer
224
+ if(!$this->fp) {
225
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
226
+ if ($this->errno) {
227
+ $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
228
+ } else {
229
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
230
+ }
231
+ $this->debug($msg);
232
+ $this->setError($msg);
233
+ return false;
234
+ }
235
+
236
+ // set response timeout
237
+ $this->debug('set response timeout to ' . $response_timeout);
238
+ socket_set_timeout( $this->fp, $response_timeout);
239
+
240
+ $this->debug('socket connected');
241
+ return true;
242
+ } else if ($this->io_method() == 'curl') {
243
+ if (!extension_loaded('curl')) {
244
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
245
+ $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.');
246
+ return false;
247
+ }
248
+ // Avoid warnings when PHP does not have these options
249
+ if (defined('CURLOPT_CONNECTIONTIMEOUT'))
250
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
251
+ else
252
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
253
+ if (defined('CURLOPT_HTTPAUTH'))
254
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
255
+ else
256
+ $CURLOPT_HTTPAUTH = 107;
257
+ if (defined('CURLOPT_PROXYAUTH'))
258
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
259
+ else
260
+ $CURLOPT_PROXYAUTH = 111;
261
+ if (defined('CURLAUTH_BASIC'))
262
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
263
+ else
264
+ $CURLAUTH_BASIC = 1;
265
+ if (defined('CURLAUTH_DIGEST'))
266
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
267
+ else
268
+ $CURLAUTH_DIGEST = 2;
269
+ if (defined('CURLAUTH_NTLM'))
270
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
271
+ else
272
+ $CURLAUTH_NTLM = 8;
273
+
274
+ $this->debug('connect using cURL');
275
+ // init CURL
276
+ $this->ch = curl_init();
277
+ // set url
278
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
279
+ // add path
280
+ $hostURL .= $this->path;
281
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
282
+ // follow location headers (re-directs)
283
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
284
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
285
+ $this->debug('safe_mode = ');
286
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
287
+ $this->debug('open_basedir = ');
288
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
289
+ } else {
290
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
291
+ }
292
+ // ask for headers in the response output
293
+ $this->setCurlOption(CURLOPT_HEADER, 1);
294
+ // ask for the response output as the return value
295
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
296
+ // encode
297
+ // We manage this ourselves through headers and encoding
298
+ // if(function_exists('gzuncompress')){
299
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
300
+ // }
301
+ // persistent connection
302
+ if ($this->persistentConnection) {
303
+ // I believe the following comment is now bogus, having applied to
304
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
305
+ // The way we send data, we cannot use persistent connections, since
306
+ // there will be some "junk" at the end of our request.
307
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
308
+ $this->persistentConnection = false;
309
+ $this->setHeader('Connection', 'close');
310
+ }
311
+ // set timeouts
312
+ if ($connection_timeout != 0) {
313
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
314
+ }
315
+ if ($response_timeout != 0) {
316
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
317
+ }
318
+
319
+ if ($this->scheme == 'https') {
320
+ $this->debug('set cURL SSL verify options');
321
+ // recent versions of cURL turn on peer/host checking by default,
322
+ // while PHP binaries are not compiled with a default location for the
323
+ // CA cert bundle, so disable peer/host checking.
324
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
325
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
326
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
327
+
328
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
329
+ if ($this->authtype == 'certificate') {
330
+ $this->debug('set cURL certificate options');
331
+ if (isset($this->certRequest['cainfofile'])) {
332
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
333
+ }
334
+ if (isset($this->certRequest['verifypeer'])) {
335
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
336
+ } else {
337
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
338
+ }
339
+ if (isset($this->certRequest['verifyhost'])) {
340
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
341
+ } else {
342
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
343
+ }
344
+ if (isset($this->certRequest['sslcertfile'])) {
345
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
346
+ }
347
+ if (isset($this->certRequest['sslkeyfile'])) {
348
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
349
+ }
350
+ if (isset($this->certRequest['passphrase'])) {
351
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
352
+ }
353
+ if (isset($this->certRequest['certpassword'])) {
354
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
355
+ }
356
+ }
357
+ }
358
+ if ($this->authtype && ($this->authtype != 'certificate')) {
359
+ if ($this->username) {
360
+ $this->debug('set cURL username/password');
361
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
362
+ }
363
+ if ($this->authtype == 'basic') {
364
+ $this->debug('set cURL for Basic authentication');
365
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
366
+ }
367
+ if ($this->authtype == 'digest') {
368
+ $this->debug('set cURL for digest authentication');
369
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
370
+ }
371
+ if ($this->authtype == 'ntlm') {
372
+ $this->debug('set cURL for NTLM authentication');
373
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
374
+ }
375
+ }
376
+ if (is_array($this->proxy)) {
377
+ $this->debug('set cURL proxy options');
378
+ if ($this->proxy['port'] != '') {
379
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
380
+ } else {
381
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
382
+ }
383
+ if ($this->proxy['username'] || $this->proxy['password']) {
384
+ $this->debug('set cURL proxy authentication options');
385
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
386
+ if ($this->proxy['authtype'] == 'basic') {
387
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
388
+ }
389
+ if ($this->proxy['authtype'] == 'ntlm') {
390
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
391
+ }
392
+ }
393
+ }
394
+ $this->debug('cURL connection set up');
395
+ return true;
396
+ } else {
397
+ $this->setError('Unknown scheme ' . $this->scheme);
398
+ $this->debug('Unknown scheme ' . $this->scheme);
399
+ return false;
400
+ }
401
+ }
402
+
403
+ /**
404
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
405
+ *
406
+ * @param string $data message data
407
+ * @param integer $timeout set connection timeout in seconds
408
+ * @param integer $response_timeout set response timeout in seconds
409
+ * @param array $cookies cookies to send
410
+ * @return string data
411
+ * @access public
412
+ */
413
+ function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
414
+
415
+ $this->debug('entered send() with data of length: '.strlen($data));
416
+
417
+ $this->tryagain = true;
418
+ $tries = 0;
419
+ while ($this->tryagain) {
420
+ $this->tryagain = false;
421
+ if ($tries++ < 2) {
422
+ // make connnection
423
+ if (!$this->connect($timeout, $response_timeout)){
424
+ return false;
425
+ }
426
+
427
+ // send request
428
+ if (!$this->sendRequest($data, $cookies)){
429
+ return false;
430
+ }
431
+
432
+ // get response
433
+ $respdata = $this->getResponse();
434
+ } else {
435
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
436
+ }
437
+ }
438
+ $this->debug('end of send()');
439
+ return $respdata;
440
+ }
441
+
442
+
443
+ /**
444
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
445
+ *
446
+ * @param string $data message data
447
+ * @param integer $timeout set connection timeout in seconds
448
+ * @param integer $response_timeout set response timeout in seconds
449
+ * @param array $cookies cookies to send
450
+ * @return string data
451
+ * @access public
452
+ * @deprecated
453
+ */
454
+ function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
455
+ return $this->send($data, $timeout, $response_timeout, $cookies);
456
+ }
457
+
458
+ /**
459
+ * if authenticating, set user credentials here
460
+ *
461
+ * @param string $username
462
+ * @param string $password
463
+ * @param string $authtype (basic|digest|certificate|ntlm)
464
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
465
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
466
+ * @access public
467
+ */
468
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
469
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
470
+ $this->appendDebug($this->varDump($digestRequest));
471
+ $this->debug("certRequest=");
472
+ $this->appendDebug($this->varDump($certRequest));
473
+ // cf. RFC 2617
474
+ if ($authtype == 'basic') {
475
+ $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
476
+ } elseif ($authtype == 'digest') {
477
+ if (isset($digestRequest['nonce'])) {
478
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
479
+
480
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
481
+
482
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
483
+ $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
484
+
485
+ // H(A1) = MD5(A1)
486
+ $HA1 = md5($A1);
487
+
488
+ // A2 = Method ":" digest-uri-value
489
+ $A2 = $this->request_method . ':' . $this->digest_uri;
490
+
491
+ // H(A2)
492
+ $HA2 = md5($A2);
493
+
494
+ // KD(secret, data) = H(concat(secret, ":", data))
495
+ // if qop == auth:
496
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
497
+ // ":" nc-value
498
+ // ":" unq(cnonce-value)
499
+ // ":" unq(qop-value)
500
+ // ":" H(A2)
501
+ // ) <">
502
+ // if qop is missing,
503
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
504
+
505
+ $unhashedDigest = '';
506
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
507
+ $cnonce = $nonce;
508
+ if ($digestRequest['qop'] != '') {
509
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
510
+ } else {
511
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
512
+ }
513
+
514
+ $hashedDigest = md5($unhashedDigest);
515
+
516
+ $opaque = '';
517
+ if (isset($digestRequest['opaque'])) {
518
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
519
+ }
520
+
521
+ $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 . '"');
522
+ }
523
+ } elseif ($authtype == 'certificate') {
524
+ $this->certRequest = $certRequest;
525
+ $this->debug('Authorization header not set for certificate');
526
+ } elseif ($authtype == 'ntlm') {
527
+ // do nothing
528
+ $this->debug('Authorization header not set for ntlm');
529
+ }
530
+ $this->username = $username;
531
+ $this->password = $password;
532
+ $this->authtype = $authtype;
533
+ $this->digestRequest = $digestRequest;
534
+ }
535
+
536
+ /**
537
+ * set the soapaction value
538
+ *
539
+ * @param string $soapaction
540
+ * @access public
541
+ */
542
+ function setSOAPAction($soapaction) {
543
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
544
+ }
545
+
546
+ /**
547
+ * use http encoding
548
+ *
549
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
550
+ * @access public
551
+ */
552
+ function setEncoding($enc='gzip, deflate') {
553
+ if (function_exists('gzdeflate')) {
554
+ $this->protocol_version = '1.1';
555
+ $this->setHeader('Accept-Encoding', $enc);
556
+ if (!isset($this->outgoing_headers['Connection'])) {
557
+ $this->setHeader('Connection', 'close');
558
+ $this->persistentConnection = false;
559
+ }
560
+ set_magic_quotes_runtime(0);
561
+ // deprecated
562
+ $this->encoding = $enc;
563
+ }
564
+ }
565
+
566
+ /**
567
+ * set proxy info here
568
+ *
569
+ * @param string $proxyhost use an empty string to remove proxy
570
+ * @param string $proxyport
571
+ * @param string $proxyusername
572
+ * @param string $proxypassword
573
+ * @param string $proxyauthtype (basic|ntlm)
574
+ * @access public
575
+ */
576
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
577
+ if ($proxyhost) {
578
+ $this->proxy = array(
579
+ 'host' => $proxyhost,
580
+ 'port' => $proxyport,
581
+ 'username' => $proxyusername,
582
+ 'password' => $proxypassword,
583
+ 'authtype' => $proxyauthtype
584
+ );
585
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
586
+ $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
587
+ }
588
+ } else {
589
+ $this->debug('remove proxy');
590
+ $proxy = null;
591
+ unsetHeader('Proxy-Authorization');
592
+ }
593
+ }
594
+
595
+
596
+ /**
597
+ * Test if the given string starts with a header that is to be skipped.
598
+ * Skippable headers result from chunked transfer and proxy requests.
599
+ *
600
+ * @param string $data The string to check.
601
+ * @returns boolean Whether a skippable header was found.
602
+ * @access private
603
+ */
604
+ function isSkippableCurlHeader(&$data) {
605
+ $skipHeaders = array( 'HTTP/1.1 100',
606
+ 'HTTP/1.0 301',
607
+ 'HTTP/1.1 301',
608
+ 'HTTP/1.0 302',
609
+ 'HTTP/1.1 302',
610
+ 'HTTP/1.0 401',
611
+ 'HTTP/1.1 401',
612
+ 'HTTP/1.0 200 Connection established');
613
+ foreach ($skipHeaders as $hd) {
614
+ $prefix = substr($data, 0, strlen($hd));
615
+ if ($prefix == $hd) return true;
616
+ }
617
+
618
+ return false;
619
+ }
620
+
621
+ /**
622
+ * decode a string that is encoded w/ "chunked' transfer encoding
623
+ * as defined in RFC2068 19.4.6
624
+ *
625
+ * @param string $buffer
626
+ * @param string $lb
627
+ * @returns string
628
+ * @access public
629
+ * @deprecated
630
+ */
631
+ function decodeChunked($buffer, $lb){
632
+ // length := 0
633
+ $length = 0;
634
+ $new = '';
635
+
636
+ // read chunk-size, chunk-extension (if any) and CRLF
637
+ // get the position of the linebreak
638
+ $chunkend = strpos($buffer, $lb);
639
+ if ($chunkend == FALSE) {
640
+ $this->debug('no linebreak found in decodeChunked');
641
+ return $new;
642
+ }
643
+ $temp = substr($buffer,0,$chunkend);
644
+ $chunk_size = hexdec( trim($temp) );
645
+ $chunkstart = $chunkend + strlen($lb);
646
+ // while (chunk-size > 0) {
647
+ while ($chunk_size > 0) {
648
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
649
+ $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
650
+
651
+ // Just in case we got a broken connection
652
+ if ($chunkend == FALSE) {
653
+ $chunk = substr($buffer,$chunkstart);
654
+ // append chunk-data to entity-body
655
+ $new .= $chunk;
656
+ $length += strlen($chunk);
657
+ break;
658
+ }
659
+
660
+ // read chunk-data and CRLF
661
+ $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
662
+ // append chunk-data to entity-body
663
+ $new .= $chunk;
664
+ // length := length + chunk-size
665
+ $length += strlen($chunk);
666
+ // read chunk-size and CRLF
667
+ $chunkstart = $chunkend + strlen($lb);
668
+
669
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
670
+ if ($chunkend == FALSE) {
671
+ break; //Just in case we got a broken connection
672
+ }
673
+ $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
674
+ $chunk_size = hexdec( trim($temp) );
675
+ $chunkstart = $chunkend;
676
+ }
677
+ return $new;
678
+ }
679
+
680
+ /**
681
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
682
+ *
683
+ * @param string $data HTTP body
684
+ * @param string $cookie_str data for HTTP Cookie header
685
+ * @return void
686
+ * @access private
687
+ */
688
+ function buildPayload($data, $cookie_str = '') {
689
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
690
+ // as is the Content-Length header, but these are still created as
691
+ // debugging guides.
692
+
693
+ // add content-length header
694
+ $this->setHeader('Content-Length', strlen($data));
695
+
696
+ // start building outgoing payload:
697
+ if ($this->proxy) {
698
+ $uri = $this->url;
699
+ } else {
700
+ $uri = $this->uri;
701
+ }
702
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
703
+ $this->debug("HTTP request: $req");
704
+ $this->outgoing_payload = "$req\r\n";
705
+
706
+ // loop thru headers, serializing
707
+ foreach($this->outgoing_headers as $k => $v){
708
+ $hdr = $k.': '.$v;
709
+ $this->debug("HTTP header: $hdr");
710
+ $this->outgoing_payload .= "$hdr\r\n";
711
+ }
712
+
713
+ // add any cookies
714
+ if ($cookie_str != '') {
715
+ $hdr = 'Cookie: '.$cookie_str;
716
+ $this->debug("HTTP header: $hdr");
717
+ $this->outgoing_payload .= "$hdr\r\n";
718
+ }
719
+
720
+ // header/body separator
721
+ $this->outgoing_payload .= "\r\n";
722
+
723
+ // add data
724
+ $this->outgoing_payload .= $data;
725
+ }
726
+
727
+ /**
728
+ * sends the SOAP request via HTTP[S]
729
+ *
730
+ * @param string $data message data
731
+ * @param array $cookies cookies to send
732
+ * @return boolean true if OK, false if problem
733
+ * @access private
734
+ */
735
+ function sendRequest($data, $cookies = NULL) {
736
+ // build cookie string
737
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
738
+
739
+ // build payload
740
+ $this->buildPayload($data, $cookie_str);
741
+
742
+ if ($this->io_method() == 'socket') {
743
+ // send payload
744
+ if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
745
+ $this->setError('couldn\'t write message data to socket');
746
+ $this->debug('couldn\'t write message data to socket');
747
+ return false;
748
+ }
749
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
750
+ return true;
751
+ } else if ($this->io_method() == 'curl') {
752
+ // set payload
753
+ // cURL does say this should only be the verb, and in fact it
754
+ // turns out that the URI and HTTP version are appended to this, which
755
+ // some servers refuse to work with (so we no longer use this method!)
756
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
757
+ $curl_headers = array();
758
+ foreach($this->outgoing_headers as $k => $v){
759
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
760
+ $this->debug("Skip cURL header $k: $v");
761
+ } else {
762
+ $curl_headers[] = "$k: $v";
763
+ }
764
+ }
765
+ if ($cookie_str != '') {
766
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
767
+ }
768
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
769
+ $this->debug('set cURL HTTP headers');
770
+ if ($this->request_method == "POST") {
771
+ $this->setCurlOption(CURLOPT_POST, 1);
772
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
773
+ $this->debug('set cURL POST data');
774
+ } else {
775
+ }
776
+ // insert custom user-set cURL options
777
+ foreach ($this->ch_options as $key => $val) {
778
+ $this->setCurlOption($key, $val);
779
+ }
780
+
781
+ $this->debug('set cURL payload');
782
+ return true;
783
+ }
784
+ }
785
+
786
+ /**
787
+ * gets the SOAP response via HTTP[S]
788
+ *
789
+ * @return string the response (also sets member variables like incoming_payload)
790
+ * @access private
791
+ */
792
+ function getResponse(){
793
+ $this->incoming_payload = '';
794
+
795
+ if ($this->io_method() == 'socket') {
796
+ // loop until headers have been retrieved
797
+ $data = '';
798
+ while (!isset($lb)){
799
+
800
+ // We might EOF during header read.
801
+ if(feof($this->fp)) {
802
+ $this->incoming_payload = $data;
803
+ $this->debug('found no headers before EOF after length ' . strlen($data));
804
+ $this->debug("received before EOF:\n" . $data);
805
+ $this->setError('server failed to send headers');
806
+ return false;
807
+ }
808
+
809
+ $tmp = fgets($this->fp, 256);
810
+ $tmplen = strlen($tmp);
811
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
812
+
813
+ if ($tmplen == 0) {
814
+ $this->incoming_payload = $data;
815
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
816
+ $this->debug("read before timeout: " . $data);
817
+ $this->setError('socket read of headers timed out');
818
+ return false;
819
+ }
820
+
821
+ $data .= $tmp;
822
+ $pos = strpos($data,"\r\n\r\n");
823
+ if($pos > 1){
824
+ $lb = "\r\n";
825
+ } else {
826
+ $pos = strpos($data,"\n\n");
827
+ if($pos > 1){
828
+ $lb = "\n";
829
+ }
830
+ }
831
+ // remove 100 headers
832
+ if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
833
+ unset($lb);
834
+ $data = '';
835
+ }//
836
+ }
837
+ // store header data
838
+ $this->incoming_payload .= $data;
839
+ $this->debug('found end of headers after length ' . strlen($data));
840
+ // process headers
841
+ $header_data = trim(substr($data,0,$pos));
842
+ $header_array = explode($lb,$header_data);
843
+ $this->incoming_headers = array();
844
+ $this->incoming_cookies = array();
845
+ foreach($header_array as $header_line){
846
+ $arr = explode(':',$header_line, 2);
847
+ if(count($arr) > 1){
848
+ $header_name = strtolower(trim($arr[0]));
849
+ $this->incoming_headers[$header_name] = trim($arr[1]);
850
+ if ($header_name == 'set-cookie') {
851
+ // TODO: allow multiple cookies from parseCookie
852
+ $cookie = $this->parseCookie(trim($arr[1]));
853
+ if ($cookie) {
854
+ $this->incoming_cookies[] = $cookie;
855
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
856
+ } else {
857
+ $this->debug('did not find cookie in ' . trim($arr[1]));
858
+ }
859
+ }
860
+ } else if (isset($header_name)) {
861
+ // append continuation line to previous header
862
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
863
+ }
864
+ }
865
+
866
+ // loop until msg has been received
867
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
868
+ $content_length = 2147483647; // ignore any content-length header
869
+ $chunked = true;
870
+ $this->debug("want to read chunked content");
871
+ } elseif (isset($this->incoming_headers['content-length'])) {
872
+ $content_length = $this->incoming_headers['content-length'];
873
+ $chunked = false;
874
+ $this->debug("want to read content of length $content_length");
875
+ } else {
876
+ $content_length = 2147483647;
877
+ $chunked = false;
878
+ $this->debug("want to read content to EOF");
879
+ }
880
+ $data = '';
881
+ do {
882
+ if ($chunked) {
883
+ $tmp = fgets($this->fp, 256);
884
+ $tmplen = strlen($tmp);
885
+ $this->debug("read chunk line of $tmplen bytes");
886
+ if ($tmplen == 0) {
887
+ $this->incoming_payload = $data;
888
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
889
+ $this->debug("read before timeout:\n" . $data);
890
+ $this->setError('socket read of chunk length timed out');
891
+ return false;
892
+ }
893
+ $content_length = hexdec(trim($tmp));
894
+ $this->debug("chunk length $content_length");
895
+ }
896
+ $strlen = 0;
897
+ while (($strlen < $content_length) && (!feof($this->fp))) {
898
+ $readlen = min(8192, $content_length - $strlen);
899
+ $tmp = fread($this->fp, $readlen);
900
+ $tmplen = strlen($tmp);
901
+ $this->debug("read buffer of $tmplen bytes");
902
+ if (($tmplen == 0) && (!feof($this->fp))) {
903
+ $this->incoming_payload = $data;
904
+ $this->debug('socket read of body timed out after length ' . strlen($data));
905
+ $this->debug("read before timeout:\n" . $data);
906
+ $this->setError('socket read of body timed out');
907
+ return false;
908
+ }
909
+ $strlen += $tmplen;
910
+ $data .= $tmp;
911
+ }
912
+ if ($chunked && ($content_length > 0)) {
913
+ $tmp = fgets($this->fp, 256);
914
+ $tmplen = strlen($tmp);
915
+ $this->debug("read chunk terminator of $tmplen bytes");
916
+ if ($tmplen == 0) {
917
+ $this->incoming_payload = $data;
918
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
919
+ $this->debug("read before timeout:\n" . $data);
920
+ $this->setError('socket read of chunk terminator timed out');
921
+ return false;
922
+ }
923
+ }
924
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
925
+ if (feof($this->fp)) {
926
+ $this->debug('read to EOF');
927
+ }
928
+ $this->debug('read body of length ' . strlen($data));
929
+ $this->incoming_payload .= $data;
930
+ $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
931
+
932
+ // close filepointer
933
+ if(
934
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
935
+ (! $this->persistentConnection) || feof($this->fp)){
936
+ fclose($this->fp);
937
+ $this->fp = false;
938
+ $this->debug('closed socket');
939
+ }
940
+
941
+ // connection was closed unexpectedly
942
+ if($this->incoming_payload == ''){
943
+ $this->setError('no response from server');
944
+ return false;
945
+ }
946
+
947
+ // decode transfer-encoding
948
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
949
+ // if(!$data = $this->decodeChunked($data, $lb)){
950
+ // $this->setError('Decoding of chunked data failed');
951
+ // return false;
952
+ // }
953
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
954
+ // set decoded payload
955
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
956
+ // }
957
+
958
+ } else if ($this->io_method() == 'curl') {
959
+ // send and receive
960
+ $this->debug('send and receive with cURL');
961
+ $this->incoming_payload = curl_exec($this->ch);
962
+ $data = $this->incoming_payload;
963
+
964
+ $cErr = curl_error($this->ch);
965
+ if ($cErr != '') {
966
+ $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
967
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
968
+ foreach(curl_getinfo($this->ch) as $k => $v){
969
+ $err .= "$k: $v<br>";
970
+ }
971
+ $this->debug($err);
972
+ $this->setError($err);
973
+ curl_close($this->ch);
974
+ return false;
975
+ } else {
976
+ //echo '<pre>';
977
+ //var_dump(curl_getinfo($this->ch));
978
+ //echo '</pre>';
979
+ }
980
+ // close curl
981
+ $this->debug('No cURL error, closing cURL');
982
+ curl_close($this->ch);
983
+
984
+ // try removing skippable headers
985
+ $savedata = $data;
986
+ while ($this->isSkippableCurlHeader($data)) {
987
+ $this->debug("Found HTTP header to skip");
988
+ if ($pos = strpos($data,"\r\n\r\n")) {
989
+ $data = ltrim(substr($data,$pos));
990
+ } elseif($pos = strpos($data,"\n\n") ) {
991
+ $data = ltrim(substr($data,$pos));
992
+ }
993
+ }
994
+
995
+ if ($data == '') {
996
+ // have nothing left; just remove 100 header(s)
997
+ $data = $savedata;
998
+ while (ereg('^HTTP/1.1 100',$data)) {
999
+ if ($pos = strpos($data,"\r\n\r\n")) {
1000
+ $data = ltrim(substr($data,$pos));
1001
+ } elseif($pos = strpos($data,"\n\n") ) {
1002
+ $data = ltrim(substr($data,$pos));
1003
+ }
1004
+ }
1005
+ }
1006
+
1007
+ // separate content from HTTP headers
1008
+ if ($pos = strpos($data,"\r\n\r\n")) {
1009
+ $lb = "\r\n";
1010
+ } elseif( $pos = strpos($data,"\n\n")) {
1011
+ $lb = "\n";
1012
+ } else {
1013
+ $this->debug('no proper separation of headers and document');
1014
+ $this->setError('no proper separation of headers and document');
1015
+ return false;
1016
+ }
1017
+ $header_data = trim(substr($data,0,$pos));
1018
+ $header_array = explode($lb,$header_data);
1019
+ $data = ltrim(substr($data,$pos));
1020
+ $this->debug('found proper separation of headers and document');
1021
+ $this->debug('cleaned data, stringlen: '.strlen($data));
1022
+ // clean headers
1023
+ foreach ($header_array as $header_line) {
1024
+ $arr = explode(':',$header_line,2);
1025
+ if(count($arr) > 1){
1026
+ $header_name = strtolower(trim($arr[0]));
1027
+ $this->incoming_headers[$header_name] = trim($arr[1]);
1028
+ if ($header_name == 'set-cookie') {
1029
+ // TODO: allow multiple cookies from parseCookie
1030
+ $cookie = $this->parseCookie(trim($arr[1]));
1031
+ if ($cookie) {
1032
+ $this->incoming_cookies[] = $cookie;
1033
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
1034
+ } else {
1035
+ $this->debug('did not find cookie in ' . trim($arr[1]));
1036
+ }
1037
+ }
1038
+ } else if (isset($header_name)) {
1039
+ // append continuation line to previous header
1040
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
1041
+ }
1042
+ }
1043
+ }
1044
+
1045
+ $this->response_status_line = $header_array[0];
1046
+ $arr = explode(' ', $this->response_status_line, 3);
1047
+ $http_version = $arr[0];
1048
+ $http_status = intval($arr[1]);
1049
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
1050
+
1051
+ // see if we need to resend the request with http digest authentication
1052
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
1053
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
1054
+ $this->setURL($this->incoming_headers['location']);
1055
+ $this->tryagain = true;
1056
+ return false;
1057
+ }
1058
+
1059
+ // see if we need to resend the request with http digest authentication
1060
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
1061
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
1062
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
1063
+ $this->debug('Server wants digest authentication');
1064
+ // remove "Digest " from our elements
1065
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
1066
+
1067
+ // parse elements into array
1068
+ $digestElements = explode(',', $digestString);
1069
+ foreach ($digestElements as $val) {
1070
+ $tempElement = explode('=', trim($val), 2);
1071
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
1072
+ }
1073
+
1074
+ // should have (at least) qop, realm, nonce
1075
+ if (isset($digestRequest['nonce'])) {
1076
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
1077
+ $this->tryagain = true;
1078
+ return false;
1079
+ }
1080
+ }
1081
+ $this->debug('HTTP authentication failed');
1082
+ $this->setError('HTTP authentication failed');
1083
+ return false;
1084
+ }
1085
+
1086
+ if (
1087
+ ($http_status >= 300 && $http_status <= 307) ||
1088
+ ($http_status >= 400 && $http_status <= 417) ||
1089
+ ($http_status >= 501 && $http_status <= 505)
1090
+ ) {
1091
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
1092
+ return false;
1093
+ }
1094
+
1095
+ // decode content-encoding
1096
+ if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
1097
+ if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
1098
+ // if decoding works, use it. else assume data wasn't gzencoded
1099
+ if(function_exists('gzinflate')){
1100
+ //$timer->setMarker('starting decoding of gzip/deflated content');
1101
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
1102
+ // this means there are no Zlib headers, although there should be
1103
+ $this->debug('The gzinflate function exists');
1104
+ $datalen = strlen($data);
1105
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
1106
+ if ($degzdata = @gzinflate($data)) {
1107
+ $data = $degzdata;
1108
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
1109
+ if (strlen($data) < $datalen) {
1110
+ // test for the case that the payload has been compressed twice
1111
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
1112
+ if ($degzdata = @gzinflate($data)) {
1113
+ $data = $degzdata;
1114
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
1115
+ }
1116
+ }
1117
+ } else {
1118
+ $this->debug('Error using gzinflate to inflate the payload');
1119
+ $this->setError('Error using gzinflate to inflate the payload');
1120
+ }
1121
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
1122
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
1123
+ $data = $degzdata;
1124
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
1125
+ if (strlen($data) < $datalen) {
1126
+ // test for the case that the payload has been compressed twice
1127
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
1128
+ if ($degzdata = @gzinflate(substr($data, 10))) {
1129
+ $data = $degzdata;
1130
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
1131
+ }
1132
+ }
1133
+ } else {
1134
+ $this->debug('Error using gzinflate to un-gzip the payload');
1135
+ $this->setError('Error using gzinflate to un-gzip the payload');
1136
+ }
1137
+ }
1138
+ //$timer->setMarker('finished decoding of gzip/deflated content');
1139
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
1140
+ // set decoded payload
1141
+ $this->incoming_payload = $header_data.$lb.$lb.$data;
1142
+ } else {
1143
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
1144
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
1145
+ }
1146
+ } else {
1147
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
1148
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
1149
+ }
1150
+ } else {
1151
+ $this->debug('No Content-Encoding header');
1152
+ }
1153
+
1154
+ if(strlen($data) == 0){
1155
+ $this->debug('no data after headers!');
1156
+ $this->setError('no data present after HTTP headers');
1157
+ return false;
1158
+ }
1159
+
1160
+ return $data;
1161
+ }
1162
+
1163
+ /**
1164
+ * sets the content-type for the SOAP message to be sent
1165
+ *
1166
+ * @param string $type the content type, MIME style
1167
+ * @param mixed $charset character set used for encoding (or false)
1168
+ * @access public
1169
+ */
1170
+ function setContentType($type, $charset = false) {
1171
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
1172
+ }
1173
+
1174
+ /**
1175
+ * specifies that an HTTP persistent connection should be used
1176
+ *
1177
+ * @return boolean whether the request was honored by this method.
1178
+ * @access public
1179
+ */
1180
+ function usePersistentConnection(){
1181
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
1182
+ return false;
1183
+ }
1184
+ $this->protocol_version = '1.1';
1185
+ $this->persistentConnection = true;
1186
+ $this->setHeader('Connection', 'Keep-Alive');
1187
+ return true;
1188
+ }
1189
+
1190
+ /**
1191
+ * parse an incoming Cookie into it's parts
1192
+ *
1193
+ * @param string $cookie_str content of cookie
1194
+ * @return array with data of that cookie
1195
+ * @access private
1196
+ */
1197
+ /*
1198
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
1199
+ */
1200
+ function parseCookie($cookie_str) {
1201
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
1202
+ $data = split(';', $cookie_str);
1203
+ $value_str = $data[0];
1204
+
1205
+ $cookie_param = 'domain=';
1206
+ $start = strpos($cookie_str, $cookie_param);
1207
+ if ($start > 0) {
1208
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
1209
+ $domain = substr($domain, 0, strpos($domain, ';'));
1210
+ } else {
1211
+ $domain = '';
1212
+ }
1213
+
1214
+ $cookie_param = 'expires=';
1215
+ $start = strpos($cookie_str, $cookie_param);
1216
+ if ($start > 0) {
1217
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
1218
+ $expires = substr($expires, 0, strpos($expires, ';'));
1219
+ } else {
1220
+ $expires = '';
1221
+ }
1222
+
1223
+ $cookie_param = 'path=';
1224
+ $start = strpos($cookie_str, $cookie_param);
1225
+ if ( $start > 0 ) {
1226
+ $path = substr($cookie_str, $start + strlen($cookie_param));
1227
+ $path = substr($path, 0, strpos($path, ';'));
1228
+ } else {
1229
+ $path = '/';
1230
+ }
1231
+
1232
+ $cookie_param = ';secure;';
1233
+ if (strpos($cookie_str, $cookie_param) !== FALSE) {
1234
+ $secure = true;
1235
+ } else {
1236
+ $secure = false;
1237
+ }
1238
+
1239
+ $sep_pos = strpos($value_str, '=');
1240
+
1241
+ if ($sep_pos) {
1242
+ $name = substr($value_str, 0, $sep_pos);
1243
+ $value = substr($value_str, $sep_pos + 1);
1244
+ $cookie= array( 'name' => $name,
1245
+ 'value' => $value,
1246
+ 'domain' => $domain,
1247
+ 'path' => $path,
1248
+ 'expires' => $expires,
1249
+ 'secure' => $secure
1250
+ );
1251
+ return $cookie;
1252
+ }
1253
+ return false;
1254
+ }
1255
+
1256
+ /**
1257
+ * sort out cookies for the current request
1258
+ *
1259
+ * @param array $cookies array with all cookies
1260
+ * @param boolean $secure is the send-content secure or not?
1261
+ * @return string for Cookie-HTTP-Header
1262
+ * @access private
1263
+ */
1264
+ function getCookiesForRequest($cookies, $secure=false) {
1265
+ $cookie_str = '';
1266
+ if ((! is_null($cookies)) && (is_array($cookies))) {
1267
+ foreach ($cookies as $cookie) {
1268
+ if (! is_array($cookie)) {
1269
+ continue;
1270
+ }
1271
+ $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
1272
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
1273
+ if (strtotime($cookie['expires']) <= time()) {
1274
+ $this->debug('cookie has expired');
1275
+ continue;
1276
+ }
1277
+ }
1278
+ if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
1279
+ $domain = preg_quote($cookie['domain']);
1280
+ if (! preg_match("'.*$domain$'i", $this->host)) {
1281
+ $this->debug('cookie has different domain');
1282
+ continue;
1283
+ }
1284
+ }
1285
+ if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
1286
+ $path = preg_quote($cookie['path']);
1287
+ if (! preg_match("'^$path.*'i", $this->path)) {
1288
+ $this->debug('cookie is for a different path');
1289
+ continue;
1290
+ }
1291
+ }
1292
+ if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
1293
+ $this->debug('cookie is secure, transport is not');
1294
+ continue;
1295
+ }
1296
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
1297
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
1298
+ }
1299
+ }
1300
+ return $cookie_str;
1301
+ }
1302
+ }
1303
+
1304
+
1305
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soap_val.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ * For creating serializable abstractions of native PHP types. This class
8
+ * allows element name/namespace, XSD type, and XML attributes to be
9
+ * associated with a value. This is extremely useful when WSDL is not
10
+ * used, but is also useful when WSDL is used with polymorphic types, including
11
+ * xsd:anyType and user-defined types.
12
+ *
13
+ * @author Dietrich Ayala <dietrich@ganx4.com>
14
+ * @version $Id: class.soap_val.php,v 1.11 2007/04/06 13:56:32 snichol Exp $
15
+ * @access public
16
+ */
17
+ class soapval extends nusoap_base {
18
+ /**
19
+ * The XML element name
20
+ *
21
+ * @var string
22
+ * @access private
23
+ */
24
+ var $name;
25
+ /**
26
+ * The XML type name (string or false)
27
+ *
28
+ * @var mixed
29
+ * @access private
30
+ */
31
+ var $type;
32
+ /**
33
+ * The PHP value
34
+ *
35
+ * @var mixed
36
+ * @access private
37
+ */
38
+ var $value;
39
+ /**
40
+ * The XML element namespace (string or false)
41
+ *
42
+ * @var mixed
43
+ * @access private
44
+ */
45
+ var $element_ns;
46
+ /**
47
+ * The XML type namespace (string or false)
48
+ *
49
+ * @var mixed
50
+ * @access private
51
+ */
52
+ var $type_ns;
53
+ /**
54
+ * The XML element attributes (array or false)
55
+ *
56
+ * @var mixed
57
+ * @access private
58
+ */
59
+ var $attributes;
60
+
61
+ /**
62
+ * constructor
63
+ *
64
+ * @param string $name optional name
65
+ * @param mixed $type optional type name
66
+ * @param mixed $value optional value
67
+ * @param mixed $element_ns optional namespace of value
68
+ * @param mixed $type_ns optional namespace of type
69
+ * @param mixed $attributes associative array of attributes to add to element serialization
70
+ * @access public
71
+ */
72
+ function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
73
+ parent::nusoap_base();
74
+ $this->name = $name;
75
+ $this->type = $type;
76
+ $this->value = $value;
77
+ $this->element_ns = $element_ns;
78
+ $this->type_ns = $type_ns;
79
+ $this->attributes = $attributes;
80
+ }
81
+
82
+ /**
83
+ * return serialized value
84
+ *
85
+ * @param string $use The WSDL use value (encoded|literal)
86
+ * @return string XML data
87
+ * @access public
88
+ */
89
+ function serialize($use='encoded') {
90
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
91
+ }
92
+
93
+ /**
94
+ * decodes a soapval object into a PHP native type
95
+ *
96
+ * @return mixed
97
+ * @access public
98
+ */
99
+ function decode(){
100
+ return $this->value;
101
+ }
102
+ }
103
+
104
+
105
+
106
+
107
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.soapclient.php ADDED
@@ -0,0 +1,977 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ *
8
+ * [nu]soapclient higher level class for easy usage.
9
+ *
10
+ * usage:
11
+ *
12
+ * // instantiate client with server info
13
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
14
+ *
15
+ * // call method, get results
16
+ * echo $soapclient->call( string methodname [ ,array parameters] );
17
+ *
18
+ * // bye bye client
19
+ * unset($soapclient);
20
+ *
21
+ * @author Dietrich Ayala <dietrich@ganx4.com>
22
+ * @author Scott Nichol <snichol@users.sourceforge.net>
23
+ * @version $Id: class.soapclient.php,v 1.64 2007/10/22 01:15:17 snichol Exp $
24
+ * @access public
25
+ */
26
+ class nusoap_client extends nusoap_base {
27
+
28
+ var $username = ''; // Username for HTTP authentication
29
+ var $password = ''; // Password for HTTP authentication
30
+ var $authtype = ''; // Type of HTTP authentication
31
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
32
+ var $requestHeaders = false; // SOAP headers in request (text)
33
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
34
+ var $responseHeader = NULL; // SOAP Header from response (parsed)
35
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
36
+ var $endpoint;
37
+ var $forceEndpoint = ''; // overrides WSDL endpoint
38
+ var $proxyhost = '';
39
+ var $proxyport = '';
40
+ var $proxyusername = '';
41
+ var $proxypassword = '';
42
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
43
+ var $http_encoding = false;
44
+ var $timeout = 0; // HTTP connection timeout
45
+ var $response_timeout = 30; // HTTP response timeout
46
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
47
+ var $persistentConnection = false;
48
+ var $defaultRpcParams = false; // This is no longer used
49
+ var $request = ''; // HTTP request
50
+ var $response = ''; // HTTP response
51
+ var $responseData = ''; // SOAP payload of response
52
+ var $cookies = array(); // Cookies from response or for request
53
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
54
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
55
+ var $curl_options = array(); // User-specified cURL options
56
+ var $bindingType = ''; // WSDL operation binding type
57
+ var $use_curl = false; // whether to always try to use cURL
58
+
59
+ /*
60
+ * fault related variables
61
+ */
62
+ /**
63
+ * @var fault
64
+ * @access public
65
+ */
66
+ var $fault;
67
+ /**
68
+ * @var faultcode
69
+ * @access public
70
+ */
71
+ var $faultcode;
72
+ /**
73
+ * @var faultstring
74
+ * @access public
75
+ */
76
+ var $faultstring;
77
+ /**
78
+ * @var faultdetail
79
+ * @access public
80
+ */
81
+ var $faultdetail;
82
+
83
+ /**
84
+ * constructor
85
+ *
86
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
87
+ * @param bool $wsdl optional, set to true if using WSDL
88
+ * @param int $portName optional portName in WSDL document
89
+ * @param string $proxyhost
90
+ * @param string $proxyport
91
+ * @param string $proxyusername
92
+ * @param string $proxypassword
93
+ * @param integer $timeout set the connection timeout
94
+ * @param integer $response_timeout set the response timeout
95
+ * @access public
96
+ */
97
+ function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
98
+ parent::nusoap_base();
99
+ $this->endpoint = $endpoint;
100
+ $this->proxyhost = $proxyhost;
101
+ $this->proxyport = $proxyport;
102
+ $this->proxyusername = $proxyusername;
103
+ $this->proxypassword = $proxypassword;
104
+ $this->timeout = $timeout;
105
+ $this->response_timeout = $response_timeout;
106
+
107
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
108
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
109
+
110
+ // make values
111
+ if($wsdl){
112
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
113
+ $this->wsdl = $endpoint;
114
+ $this->endpoint = $this->wsdl->wsdl;
115
+ $this->wsdlFile = $this->endpoint;
116
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
117
+ $this->checkWSDL();
118
+ } else {
119
+ $this->wsdlFile = $this->endpoint;
120
+ $this->wsdl = null;
121
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
122
+ }
123
+ $this->endpointType = 'wsdl';
124
+ } else {
125
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
126
+ $this->endpointType = 'soap';
127
+ }
128
+ }
129
+
130
+ /**
131
+ * calls method, returns PHP native type
132
+ *
133
+ * @param string $operation SOAP server URL or path
134
+ * @param mixed $params An array, associative or simple, of the parameters
135
+ * for the method call, or a string that is the XML
136
+ * for the call. For rpc style, this call will
137
+ * wrap the XML in a tag named after the method, as
138
+ * well as the SOAP Envelope and Body. For document
139
+ * style, this will only wrap with the Envelope and Body.
140
+ * IMPORTANT: when using an array with document style,
141
+ * in which case there
142
+ * is really one parameter, the root of the fragment
143
+ * used in the call, which encloses what programmers
144
+ * normally think of parameters. A parameter array
145
+ * *must* include the wrapper.
146
+ * @param string $namespace optional method namespace (WSDL can override)
147
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
148
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
149
+ * @param boolean $rpcParams optional (no longer used)
150
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
151
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
152
+ * @return mixed response from SOAP call
153
+ * @access public
154
+ */
155
+ function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
156
+ $this->operation = $operation;
157
+ $this->fault = false;
158
+ $this->setError('');
159
+ $this->request = '';
160
+ $this->response = '';
161
+ $this->responseData = '';
162
+ $this->faultstring = '';
163
+ $this->faultcode = '';
164
+ $this->opData = array();
165
+
166
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
167
+ $this->appendDebug('params=' . $this->varDump($params));
168
+ $this->appendDebug('headers=' . $this->varDump($headers));
169
+ if ($headers) {
170
+ $this->requestHeaders = $headers;
171
+ }
172
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
173
+ $this->loadWSDL();
174
+ if ($this->getError())
175
+ return false;
176
+ }
177
+ // serialize parameters
178
+ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
179
+ // use WSDL for operation
180
+ $this->opData = $opData;
181
+ $this->debug("found operation");
182
+ $this->appendDebug('opData=' . $this->varDump($opData));
183
+ if (isset($opData['soapAction'])) {
184
+ $soapAction = $opData['soapAction'];
185
+ }
186
+ if (! $this->forceEndpoint) {
187
+ $this->endpoint = $opData['endpoint'];
188
+ } else {
189
+ $this->endpoint = $this->forceEndpoint;
190
+ }
191
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
192
+ $style = $opData['style'];
193
+ $use = $opData['input']['use'];
194
+ // add ns to ns array
195
+ if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
196
+ $nsPrefix = 'ns' . rand(1000, 9999);
197
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
198
+ }
199
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
200
+ // serialize payload
201
+ if (is_string($params)) {
202
+ $this->debug("serializing param string for WSDL operation $operation");
203
+ $payload = $params;
204
+ } elseif (is_array($params)) {
205
+ $this->debug("serializing param array for WSDL operation $operation");
206
+ $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
207
+ } else {
208
+ $this->debug('params must be array or string');
209
+ $this->setError('params must be array or string');
210
+ return false;
211
+ }
212
+ $usedNamespaces = $this->wsdl->usedNamespaces;
213
+ if (isset($opData['input']['encodingStyle'])) {
214
+ $encodingStyle = $opData['input']['encodingStyle'];
215
+ } else {
216
+ $encodingStyle = '';
217
+ }
218
+ $this->appendDebug($this->wsdl->getDebug());
219
+ $this->wsdl->clearDebug();
220
+ if ($errstr = $this->wsdl->getError()) {
221
+ $this->debug('got wsdl error: '.$errstr);
222
+ $this->setError('wsdl error: '.$errstr);
223
+ return false;
224
+ }
225
+ } elseif($this->endpointType == 'wsdl') {
226
+ // operation not in WSDL
227
+ $this->appendDebug($this->wsdl->getDebug());
228
+ $this->wsdl->clearDebug();
229
+ $this->setError( 'operation '.$operation.' not present.');
230
+ $this->debug("operation '$operation' not present.");
231
+ return false;
232
+ } else {
233
+ // no WSDL
234
+ //$this->namespaces['ns1'] = $namespace;
235
+ $nsPrefix = 'ns' . rand(1000, 9999);
236
+ // serialize
237
+ $payload = '';
238
+ if (is_string($params)) {
239
+ $this->debug("serializing param string for operation $operation");
240
+ $payload = $params;
241
+ } elseif (is_array($params)) {
242
+ $this->debug("serializing param array for operation $operation");
243
+ foreach($params as $k => $v){
244
+ $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
245
+ }
246
+ } else {
247
+ $this->debug('params must be array or string');
248
+ $this->setError('params must be array or string');
249
+ return false;
250
+ }
251
+ $usedNamespaces = array();
252
+ if ($use == 'encoded') {
253
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
254
+ } else {
255
+ $encodingStyle = '';
256
+ }
257
+ }
258
+ // wrap RPC calls with method element
259
+ if ($style == 'rpc') {
260
+ if ($use == 'literal') {
261
+ $this->debug("wrapping RPC request with literal method element");
262
+ if ($namespace) {
263
+ // 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
264
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
265
+ $payload .
266
+ "</$nsPrefix:$operation>";
267
+ } else {
268
+ $payload = "<$operation>" . $payload . "</$operation>";
269
+ }
270
+ } else {
271
+ $this->debug("wrapping RPC request with encoded method element");
272
+ if ($namespace) {
273
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
274
+ $payload .
275
+ "</$nsPrefix:$operation>";
276
+ } else {
277
+ $payload = "<$operation>" .
278
+ $payload .
279
+ "</$operation>";
280
+ }
281
+ }
282
+ }
283
+ // serialize envelope
284
+ $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
285
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
286
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
287
+ // send
288
+ $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
289
+ if($errstr = $this->getError()){
290
+ $this->debug('Error: '.$errstr);
291
+ return false;
292
+ } else {
293
+ $this->return = $return;
294
+ $this->debug('sent message successfully and got a(n) '.gettype($return));
295
+ $this->appendDebug('return=' . $this->varDump($return));
296
+
297
+ // fault?
298
+ if(is_array($return) && isset($return['faultcode'])){
299
+ $this->debug('got fault');
300
+ $this->setError($return['faultcode'].': '.$return['faultstring']);
301
+ $this->fault = true;
302
+ foreach($return as $k => $v){
303
+ $this->$k = $v;
304
+ $this->debug("$k = $v<br>");
305
+ }
306
+ return $return;
307
+ } elseif ($style == 'document') {
308
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
309
+ // we are only going to return the first part here...sorry about that
310
+ return $return;
311
+ } else {
312
+ // array of return values
313
+ if(is_array($return)){
314
+ // multiple 'out' parameters, which we return wrapped up
315
+ // in the array
316
+ if(sizeof($return) > 1){
317
+ return $return;
318
+ }
319
+ // single 'out' parameter (normally the return value)
320
+ $return = array_shift($return);
321
+ $this->debug('return shifted value: ');
322
+ $this->appendDebug($this->varDump($return));
323
+ return $return;
324
+ // nothing returned (ie, echoVoid)
325
+ } else {
326
+ return "";
327
+ }
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * check WSDL passed as an instance or pulled from an endpoint
334
+ *
335
+ * @access private
336
+ */
337
+ function checkWSDL() {
338
+ $this->appendDebug($this->wsdl->getDebug());
339
+ $this->wsdl->clearDebug();
340
+ $this->debug('checkWSDL');
341
+ // catch errors
342
+ if ($errstr = $this->wsdl->getError()) {
343
+ $this->debug('got wsdl error: '.$errstr);
344
+ $this->setError('wsdl error: '.$errstr);
345
+ } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
346
+ $this->bindingType = 'soap';
347
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
348
+ } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
349
+ $this->bindingType = 'soap12';
350
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
351
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
352
+ } else {
353
+ $this->debug('getOperations returned false');
354
+ $this->setError('no operations defined in the WSDL document!');
355
+ }
356
+ }
357
+
358
+ /**
359
+ * instantiate wsdl object and parse wsdl file
360
+ *
361
+ * @access public
362
+ */
363
+ function loadWSDL() {
364
+ $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
365
+ $this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
366
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
367
+ $this->wsdl->fetchWSDL($this->wsdlFile);
368
+ $this->checkWSDL();
369
+ }
370
+
371
+ /**
372
+ * get available data pertaining to an operation
373
+ *
374
+ * @param string $operation operation name
375
+ * @return array array of data pertaining to the operation
376
+ * @access public
377
+ */
378
+ function getOperationData($operation){
379
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
380
+ $this->loadWSDL();
381
+ if ($this->getError())
382
+ return false;
383
+ }
384
+ if(isset($this->operations[$operation])){
385
+ return $this->operations[$operation];
386
+ }
387
+ $this->debug("No data for operation: $operation");
388
+ }
389
+
390
+ /**
391
+ * send the SOAP message
392
+ *
393
+ * Note: if the operation has multiple return values
394
+ * the return value of this method will be an array
395
+ * of those values.
396
+ *
397
+ * @param string $msg a SOAPx4 soapmsg object
398
+ * @param string $soapaction SOAPAction value
399
+ * @param integer $timeout set connection timeout in seconds
400
+ * @param integer $response_timeout set response timeout in seconds
401
+ * @return mixed native PHP types.
402
+ * @access private
403
+ */
404
+ function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
405
+ $this->checkCookies();
406
+ // detect transport
407
+ switch(true){
408
+ // http(s)
409
+ case ereg('^http',$this->endpoint):
410
+ $this->debug('transporting via HTTP');
411
+ if($this->persistentConnection == true && is_object($this->persistentConnection)){
412
+ $http =& $this->persistentConnection;
413
+ } else {
414
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
415
+ if ($this->persistentConnection) {
416
+ $http->usePersistentConnection();
417
+ }
418
+ }
419
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
420
+ $http->setSOAPAction($soapaction);
421
+ if($this->proxyhost && $this->proxyport){
422
+ $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
423
+ }
424
+ if($this->authtype != '') {
425
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
426
+ }
427
+ if($this->http_encoding != ''){
428
+ $http->setEncoding($this->http_encoding);
429
+ }
430
+ $this->debug('sending message, length='.strlen($msg));
431
+ if(ereg('^http:',$this->endpoint)){
432
+ //if(strpos($this->endpoint,'http:')){
433
+ $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
434
+ } elseif(ereg('^https',$this->endpoint)){
435
+ //} elseif(strpos($this->endpoint,'https:')){
436
+ //if(phpversion() == '4.3.0-dev'){
437
+ //$response = $http->send($msg,$timeout,$response_timeout);
438
+ //$this->request = $http->outgoing_payload;
439
+ //$this->response = $http->incoming_payload;
440
+ //} else
441
+ $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
442
+ } else {
443
+ $this->setError('no http/s in endpoint url');
444
+ }
445
+ $this->request = $http->outgoing_payload;
446
+ $this->response = $http->incoming_payload;
447
+ $this->appendDebug($http->getDebug());
448
+ $this->UpdateCookies($http->incoming_cookies);
449
+
450
+ // save transport object if using persistent connections
451
+ if ($this->persistentConnection) {
452
+ $http->clearDebug();
453
+ if (!is_object($this->persistentConnection)) {
454
+ $this->persistentConnection = $http;
455
+ }
456
+ }
457
+
458
+ if($err = $http->getError()){
459
+ $this->setError('HTTP Error: '.$err);
460
+ return false;
461
+ } elseif($this->getError()){
462
+ return false;
463
+ } else {
464
+ $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
465
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
466
+ }
467
+ break;
468
+ default:
469
+ $this->setError('no transport found, or selected transport is not yet supported!');
470
+ return false;
471
+ break;
472
+ }
473
+ }
474
+
475
+ /**
476
+ * processes SOAP message returned from server
477
+ *
478
+ * @param array $headers The HTTP headers
479
+ * @param string $data unprocessed response data from server
480
+ * @return mixed value of the message, decoded into a PHP type
481
+ * @access private
482
+ */
483
+ function parseResponse($headers, $data) {
484
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
485
+ $this->appendDebug($this->varDump($headers));
486
+ if (!strstr($headers['content-type'], 'text/xml')) {
487
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
488
+ return false;
489
+ }
490
+ if (strpos($headers['content-type'], '=')) {
491
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
492
+ $this->debug('Got response encoding: ' . $enc);
493
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
494
+ $this->xml_encoding = strtoupper($enc);
495
+ } else {
496
+ $this->xml_encoding = 'US-ASCII';
497
+ }
498
+ } else {
499
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
500
+ $this->xml_encoding = 'ISO-8859-1';
501
+ }
502
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
503
+ $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
504
+ // add parser debug data to our debug
505
+ $this->appendDebug($parser->getDebug());
506
+ // if parse errors
507
+ if($errstr = $parser->getError()){
508
+ $this->setError( $errstr);
509
+ // destroy the parser object
510
+ unset($parser);
511
+ return false;
512
+ } else {
513
+ // get SOAP headers
514
+ $this->responseHeaders = $parser->getHeaders();
515
+ // get SOAP headers
516
+ $this->responseHeader = $parser->get_soapheader();
517
+ // get decoded message
518
+ $return = $parser->get_soapbody();
519
+ // add document for doclit support
520
+ $this->document = $parser->document;
521
+ // destroy the parser object
522
+ unset($parser);
523
+ // return decode message
524
+ return $return;
525
+ }
526
+ }
527
+
528
+ /**
529
+ * sets user-specified cURL options
530
+ *
531
+ * @param mixed $option The cURL option (always integer?)
532
+ * @param mixed $value The cURL option value
533
+ * @access public
534
+ */
535
+ function setCurlOption($option, $value) {
536
+ $this->debug("setCurlOption option=$option, value=");
537
+ $this->appendDebug($this->varDump($value));
538
+ $this->curl_options[$option] = $value;
539
+ }
540
+
541
+ /**
542
+ * sets the SOAP endpoint, which can override WSDL
543
+ *
544
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
545
+ * @access public
546
+ */
547
+ function setEndpoint($endpoint) {
548
+ $this->debug("setEndpoint(\"$endpoint\")");
549
+ $this->forceEndpoint = $endpoint;
550
+ }
551
+
552
+ /**
553
+ * set the SOAP headers
554
+ *
555
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
556
+ * @access public
557
+ */
558
+ function setHeaders($headers){
559
+ $this->debug("setHeaders headers=");
560
+ $this->appendDebug($this->varDump($headers));
561
+ $this->requestHeaders = $headers;
562
+ }
563
+
564
+ /**
565
+ * get the SOAP response headers (namespace resolution incomplete)
566
+ *
567
+ * @return string
568
+ * @access public
569
+ */
570
+ function getHeaders(){
571
+ return $this->responseHeaders;
572
+ }
573
+
574
+ /**
575
+ * get the SOAP response Header (parsed)
576
+ *
577
+ * @return mixed
578
+ * @access public
579
+ */
580
+ function getHeader(){
581
+ return $this->responseHeader;
582
+ }
583
+
584
+ /**
585
+ * set proxy info here
586
+ *
587
+ * @param string $proxyhost
588
+ * @param string $proxyport
589
+ * @param string $proxyusername
590
+ * @param string $proxypassword
591
+ * @access public
592
+ */
593
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
594
+ $this->proxyhost = $proxyhost;
595
+ $this->proxyport = $proxyport;
596
+ $this->proxyusername = $proxyusername;
597
+ $this->proxypassword = $proxypassword;
598
+ }
599
+
600
+ /**
601
+ * if authenticating, set user credentials here
602
+ *
603
+ * @param string $username
604
+ * @param string $password
605
+ * @param string $authtype (basic|digest|certificate|ntlm)
606
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
607
+ * @access public
608
+ */
609
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
610
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
611
+ $this->appendDebug($this->varDump($certRequest));
612
+ $this->username = $username;
613
+ $this->password = $password;
614
+ $this->authtype = $authtype;
615
+ $this->certRequest = $certRequest;
616
+ }
617
+
618
+ /**
619
+ * use HTTP encoding
620
+ *
621
+ * @param string $enc HTTP encoding
622
+ * @access public
623
+ */
624
+ function setHTTPEncoding($enc='gzip, deflate'){
625
+ $this->debug("setHTTPEncoding(\"$enc\")");
626
+ $this->http_encoding = $enc;
627
+ }
628
+
629
+ /**
630
+ * Set whether to try to use cURL connections if possible
631
+ *
632
+ * @param boolean $use Whether to try to use cURL
633
+ * @access public
634
+ */
635
+ function setUseCURL($use) {
636
+ $this->debug("setUseCURL($use)");
637
+ $this->use_curl = $use;
638
+ }
639
+
640
+ /**
641
+ * use HTTP persistent connections if possible
642
+ *
643
+ * @access public
644
+ */
645
+ function useHTTPPersistentConnection(){
646
+ $this->debug("useHTTPPersistentConnection");
647
+ $this->persistentConnection = true;
648
+ }
649
+
650
+ /**
651
+ * gets the default RPC parameter setting.
652
+ * If true, default is that call params are like RPC even for document style.
653
+ * Each call() can override this value.
654
+ *
655
+ * This is no longer used.
656
+ *
657
+ * @return boolean
658
+ * @access public
659
+ * @deprecated
660
+ */
661
+ function getDefaultRpcParams() {
662
+ return $this->defaultRpcParams;
663
+ }
664
+
665
+ /**
666
+ * sets the default RPC parameter setting.
667
+ * If true, default is that call params are like RPC even for document style
668
+ * Each call() can override this value.
669
+ *
670
+ * This is no longer used.
671
+ *
672
+ * @param boolean $rpcParams
673
+ * @access public
674
+ * @deprecated
675
+ */
676
+ function setDefaultRpcParams($rpcParams) {
677
+ $this->defaultRpcParams = $rpcParams;
678
+ }
679
+
680
+ /**
681
+ * dynamically creates an instance of a proxy class,
682
+ * allowing user to directly call methods from wsdl
683
+ *
684
+ * @return object soap_proxy object
685
+ * @access public
686
+ */
687
+ function getProxy() {
688
+ $r = rand();
689
+ $evalStr = $this->_getProxyClassCode($r);
690
+ //$this->debug("proxy class: $evalStr");
691
+ if ($this->getError()) {
692
+ $this->debug("Error from _getProxyClassCode, so return NULL");
693
+ return null;
694
+ }
695
+ // eval the class
696
+ eval($evalStr);
697
+ // instantiate proxy object
698
+ eval("\$proxy = new nusoap_proxy_$r('');");
699
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
700
+ $proxy->endpointType = 'wsdl';
701
+ $proxy->wsdlFile = $this->wsdlFile;
702
+ $proxy->wsdl = $this->wsdl;
703
+ $proxy->operations = $this->operations;
704
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
705
+ // transfer other state
706
+ $proxy->soap_defencoding = $this->soap_defencoding;
707
+ $proxy->username = $this->username;
708
+ $proxy->password = $this->password;
709
+ $proxy->authtype = $this->authtype;
710
+ $proxy->certRequest = $this->certRequest;
711
+ $proxy->requestHeaders = $this->requestHeaders;
712
+ $proxy->endpoint = $this->endpoint;
713
+ $proxy->forceEndpoint = $this->forceEndpoint;
714
+ $proxy->proxyhost = $this->proxyhost;
715
+ $proxy->proxyport = $this->proxyport;
716
+ $proxy->proxyusername = $this->proxyusername;
717
+ $proxy->proxypassword = $this->proxypassword;
718
+ $proxy->http_encoding = $this->http_encoding;
719
+ $proxy->timeout = $this->timeout;
720
+ $proxy->response_timeout = $this->response_timeout;
721
+ $proxy->persistentConnection = &$this->persistentConnection;
722
+ $proxy->decode_utf8 = $this->decode_utf8;
723
+ $proxy->curl_options = $this->curl_options;
724
+ $proxy->bindingType = $this->bindingType;
725
+ $proxy->use_curl = $this->use_curl;
726
+ return $proxy;
727
+ }
728
+
729
+ /**
730
+ * dynamically creates proxy class code
731
+ *
732
+ * @return string PHP/NuSOAP code for the proxy class
733
+ * @access private
734
+ */
735
+ function _getProxyClassCode($r) {
736
+ $this->debug("in getProxy endpointType=$this->endpointType");
737
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
738
+ if ($this->endpointType != 'wsdl') {
739
+ $evalStr = 'A proxy can only be created for a WSDL client';
740
+ $this->setError($evalStr);
741
+ $evalStr = "echo \"$evalStr\";";
742
+ return $evalStr;
743
+ }
744
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
745
+ $this->loadWSDL();
746
+ if ($this->getError()) {
747
+ return "echo \"" . $this->getError() . "\";";
748
+ }
749
+ }
750
+ $evalStr = '';
751
+ foreach ($this->operations as $operation => $opData) {
752
+ if ($operation != '') {
753
+ // create param string and param comment string
754
+ if (sizeof($opData['input']['parts']) > 0) {
755
+ $paramStr = '';
756
+ $paramArrayStr = '';
757
+ $paramCommentStr = '';
758
+ foreach ($opData['input']['parts'] as $name => $type) {
759
+ $paramStr .= "\$$name, ";
760
+ $paramArrayStr .= "'$name' => \$$name, ";
761
+ $paramCommentStr .= "$type \$$name, ";
762
+ }
763
+ $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
764
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
765
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
766
+ } else {
767
+ $paramStr = '';
768
+ $paramArrayStr = '';
769
+ $paramCommentStr = 'void';
770
+ }
771
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
772
+ $evalStr .= "// $paramCommentStr
773
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
774
+ \$params = array($paramArrayStr);
775
+ return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
776
+ }
777
+ ";
778
+ unset($paramStr);
779
+ unset($paramCommentStr);
780
+ }
781
+ }
782
+ $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
783
+ '.$evalStr.'
784
+ }';
785
+ return $evalStr;
786
+ }
787
+
788
+ /**
789
+ * dynamically creates proxy class code
790
+ *
791
+ * @return string PHP/NuSOAP code for the proxy class
792
+ * @access public
793
+ */
794
+ function getProxyClassCode() {
795
+ $r = rand();
796
+ return $this->_getProxyClassCode($r);
797
+ }
798
+
799
+ /**
800
+ * gets the HTTP body for the current request.
801
+ *
802
+ * @param string $soapmsg The SOAP payload
803
+ * @return string The HTTP body, which includes the SOAP payload
804
+ * @access private
805
+ */
806
+ function getHTTPBody($soapmsg) {
807
+ return $soapmsg;
808
+ }
809
+
810
+ /**
811
+ * gets the HTTP content type for the current request.
812
+ *
813
+ * Note: getHTTPBody must be called before this.
814
+ *
815
+ * @return string the HTTP content type for the current request.
816
+ * @access private
817
+ */
818
+ function getHTTPContentType() {
819
+ return 'text/xml';
820
+ }
821
+
822
+ /**
823
+ * gets the HTTP content type charset for the current request.
824
+ * returns false for non-text content types.
825
+ *
826
+ * Note: getHTTPBody must be called before this.
827
+ *
828
+ * @return string the HTTP content type charset for the current request.
829
+ * @access private
830
+ */
831
+ function getHTTPContentTypeCharset() {
832
+ return $this->soap_defencoding;
833
+ }
834
+
835
+ /*
836
+ * whether or not parser should decode utf8 element content
837
+ *
838
+ * @return always returns true
839
+ * @access public
840
+ */
841
+ function decodeUTF8($bool){
842
+ $this->decode_utf8 = $bool;
843
+ return true;
844
+ }
845
+
846
+ /**
847
+ * adds a new Cookie into $this->cookies array
848
+ *
849
+ * @param string $name Cookie Name
850
+ * @param string $value Cookie Value
851
+ * @return boolean if cookie-set was successful returns true, else false
852
+ * @access public
853
+ */
854
+ function setCookie($name, $value) {
855
+ if (strlen($name) == 0) {
856
+ return false;
857
+ }
858
+ $this->cookies[] = array('name' => $name, 'value' => $value);
859
+ return true;
860
+ }
861
+
862
+ /**
863
+ * gets all Cookies
864
+ *
865
+ * @return array with all internal cookies
866
+ * @access public
867
+ */
868
+ function getCookies() {
869
+ return $this->cookies;
870
+ }
871
+
872
+ /**
873
+ * checks all Cookies and delete those which are expired
874
+ *
875
+ * @return boolean always return true
876
+ * @access private
877
+ */
878
+ function checkCookies() {
879
+ if (sizeof($this->cookies) == 0) {
880
+ return true;
881
+ }
882
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
883
+ $curr_cookies = $this->cookies;
884
+ $this->cookies = array();
885
+ foreach ($curr_cookies as $cookie) {
886
+ if (! is_array($cookie)) {
887
+ $this->debug('Remove cookie that is not an array');
888
+ continue;
889
+ }
890
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
891
+ if (strtotime($cookie['expires']) > time()) {
892
+ $this->cookies[] = $cookie;
893
+ } else {
894
+ $this->debug('Remove expired cookie ' . $cookie['name']);
895
+ }
896
+ } else {
897
+ $this->cookies[] = $cookie;
898
+ }
899
+ }
900
+ $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
901
+ return true;
902
+ }
903
+
904
+ /**
905
+ * updates the current cookies with a new set
906
+ *
907
+ * @param array $cookies new cookies with which to update current ones
908
+ * @return boolean always return true
909
+ * @access private
910
+ */
911
+ function UpdateCookies($cookies) {
912
+ if (sizeof($this->cookies) == 0) {
913
+ // no existing cookies: take whatever is new
914
+ if (sizeof($cookies) > 0) {
915
+ $this->debug('Setting new cookie(s)');
916
+ $this->cookies = $cookies;
917
+ }
918
+ return true;
919
+ }
920
+ if (sizeof($cookies) == 0) {
921
+ // no new cookies: keep what we've got
922
+ return true;
923
+ }
924
+ // merge
925
+ foreach ($cookies as $newCookie) {
926
+ if (!is_array($newCookie)) {
927
+ continue;
928
+ }
929
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
930
+ continue;
931
+ }
932
+ $newName = $newCookie['name'];
933
+
934
+ $found = false;
935
+ for ($i = 0; $i < count($this->cookies); $i++) {
936
+ $cookie = $this->cookies[$i];
937
+ if (!is_array($cookie)) {
938
+ continue;
939
+ }
940
+ if (!isset($cookie['name'])) {
941
+ continue;
942
+ }
943
+ if ($newName != $cookie['name']) {
944
+ continue;
945
+ }
946
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
947
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
948
+ if ($newDomain != $domain) {
949
+ continue;
950
+ }
951
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
952
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
953
+ if ($newPath != $path) {
954
+ continue;
955
+ }
956
+ $this->cookies[$i] = $newCookie;
957
+ $found = true;
958
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
959
+ break;
960
+ }
961
+ if (! $found) {
962
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
963
+ $this->cookies[] = $newCookie;
964
+ }
965
+ }
966
+ return true;
967
+ }
968
+ }
969
+
970
+ if (!extension_loaded('soap')) {
971
+ /**
972
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
973
+ */
974
+ class soapclient extends nusoap_client {
975
+ }
976
+ }
977
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.wsdl.php ADDED
@@ -0,0 +1,1904 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ * parses a WSDL file, allows access to it's data, other utility methods.
8
+ * also builds WSDL structures programmatically.
9
+ *
10
+ * @author Dietrich Ayala <dietrich@ganx4.com>
11
+ * @author Scott Nichol <snichol@users.sourceforge.net>
12
+ * @version $Id: class.wsdl.php,v 1.69 2007/11/06 15:17:46 snichol Exp $
13
+ * @access public
14
+ */
15
+ class wsdl extends nusoap_base {
16
+ // URL or filename of the root of this WSDL
17
+ var $wsdl;
18
+ // define internal arrays of bindings, ports, operations, messages, etc.
19
+ var $schemas = array();
20
+ var $currentSchema;
21
+ var $message = array();
22
+ var $complexTypes = array();
23
+ var $messages = array();
24
+ var $currentMessage;
25
+ var $currentOperation;
26
+ var $portTypes = array();
27
+ var $currentPortType;
28
+ var $bindings = array();
29
+ var $currentBinding;
30
+ var $ports = array();
31
+ var $currentPort;
32
+ var $opData = array();
33
+ var $status = '';
34
+ var $documentation = false;
35
+ var $endpoint = '';
36
+ // array of wsdl docs to import
37
+ var $import = array();
38
+ // parser vars
39
+ var $parser;
40
+ var $position = 0;
41
+ var $depth = 0;
42
+ var $depth_array = array();
43
+ // for getting wsdl
44
+ var $proxyhost = '';
45
+ var $proxyport = '';
46
+ var $proxyusername = '';
47
+ var $proxypassword = '';
48
+ var $timeout = 0;
49
+ var $response_timeout = 30;
50
+ var $curl_options = array(); // User-specified cURL options
51
+ var $use_curl = false; // whether to always try to use cURL
52
+ // for HTTP authentication
53
+ var $username = ''; // Username for HTTP authentication
54
+ var $password = ''; // Password for HTTP authentication
55
+ var $authtype = ''; // Type of HTTP authentication
56
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
57
+
58
+ /**
59
+ * constructor
60
+ *
61
+ * @param string $wsdl WSDL document URL
62
+ * @param string $proxyhost
63
+ * @param string $proxyport
64
+ * @param string $proxyusername
65
+ * @param string $proxypassword
66
+ * @param integer $timeout set the connection timeout
67
+ * @param integer $response_timeout set the response timeout
68
+ * @param array $curl_options user-specified cURL options
69
+ * @param boolean $use_curl try to use cURL
70
+ * @access public
71
+ */
72
+ function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
73
+ parent::nusoap_base();
74
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
75
+ $this->proxyhost = $proxyhost;
76
+ $this->proxyport = $proxyport;
77
+ $this->proxyusername = $proxyusername;
78
+ $this->proxypassword = $proxypassword;
79
+ $this->timeout = $timeout;
80
+ $this->response_timeout = $response_timeout;
81
+ if (is_array($curl_options))
82
+ $this->curl_options = $curl_options;
83
+ $this->use_curl = $use_curl;
84
+ $this->fetchWSDL($wsdl);
85
+ }
86
+
87
+ /**
88
+ * fetches the WSDL document and parses it
89
+ *
90
+ * @access public
91
+ */
92
+ function fetchWSDL($wsdl) {
93
+ $this->debug("parse and process WSDL path=$wsdl");
94
+ $this->wsdl = $wsdl;
95
+ // parse wsdl file
96
+ if ($this->wsdl != "") {
97
+ $this->parseWSDL($this->wsdl);
98
+ }
99
+ // imports
100
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
101
+ $imported_urls = array();
102
+ $imported = 1;
103
+ while ($imported > 0) {
104
+ $imported = 0;
105
+ // Schema imports
106
+ foreach ($this->schemas as $ns => $list) {
107
+ foreach ($list as $xs) {
108
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
109
+ foreach ($xs->imports as $ns2 => $list2) {
110
+ for ($ii = 0; $ii < count($list2); $ii++) {
111
+ if (! $list2[$ii]['loaded']) {
112
+ $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
113
+ $url = $list2[$ii]['location'];
114
+ if ($url != '') {
115
+ $urlparts = parse_url($url);
116
+ if (!isset($urlparts['host'])) {
117
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
118
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
119
+ }
120
+ if (! in_array($url, $imported_urls)) {
121
+ $this->parseWSDL($url);
122
+ $imported++;
123
+ $imported_urls[] = $url;
124
+ }
125
+ } else {
126
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ // WSDL imports
134
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
135
+ foreach ($this->import as $ns => $list) {
136
+ for ($ii = 0; $ii < count($list); $ii++) {
137
+ if (! $list[$ii]['loaded']) {
138
+ $this->import[$ns][$ii]['loaded'] = true;
139
+ $url = $list[$ii]['location'];
140
+ if ($url != '') {
141
+ $urlparts = parse_url($url);
142
+ if (!isset($urlparts['host'])) {
143
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
144
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
145
+ }
146
+ if (! in_array($url, $imported_urls)) {
147
+ $this->parseWSDL($url);
148
+ $imported++;
149
+ $imported_urls[] = $url;
150
+ }
151
+ } else {
152
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ // add new data to operation data
159
+ foreach($this->bindings as $binding => $bindingData) {
160
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
161
+ foreach($bindingData['operations'] as $operation => $data) {
162
+ $this->debug('post-parse data gathering for ' . $operation);
163
+ $this->bindings[$binding]['operations'][$operation]['input'] =
164
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
165
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
166
+ $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
167
+ $this->bindings[$binding]['operations'][$operation]['output'] =
168
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
169
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
170
+ $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
171
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
172
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
173
+ }
174
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
175
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
176
+ }
177
+ // Set operation style if necessary, but do not override one already provided
178
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
179
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
180
+ }
181
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
182
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
183
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ /**
190
+ * parses the wsdl document
191
+ *
192
+ * @param string $wsdl path or URL
193
+ * @access private
194
+ */
195
+ function parseWSDL($wsdl = '') {
196
+ $this->debug("parse WSDL at path=$wsdl");
197
+
198
+ if ($wsdl == '') {
199
+ $this->debug('no wsdl passed to parseWSDL()!!');
200
+ $this->setError('no wsdl passed to parseWSDL()!!');
201
+ return false;
202
+ }
203
+
204
+ // parse $wsdl for url format
205
+ $wsdl_props = parse_url($wsdl);
206
+
207
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
208
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
209
+ // get wsdl
210
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
211
+ $tr->request_method = 'GET';
212
+ $tr->useSOAPAction = false;
213
+ if($this->proxyhost && $this->proxyport){
214
+ $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
215
+ }
216
+ if ($this->authtype != '') {
217
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
218
+ }
219
+ $tr->setEncoding('gzip, deflate');
220
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
221
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
222
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
223
+ $this->appendDebug($tr->getDebug());
224
+ // catch errors
225
+ if($err = $tr->getError() ){
226
+ $errstr = 'HTTP ERROR: '.$err;
227
+ $this->debug($errstr);
228
+ $this->setError($errstr);
229
+ unset($tr);
230
+ return false;
231
+ }
232
+ unset($tr);
233
+ $this->debug("got WSDL URL");
234
+ } else {
235
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
236
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
237
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
238
+ } else {
239
+ $path = $wsdl;
240
+ }
241
+ $this->debug('getting WSDL file ' . $path);
242
+ if ($fp = @fopen($path, 'r')) {
243
+ $wsdl_string = '';
244
+ while ($data = fread($fp, 32768)) {
245
+ $wsdl_string .= $data;
246
+ }
247
+ fclose($fp);
248
+ } else {
249
+ $errstr = "Bad path to WSDL file $path";
250
+ $this->debug($errstr);
251
+ $this->setError($errstr);
252
+ return false;
253
+ }
254
+ }
255
+ $this->debug('Parse WSDL');
256
+ // end new code added
257
+ // Create an XML parser.
258
+ $this->parser = xml_parser_create();
259
+ // Set the options for parsing the XML data.
260
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
261
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
262
+ // Set the object for the parser.
263
+ xml_set_object($this->parser, $this);
264
+ // Set the element handlers for the parser.
265
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
266
+ xml_set_character_data_handler($this->parser, 'character_data');
267
+ // Parse the XML file.
268
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
269
+ // Display an error message.
270
+ $errstr = sprintf(
271
+ 'XML error parsing WSDL from %s on line %d: %s',
272
+ $wsdl,
273
+ xml_get_current_line_number($this->parser),
274
+ xml_error_string(xml_get_error_code($this->parser))
275
+ );
276
+ $this->debug($errstr);
277
+ $this->debug("XML payload:\n" . $wsdl_string);
278
+ $this->setError($errstr);
279
+ return false;
280
+ }
281
+ // free the parser
282
+ xml_parser_free($this->parser);
283
+ $this->debug('Parsing WSDL done');
284
+ // catch wsdl parse errors
285
+ if($this->getError()){
286
+ return false;
287
+ }
288
+ return true;
289
+ }
290
+
291
+ /**
292
+ * start-element handler
293
+ *
294
+ * @param string $parser XML parser object
295
+ * @param string $name element name
296
+ * @param string $attrs associative array of attributes
297
+ * @access private
298
+ */
299
+ function start_element($parser, $name, $attrs)
300
+ {
301
+ if ($this->status == 'schema') {
302
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
303
+ $this->appendDebug($this->currentSchema->getDebug());
304
+ $this->currentSchema->clearDebug();
305
+ } elseif (ereg('schema$', $name)) {
306
+ $this->debug('Parsing WSDL schema');
307
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
308
+ $this->status = 'schema';
309
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
310
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
311
+ $this->appendDebug($this->currentSchema->getDebug());
312
+ $this->currentSchema->clearDebug();
313
+ } else {
314
+ // position in the total number of elements, starting from 0
315
+ $pos = $this->position++;
316
+ $depth = $this->depth++;
317
+ // set self as current value for this depth
318
+ $this->depth_array[$depth] = $pos;
319
+ $this->message[$pos] = array('cdata' => '');
320
+ // process attributes
321
+ if (count($attrs) > 0) {
322
+ // register namespace declarations
323
+ foreach($attrs as $k => $v) {
324
+ if (ereg("^xmlns", $k)) {
325
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
326
+ $this->namespaces[$ns_prefix] = $v;
327
+ } else {
328
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
329
+ }
330
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
331
+ $this->XMLSchemaVersion = $v;
332
+ $this->namespaces['xsi'] = $v . '-instance';
333
+ }
334
+ }
335
+ }
336
+ // expand each attribute prefix to its namespace
337
+ foreach($attrs as $k => $v) {
338
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
339
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
340
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
341
+ }
342
+ $eAttrs[$k] = $v;
343
+ }
344
+ $attrs = $eAttrs;
345
+ } else {
346
+ $attrs = array();
347
+ }
348
+ // get element prefix, namespace and name
349
+ if (ereg(':', $name)) {
350
+ // get ns prefix
351
+ $prefix = substr($name, 0, strpos($name, ':'));
352
+ // get ns
353
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
354
+ // get unqualified name
355
+ $name = substr(strstr($name, ':'), 1);
356
+ }
357
+ // process attributes, expanding any prefixes to namespaces
358
+ // find status, register data
359
+ switch ($this->status) {
360
+ case 'message':
361
+ if ($name == 'part') {
362
+ if (isset($attrs['type'])) {
363
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
364
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
365
+ }
366
+ if (isset($attrs['element'])) {
367
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
368
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
369
+ }
370
+ }
371
+ break;
372
+ case 'portType':
373
+ switch ($name) {
374
+ case 'operation':
375
+ $this->currentPortOperation = $attrs['name'];
376
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
377
+ if (isset($attrs['parameterOrder'])) {
378
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
379
+ }
380
+ break;
381
+ case 'documentation':
382
+ $this->documentation = true;
383
+ break;
384
+ // merge input/output data
385
+ default:
386
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
387
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
388
+ break;
389
+ }
390
+ break;
391
+ case 'binding':
392
+ switch ($name) {
393
+ case 'binding':
394
+ // get ns prefix
395
+ if (isset($attrs['style'])) {
396
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
397
+ }
398
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
399
+ break;
400
+ case 'header':
401
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
402
+ break;
403
+ case 'operation':
404
+ if (isset($attrs['soapAction'])) {
405
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
406
+ }
407
+ if (isset($attrs['style'])) {
408
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
409
+ }
410
+ if (isset($attrs['name'])) {
411
+ $this->currentOperation = $attrs['name'];
412
+ $this->debug("current binding operation: $this->currentOperation");
413
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
414
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
415
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
416
+ }
417
+ break;
418
+ case 'input':
419
+ $this->opStatus = 'input';
420
+ break;
421
+ case 'output':
422
+ $this->opStatus = 'output';
423
+ break;
424
+ case 'body':
425
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
426
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
427
+ } else {
428
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
429
+ }
430
+ break;
431
+ }
432
+ break;
433
+ case 'service':
434
+ switch ($name) {
435
+ case 'port':
436
+ $this->currentPort = $attrs['name'];
437
+ $this->debug('current port: ' . $this->currentPort);
438
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
439
+
440
+ break;
441
+ case 'address':
442
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
443
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
444
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
445
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
446
+ break;
447
+ }
448
+ break;
449
+ }
450
+ // set status
451
+ switch ($name) {
452
+ case 'import':
453
+ if (isset($attrs['location'])) {
454
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
455
+ $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
456
+ } else {
457
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
458
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
459
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
460
+ }
461
+ $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
462
+ }
463
+ break;
464
+ //wait for schema
465
+ //case 'types':
466
+ // $this->status = 'schema';
467
+ // break;
468
+ case 'message':
469
+ $this->status = 'message';
470
+ $this->messages[$attrs['name']] = array();
471
+ $this->currentMessage = $attrs['name'];
472
+ break;
473
+ case 'portType':
474
+ $this->status = 'portType';
475
+ $this->portTypes[$attrs['name']] = array();
476
+ $this->currentPortType = $attrs['name'];
477
+ break;
478
+ case "binding":
479
+ if (isset($attrs['name'])) {
480
+ // get binding name
481
+ if (strpos($attrs['name'], ':')) {
482
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
483
+ } else {
484
+ $this->currentBinding = $attrs['name'];
485
+ }
486
+ $this->status = 'binding';
487
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
488
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
489
+ }
490
+ break;
491
+ case 'service':
492
+ $this->serviceName = $attrs['name'];
493
+ $this->status = 'service';
494
+ $this->debug('current service: ' . $this->serviceName);
495
+ break;
496
+ case 'definitions':
497
+ foreach ($attrs as $name => $value) {
498
+ $this->wsdl_info[$name] = $value;
499
+ }
500
+ break;
501
+ }
502
+ }
503
+ }
504
+
505
+ /**
506
+ * end-element handler
507
+ *
508
+ * @param string $parser XML parser object
509
+ * @param string $name element name
510
+ * @access private
511
+ */
512
+ function end_element($parser, $name){
513
+ // unset schema status
514
+ if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
515
+ $this->status = "";
516
+ $this->appendDebug($this->currentSchema->getDebug());
517
+ $this->currentSchema->clearDebug();
518
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
519
+ $this->debug('Parsing WSDL schema done');
520
+ }
521
+ if ($this->status == 'schema') {
522
+ $this->currentSchema->schemaEndElement($parser, $name);
523
+ } else {
524
+ // bring depth down a notch
525
+ $this->depth--;
526
+ }
527
+ // end documentation
528
+ if ($this->documentation) {
529
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
530
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
531
+ $this->documentation = false;
532
+ }
533
+ }
534
+
535
+ /**
536
+ * element content handler
537
+ *
538
+ * @param string $parser XML parser object
539
+ * @param string $data element content
540
+ * @access private
541
+ */
542
+ function character_data($parser, $data)
543
+ {
544
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
545
+ if (isset($this->message[$pos]['cdata'])) {
546
+ $this->message[$pos]['cdata'] .= $data;
547
+ }
548
+ if ($this->documentation) {
549
+ $this->documentation .= $data;
550
+ }
551
+ }
552
+
553
+ /**
554
+ * if authenticating, set user credentials here
555
+ *
556
+ * @param string $username
557
+ * @param string $password
558
+ * @param string $authtype (basic|digest|certificate|ntlm)
559
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
560
+ * @access public
561
+ */
562
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
563
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
564
+ $this->appendDebug($this->varDump($certRequest));
565
+ $this->username = $username;
566
+ $this->password = $password;
567
+ $this->authtype = $authtype;
568
+ $this->certRequest = $certRequest;
569
+ }
570
+
571
+ function getBindingData($binding)
572
+ {
573
+ if (is_array($this->bindings[$binding])) {
574
+ return $this->bindings[$binding];
575
+ }
576
+ }
577
+
578
+ /**
579
+ * returns an assoc array of operation names => operation data
580
+ *
581
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
582
+ * @return array
583
+ * @access public
584
+ */
585
+ function getOperations($bindingType = 'soap') {
586
+ $ops = array();
587
+ if ($bindingType == 'soap') {
588
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
589
+ } elseif ($bindingType == 'soap12') {
590
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
591
+ }
592
+ // loop thru ports
593
+ foreach($this->ports as $port => $portData) {
594
+ // binding type of port matches parameter
595
+ if ($portData['bindingType'] == $bindingType) {
596
+ //$this->debug("getOperations for port $port");
597
+ //$this->debug("port data: " . $this->varDump($portData));
598
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
599
+ // merge bindings
600
+ if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
601
+ $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
602
+ }
603
+ }
604
+ }
605
+ return $ops;
606
+ }
607
+
608
+ /**
609
+ * returns an associative array of data necessary for calling an operation
610
+ *
611
+ * @param string $operation name of operation
612
+ * @param string $bindingType type of binding eg: soap, soap12
613
+ * @return array
614
+ * @access public
615
+ */
616
+ function getOperationData($operation, $bindingType = 'soap')
617
+ {
618
+ if ($bindingType == 'soap') {
619
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
620
+ } elseif ($bindingType == 'soap12') {
621
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
622
+ }
623
+ // loop thru ports
624
+ foreach($this->ports as $port => $portData) {
625
+ // binding type of port matches parameter
626
+ if ($portData['bindingType'] == $bindingType) {
627
+ // get binding
628
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
629
+ foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
630
+ // note that we could/should also check the namespace here
631
+ if ($operation == $bOperation) {
632
+ $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
633
+ return $opData;
634
+ }
635
+ }
636
+ }
637
+ }
638
+ }
639
+
640
+ /**
641
+ * returns an associative array of data necessary for calling an operation
642
+ *
643
+ * @param string $soapAction soapAction for operation
644
+ * @param string $bindingType type of binding eg: soap, soap12
645
+ * @return array
646
+ * @access public
647
+ */
648
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
649
+ if ($bindingType == 'soap') {
650
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
651
+ } elseif ($bindingType == 'soap12') {
652
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
653
+ }
654
+ // loop thru ports
655
+ foreach($this->ports as $port => $portData) {
656
+ // binding type of port matches parameter
657
+ if ($portData['bindingType'] == $bindingType) {
658
+ // loop through operations for the binding
659
+ foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
660
+ if ($opData['soapAction'] == $soapAction) {
661
+ return $opData;
662
+ }
663
+ }
664
+ }
665
+ }
666
+ }
667
+
668
+ /**
669
+ * returns an array of information about a given type
670
+ * returns false if no type exists by the given name
671
+ *
672
+ * typeDef = array(
673
+ * 'elements' => array(), // refs to elements array
674
+ * 'restrictionBase' => '',
675
+ * 'phpType' => '',
676
+ * 'order' => '(sequence|all)',
677
+ * 'attrs' => array() // refs to attributes array
678
+ * )
679
+ *
680
+ * @param string $type the type
681
+ * @param string $ns namespace (not prefix) of the type
682
+ * @return mixed
683
+ * @access public
684
+ * @see nusoap_xmlschema
685
+ */
686
+ function getTypeDef($type, $ns) {
687
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
688
+ if ((! $ns) && isset($this->namespaces['tns'])) {
689
+ $ns = $this->namespaces['tns'];
690
+ $this->debug("in getTypeDef: type namespace forced to $ns");
691
+ }
692
+ if (!isset($this->schemas[$ns])) {
693
+ foreach ($this->schemas as $ns0 => $schema0) {
694
+ if (strcasecmp($ns, $ns0) == 0) {
695
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
696
+ $ns = $ns0;
697
+ break;
698
+ }
699
+ }
700
+ }
701
+ if (isset($this->schemas[$ns])) {
702
+ $this->debug("in getTypeDef: have schema for namespace $ns");
703
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
704
+ $xs = &$this->schemas[$ns][$i];
705
+ $t = $xs->getTypeDef($type);
706
+ //$this->appendDebug($xs->getDebug());
707
+ //$xs->clearDebug();
708
+ if ($t) {
709
+ if (!isset($t['phpType'])) {
710
+ // get info for type to tack onto the element
711
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
712
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
713
+ $etype = $this->getTypeDef($uqType, $ns);
714
+ if ($etype) {
715
+ $this->debug("found type for [element] $type:");
716
+ $this->debug($this->varDump($etype));
717
+ if (isset($etype['phpType'])) {
718
+ $t['phpType'] = $etype['phpType'];
719
+ }
720
+ if (isset($etype['elements'])) {
721
+ $t['elements'] = $etype['elements'];
722
+ }
723
+ if (isset($etype['attrs'])) {
724
+ $t['attrs'] = $etype['attrs'];
725
+ }
726
+ }
727
+ }
728
+ return $t;
729
+ }
730
+ }
731
+ } else {
732
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
733
+ }
734
+ return false;
735
+ }
736
+
737
+ /**
738
+ * prints html description of services
739
+ *
740
+ * @access private
741
+ */
742
+ function webDescription(){
743
+ global $HTTP_SERVER_VARS;
744
+
745
+ if (isset($_SERVER)) {
746
+ $PHP_SELF = $_SERVER['PHP_SELF'];
747
+ } elseif (isset($HTTP_SERVER_VARS)) {
748
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
749
+ } else {
750
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
751
+ }
752
+
753
+ $b = '
754
+ <html><head><title>NuSOAP: '.$this->serviceName.'</title>
755
+ <style type="text/css">
756
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
757
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
758
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
759
+ ul { margin-top: 10px; margin-left: 20px; }
760
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
761
+ .content{
762
+ margin-left: 0px; padding-bottom: 2em; }
763
+ .nav {
764
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
765
+ margin-top: 10px; margin-left: 0px; color: #000000;
766
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
767
+ .title {
768
+ font-family: arial; font-size: 26px; color: #ffffff;
769
+ background-color: #999999; width: 105%; margin-left: 0px;
770
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
771
+ .hidden {
772
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
773
+ font-family: arial; overflow: hidden; width: 600;
774
+ padding: 20px; font-size: 10px; background-color: #999999;
775
+ layer-background-color:#FFFFFF; }
776
+ a,a:active { color: charcoal; font-weight: bold; }
777
+ a:visited { color: #666666; font-weight: bold; }
778
+ a:hover { color: cc3300; font-weight: bold; }
779
+ </style>
780
+ <script language="JavaScript" type="text/javascript">
781
+ <!--
782
+ // POP-UP CAPTIONS...
783
+ function lib_bwcheck(){ //Browsercheck (needed)
784
+ this.ver=navigator.appVersion
785
+ this.agent=navigator.userAgent
786
+ this.dom=document.getElementById?1:0
787
+ this.opera5=this.agent.indexOf("Opera 5")>-1
788
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
789
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
790
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
791
+ this.ie=this.ie4||this.ie5||this.ie6
792
+ this.mac=this.agent.indexOf("Mac")>-1
793
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
794
+ this.ns4=(document.layers && !this.dom)?1:0;
795
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
796
+ return this
797
+ }
798
+ var bw = new lib_bwcheck()
799
+ //Makes crossbrowser object.
800
+ function makeObj(obj){
801
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
802
+ if(!this.evnt) return false
803
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
804
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
805
+ this.writeIt=b_writeIt;
806
+ return this
807
+ }
808
+ // A unit of measure that will be added when setting the position of a layer.
809
+ //var px = bw.ns4||window.opera?"":"px";
810
+ function b_writeIt(text){
811
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
812
+ else this.wref.innerHTML = text
813
+ }
814
+ //Shows the messages
815
+ var oDesc;
816
+ function popup(divid){
817
+ if(oDesc = new makeObj(divid)){
818
+ oDesc.css.visibility = "visible"
819
+ }
820
+ }
821
+ function popout(){ // Hides message
822
+ if(oDesc) oDesc.css.visibility = "hidden"
823
+ }
824
+ //-->
825
+ </script>
826
+ </head>
827
+ <body>
828
+ <div class=content>
829
+ <br><br>
830
+ <div class=title>'.$this->serviceName.'</div>
831
+ <div class=nav>
832
+ <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
833
+ Click on an operation name to view it&apos;s details.</p>
834
+ <ul>';
835
+ foreach($this->getOperations() as $op => $data){
836
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
837
+ // create hidden div
838
+ $b .= "<div id='$op' class='hidden'>
839
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
840
+ foreach($data as $donnie => $marie){ // loop through opdata
841
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
842
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
843
+ foreach($marie as $captain => $tenille){ // loop through data
844
+ if($captain == 'parts'){ // loop thru parts
845
+ $b .= "&nbsp;&nbsp;$captain:<br>";
846
+ //if(is_array($tenille)){
847
+ foreach($tenille as $joanie => $chachi){
848
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
849
+ }
850
+ //}
851
+ } else {
852
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
853
+ }
854
+ }
855
+ } else {
856
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
857
+ }
858
+ }
859
+ $b .= '</div>';
860
+ }
861
+ $b .= '
862
+ <ul>
863
+ </div>
864
+ </div></body></html>';
865
+ return $b;
866
+ }
867
+
868
+ /**
869
+ * serialize the parsed wsdl
870
+ *
871
+ * @param mixed $debug whether to put debug=1 in endpoint URL
872
+ * @return string serialization of WSDL
873
+ * @access public
874
+ */
875
+ function serialize($debug = 0)
876
+ {
877
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
878
+ $xml .= "\n<definitions";
879
+ foreach($this->namespaces as $k => $v) {
880
+ $xml .= " xmlns:$k=\"$v\"";
881
+ }
882
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
883
+ if (isset($this->namespaces['wsdl'])) {
884
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
885
+ }
886
+ if (isset($this->namespaces['tns'])) {
887
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
888
+ }
889
+ $xml .= '>';
890
+ // imports
891
+ if (sizeof($this->import) > 0) {
892
+ foreach($this->import as $ns => $list) {
893
+ foreach ($list as $ii) {
894
+ if ($ii['location'] != '') {
895
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
896
+ } else {
897
+ $xml .= '<import namespace="' . $ns . '" />';
898
+ }
899
+ }
900
+ }
901
+ }
902
+ // types
903
+ if (count($this->schemas)>=1) {
904
+ $xml .= "\n<types>\n";
905
+ foreach ($this->schemas as $ns => $list) {
906
+ foreach ($list as $xs) {
907
+ $xml .= $xs->serializeSchema();
908
+ }
909
+ }
910
+ $xml .= '</types>';
911
+ }
912
+ // messages
913
+ if (count($this->messages) >= 1) {
914
+ foreach($this->messages as $msgName => $msgParts) {
915
+ $xml .= "\n<message name=\"" . $msgName . '">';
916
+ if(is_array($msgParts)){
917
+ foreach($msgParts as $partName => $partType) {
918
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
919
+ if (strpos($partType, ':')) {
920
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
921
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
922
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
923
+ $typePrefix = 'xsd';
924
+ } else {
925
+ foreach($this->typemap as $ns => $types) {
926
+ if (isset($types[$partType])) {
927
+ $typePrefix = $this->getPrefixFromNamespace($ns);
928
+ }
929
+ }
930
+ if (!isset($typePrefix)) {
931
+ die("$partType has no namespace!");
932
+ }
933
+ }
934
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
935
+ $localPart = $this->getLocalPart($partType);
936
+ $typeDef = $this->getTypeDef($localPart, $ns);
937
+ if ($typeDef['typeClass'] == 'element') {
938
+ $elementortype = 'element';
939
+ if (substr($localPart, -1) == '^') {
940
+ $localPart = substr($localPart, 0, -1);
941
+ }
942
+ } else {
943
+ $elementortype = 'type';
944
+ }
945
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
946
+ }
947
+ }
948
+ $xml .= '</message>';
949
+ }
950
+ }
951
+ // bindings & porttypes
952
+ if (count($this->bindings) >= 1) {
953
+ $binding_xml = '';
954
+ $portType_xml = '';
955
+ foreach($this->bindings as $bindingName => $attrs) {
956
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
957
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
958
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
959
+ foreach($attrs['operations'] as $opName => $opParts) {
960
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
961
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
962
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
963
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
964
+ } else {
965
+ $enc_style = '';
966
+ }
967
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
968
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
969
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
970
+ } else {
971
+ $enc_style = '';
972
+ }
973
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
974
+ $binding_xml .= "\n" . ' </operation>';
975
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
976
+ if (isset($opParts['parameterOrder'])) {
977
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
978
+ }
979
+ $portType_xml .= '>';
980
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
981
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
982
+ }
983
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
984
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
985
+ $portType_xml .= "\n" . ' </operation>';
986
+ }
987
+ $portType_xml .= "\n" . '</portType>';
988
+ $binding_xml .= "\n" . '</binding>';
989
+ }
990
+ $xml .= $portType_xml . $binding_xml;
991
+ }
992
+ // services
993
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
994
+ if (count($this->ports) >= 1) {
995
+ foreach($this->ports as $pName => $attrs) {
996
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
997
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
998
+ $xml .= "\n" . ' </port>';
999
+ }
1000
+ }
1001
+ $xml .= "\n" . '</service>';
1002
+ return $xml . "\n</definitions>";
1003
+ }
1004
+
1005
+ /**
1006
+ * determine whether a set of parameters are unwrapped
1007
+ * when they are expect to be wrapped, Microsoft-style.
1008
+ *
1009
+ * @param string $type the type (element name) of the wrapper
1010
+ * @param array $parameters the parameter values for the SOAP call
1011
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
1012
+ * @access private
1013
+ */
1014
+ function parametersMatchWrapped($type, &$parameters) {
1015
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
1016
+ $this->appendDebug($this->varDump($parameters));
1017
+
1018
+ // split type into namespace:unqualified-type
1019
+ if (strpos($type, ':')) {
1020
+ $uqType = substr($type, strrpos($type, ':') + 1);
1021
+ $ns = substr($type, 0, strrpos($type, ':'));
1022
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
1023
+ if ($this->getNamespaceFromPrefix($ns)) {
1024
+ $ns = $this->getNamespaceFromPrefix($ns);
1025
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
1026
+ }
1027
+ } else {
1028
+ // TODO: should the type be compared to types in XSD, and the namespace
1029
+ // set to XSD if the type matches?
1030
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
1031
+ $ns = '';
1032
+ $uqType = $type;
1033
+ }
1034
+
1035
+ // get the type information
1036
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
1037
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
1038
+ return false;
1039
+ }
1040
+ $this->debug("in parametersMatchWrapped: found typeDef=");
1041
+ $this->appendDebug($this->varDump($typeDef));
1042
+ if (substr($uqType, -1) == '^') {
1043
+ $uqType = substr($uqType, 0, -1);
1044
+ }
1045
+ $phpType = $typeDef['phpType'];
1046
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
1047
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
1048
+
1049
+ // we expect a complexType or element of complexType
1050
+ if ($phpType != 'struct') {
1051
+ $this->debug("in parametersMatchWrapped: not a struct");
1052
+ return false;
1053
+ }
1054
+
1055
+ // see whether the parameter names match the elements
1056
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1057
+ $elements = 0;
1058
+ $matches = 0;
1059
+ $change = false;
1060
+ if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
1061
+ $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
1062
+ $change = true;
1063
+ }
1064
+ foreach ($typeDef['elements'] as $name => $attrs) {
1065
+ if ($change) {
1066
+ $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
1067
+ $parameters[$name] = $parameters[$elements];
1068
+ unset($parameters[$elements]);
1069
+ $matches++;
1070
+ } elseif (isset($parameters[$name])) {
1071
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
1072
+ $matches++;
1073
+ } else {
1074
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
1075
+ }
1076
+ $elements++;
1077
+ }
1078
+
1079
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
1080
+ if ($matches == 0) {
1081
+ return false;
1082
+ }
1083
+ return true;
1084
+ }
1085
+
1086
+ // since there are no elements for the type, if the user passed no
1087
+ // parameters, the parameters match wrapped.
1088
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
1089
+ return count($parameters) == 0;
1090
+ }
1091
+
1092
+ /**
1093
+ * serialize PHP values according to a WSDL message definition
1094
+ * contrary to the method name, this is not limited to RPC
1095
+ *
1096
+ * TODO
1097
+ * - multi-ref serialization
1098
+ * - validate PHP values against type definitions, return errors if invalid
1099
+ *
1100
+ * @param string $operation operation name
1101
+ * @param string $direction (input|output)
1102
+ * @param mixed $parameters parameter value(s)
1103
+ * @param string $bindingType (soap|soap12)
1104
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1105
+ * @access public
1106
+ */
1107
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
1108
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
1109
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
1110
+
1111
+ if ($direction != 'input' && $direction != 'output') {
1112
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1113
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1114
+ return false;
1115
+ }
1116
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
1117
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1118
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
1119
+ return false;
1120
+ }
1121
+ $this->debug('in serializeRPCParameters: opData:');
1122
+ $this->appendDebug($this->varDump($opData));
1123
+
1124
+ // Get encoding style for output and set to current
1125
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1126
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1127
+ $encodingStyle = $opData['output']['encodingStyle'];
1128
+ $enc_style = $encodingStyle;
1129
+ }
1130
+
1131
+ // set input params
1132
+ $xml = '';
1133
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1134
+ $parts = &$opData[$direction]['parts'];
1135
+ $part_count = sizeof($parts);
1136
+ $style = $opData['style'];
1137
+ $use = $opData[$direction]['use'];
1138
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
1139
+ if (is_array($parameters)) {
1140
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1141
+ $parameter_count = count($parameters);
1142
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
1143
+ // check for Microsoft-style wrapped parameters
1144
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
1145
+ $this->debug('check whether the caller has wrapped the parameters');
1146
+ if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
1147
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
1148
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
1149
+ $this->debug('wrap the parameters for the caller');
1150
+ $parameters = array('parameters' => $parameters);
1151
+ $parameter_count = 1;
1152
+ }
1153
+ }
1154
+ }
1155
+ foreach ($parts as $name => $type) {
1156
+ $this->debug("serializing part $name of type $type");
1157
+ // Track encoding style
1158
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1159
+ $encodingStyle = $opData[$direction]['encodingStyle'];
1160
+ $enc_style = $encodingStyle;
1161
+ } else {
1162
+ $enc_style = false;
1163
+ }
1164
+ // NOTE: add error handling here
1165
+ // if serializeType returns false, then catch global error and fault
1166
+ if ($parametersArrayType == 'arraySimple') {
1167
+ $p = array_shift($parameters);
1168
+ $this->debug('calling serializeType w/indexed param');
1169
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1170
+ } elseif (isset($parameters[$name])) {
1171
+ $this->debug('calling serializeType w/named param');
1172
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1173
+ } else {
1174
+ // TODO: only send nillable
1175
+ $this->debug('calling serializeType w/null param');
1176
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1177
+ }
1178
+ }
1179
+ } else {
1180
+ $this->debug('no parameters passed.');
1181
+ }
1182
+ }
1183
+ $this->debug("serializeRPCParameters returning: $xml");
1184
+ return $xml;
1185
+ }
1186
+
1187
+ /**
1188
+ * serialize a PHP value according to a WSDL message definition
1189
+ *
1190
+ * TODO
1191
+ * - multi-ref serialization
1192
+ * - validate PHP values against type definitions, return errors if invalid
1193
+ *
1194
+ * @param string $operation operation name
1195
+ * @param string $direction (input|output)
1196
+ * @param mixed $parameters parameter value(s)
1197
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
1198
+ * @access public
1199
+ * @deprecated
1200
+ */
1201
+ function serializeParameters($operation, $direction, $parameters)
1202
+ {
1203
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
1204
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
1205
+
1206
+ if ($direction != 'input' && $direction != 'output') {
1207
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
1208
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
1209
+ return false;
1210
+ }
1211
+ if (!$opData = $this->getOperationData($operation)) {
1212
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
1213
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
1214
+ return false;
1215
+ }
1216
+ $this->debug('opData:');
1217
+ $this->appendDebug($this->varDump($opData));
1218
+
1219
+ // Get encoding style for output and set to current
1220
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1221
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
1222
+ $encodingStyle = $opData['output']['encodingStyle'];
1223
+ $enc_style = $encodingStyle;
1224
+ }
1225
+
1226
+ // set input params
1227
+ $xml = '';
1228
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
1229
+
1230
+ $use = $opData[$direction]['use'];
1231
+ $this->debug("use=$use");
1232
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
1233
+ if (is_array($parameters)) {
1234
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
1235
+ $this->debug('have ' . $parametersArrayType . ' parameters');
1236
+ foreach($opData[$direction]['parts'] as $name => $type) {
1237
+ $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
1238
+ // Track encoding style
1239
+ if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
1240
+ $encodingStyle = $opData[$direction]['encodingStyle'];
1241
+ $enc_style = $encodingStyle;
1242
+ } else {
1243
+ $enc_style = false;
1244
+ }
1245
+ // NOTE: add error handling here
1246
+ // if serializeType returns false, then catch global error and fault
1247
+ if ($parametersArrayType == 'arraySimple') {
1248
+ $p = array_shift($parameters);
1249
+ $this->debug('calling serializeType w/indexed param');
1250
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
1251
+ } elseif (isset($parameters[$name])) {
1252
+ $this->debug('calling serializeType w/named param');
1253
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
1254
+ } else {
1255
+ // TODO: only send nillable
1256
+ $this->debug('calling serializeType w/null param');
1257
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
1258
+ }
1259
+ }
1260
+ } else {
1261
+ $this->debug('no parameters passed.');
1262
+ }
1263
+ }
1264
+ $this->debug("serializeParameters returning: $xml");
1265
+ return $xml;
1266
+ }
1267
+
1268
+ /**
1269
+ * serializes a PHP value according a given type definition
1270
+ *
1271
+ * @param string $name name of value (part or element)
1272
+ * @param string $type XML schema type of value (type or element)
1273
+ * @param mixed $value a native PHP value (parameter value)
1274
+ * @param string $use use for part (encoded|literal)
1275
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1276
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
1277
+ * @return string value serialized as an XML string
1278
+ * @access private
1279
+ */
1280
+ function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
1281
+ {
1282
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
1283
+ $this->appendDebug("value=" . $this->varDump($value));
1284
+ if($use == 'encoded' && $encodingStyle) {
1285
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
1286
+ }
1287
+
1288
+ // if a soapval has been supplied, let its type override the WSDL
1289
+ if (is_object($value) && get_class($value) == 'soapval') {
1290
+ if ($value->type_ns) {
1291
+ $type = $value->type_ns . ':' . $value->type;
1292
+ $forceType = true;
1293
+ $this->debug("in serializeType: soapval overrides type to $type");
1294
+ } elseif ($value->type) {
1295
+ $type = $value->type;
1296
+ $forceType = true;
1297
+ $this->debug("in serializeType: soapval overrides type to $type");
1298
+ } else {
1299
+ $forceType = false;
1300
+ $this->debug("in serializeType: soapval does not override type");
1301
+ }
1302
+ $attrs = $value->attributes;
1303
+ $value = $value->value;
1304
+ $this->debug("in serializeType: soapval overrides value to $value");
1305
+ if ($attrs) {
1306
+ if (!is_array($value)) {
1307
+ $value['!'] = $value;
1308
+ }
1309
+ foreach ($attrs as $n => $v) {
1310
+ $value['!' . $n] = $v;
1311
+ }
1312
+ $this->debug("in serializeType: soapval provides attributes");
1313
+ }
1314
+ } else {
1315
+ $forceType = false;
1316
+ }
1317
+
1318
+ $xml = '';
1319
+ if (strpos($type, ':')) {
1320
+ $uqType = substr($type, strrpos($type, ':') + 1);
1321
+ $ns = substr($type, 0, strrpos($type, ':'));
1322
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
1323
+ if ($this->getNamespaceFromPrefix($ns)) {
1324
+ $ns = $this->getNamespaceFromPrefix($ns);
1325
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
1326
+ }
1327
+
1328
+ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
1329
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
1330
+ if ($unqualified && $use == 'literal') {
1331
+ $elementNS = " xmlns=\"\"";
1332
+ } else {
1333
+ $elementNS = '';
1334
+ }
1335
+ if (is_null($value)) {
1336
+ if ($use == 'literal') {
1337
+ // TODO: depends on minOccurs
1338
+ $xml = "<$name$elementNS/>";
1339
+ } else {
1340
+ // TODO: depends on nillable, which should be checked before calling this method
1341
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1342
+ }
1343
+ $this->debug("in serializeType: returning: $xml");
1344
+ return $xml;
1345
+ }
1346
+ if ($uqType == 'Array') {
1347
+ // JBoss/Axis does this sometimes
1348
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
1349
+ }
1350
+ if ($uqType == 'boolean') {
1351
+ if ((is_string($value) && $value == 'false') || (! $value)) {
1352
+ $value = 'false';
1353
+ } else {
1354
+ $value = 'true';
1355
+ }
1356
+ }
1357
+ if ($uqType == 'string' && gettype($value) == 'string') {
1358
+ $value = $this->expandEntities($value);
1359
+ }
1360
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
1361
+ $value = sprintf("%.0lf", $value);
1362
+ }
1363
+ // it's a scalar
1364
+ // TODO: what about null/nil values?
1365
+ // check type isn't a custom type extending xmlschema namespace
1366
+ if (!$this->getTypeDef($uqType, $ns)) {
1367
+ if ($use == 'literal') {
1368
+ if ($forceType) {
1369
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1370
+ } else {
1371
+ $xml = "<$name$elementNS>$value</$name>";
1372
+ }
1373
+ } else {
1374
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1375
+ }
1376
+ $this->debug("in serializeType: returning: $xml");
1377
+ return $xml;
1378
+ }
1379
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
1380
+ } else if ($ns == 'http://xml.apache.org/xml-soap') {
1381
+ $this->debug('in serializeType: appears to be Apache SOAP type');
1382
+ if ($uqType == 'Map') {
1383
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1384
+ if (! $tt_prefix) {
1385
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
1386
+ $tt_prefix = 'ns' . rand(1000, 9999);
1387
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
1388
+ // force this to be added to usedNamespaces
1389
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
1390
+ }
1391
+ $contents = '';
1392
+ foreach($value as $k => $v) {
1393
+ $this->debug("serializing map element: key $k, value $v");
1394
+ $contents .= '<item>';
1395
+ $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
1396
+ $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
1397
+ $contents .= '</item>';
1398
+ }
1399
+ if ($use == 'literal') {
1400
+ if ($forceType) {
1401
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
1402
+ } else {
1403
+ $xml = "<$name>$contents</$name>";
1404
+ }
1405
+ } else {
1406
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
1407
+ }
1408
+ $this->debug("in serializeType: returning: $xml");
1409
+ return $xml;
1410
+ }
1411
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
1412
+ }
1413
+ } else {
1414
+ // TODO: should the type be compared to types in XSD, and the namespace
1415
+ // set to XSD if the type matches?
1416
+ $this->debug("in serializeType: No namespace for type $type");
1417
+ $ns = '';
1418
+ $uqType = $type;
1419
+ }
1420
+ if(!$typeDef = $this->getTypeDef($uqType, $ns)){
1421
+ $this->setError("$type ($uqType) is not a supported type.");
1422
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
1423
+ return false;
1424
+ } else {
1425
+ $this->debug("in serializeType: found typeDef");
1426
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
1427
+ if (substr($uqType, -1) == '^') {
1428
+ $uqType = substr($uqType, 0, -1);
1429
+ }
1430
+ }
1431
+ $phpType = $typeDef['phpType'];
1432
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
1433
+ // if php type == struct, map value to the <all> element names
1434
+ if ($phpType == 'struct') {
1435
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
1436
+ $elementName = $uqType;
1437
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1438
+ $elementNS = " xmlns=\"$ns\"";
1439
+ } else {
1440
+ $elementNS = " xmlns=\"\"";
1441
+ }
1442
+ } else {
1443
+ $elementName = $name;
1444
+ if ($unqualified) {
1445
+ $elementNS = " xmlns=\"\"";
1446
+ } else {
1447
+ $elementNS = '';
1448
+ }
1449
+ }
1450
+ if (is_null($value)) {
1451
+ if ($use == 'literal') {
1452
+ // TODO: depends on minOccurs
1453
+ $xml = "<$elementName$elementNS/>";
1454
+ } else {
1455
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
1456
+ }
1457
+ $this->debug("in serializeType: returning: $xml");
1458
+ return $xml;
1459
+ }
1460
+ if (is_object($value)) {
1461
+ $value = get_object_vars($value);
1462
+ }
1463
+ if (is_array($value)) {
1464
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1465
+ if ($use == 'literal') {
1466
+ if ($forceType) {
1467
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
1468
+ } else {
1469
+ $xml = "<$elementName$elementNS$elementAttrs>";
1470
+ }
1471
+ } else {
1472
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
1473
+ }
1474
+
1475
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1476
+ $xml .= "</$elementName>";
1477
+ } else {
1478
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
1479
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
1480
+ $xml = '';
1481
+ }
1482
+ } elseif ($phpType == 'array') {
1483
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1484
+ $elementNS = " xmlns=\"$ns\"";
1485
+ } else {
1486
+ if ($unqualified) {
1487
+ $elementNS = " xmlns=\"\"";
1488
+ } else {
1489
+ $elementNS = '';
1490
+ }
1491
+ }
1492
+ if (is_null($value)) {
1493
+ if ($use == 'literal') {
1494
+ // TODO: depends on minOccurs
1495
+ $xml = "<$name$elementNS/>";
1496
+ } else {
1497
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
1498
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1499
+ ":Array\" " .
1500
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
1501
+ ':arrayType="' .
1502
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
1503
+ ':' .
1504
+ $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
1505
+ }
1506
+ $this->debug("in serializeType: returning: $xml");
1507
+ return $xml;
1508
+ }
1509
+ if (isset($typeDef['multidimensional'])) {
1510
+ $nv = array();
1511
+ foreach($value as $v) {
1512
+ $cols = ',' . sizeof($v);
1513
+ $nv = array_merge($nv, $v);
1514
+ }
1515
+ $value = $nv;
1516
+ } else {
1517
+ $cols = '';
1518
+ }
1519
+ if (is_array($value) && sizeof($value) >= 1) {
1520
+ $rows = sizeof($value);
1521
+ $contents = '';
1522
+ foreach($value as $k => $v) {
1523
+ $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
1524
+ //if (strpos($typeDef['arrayType'], ':') ) {
1525
+ if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
1526
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
1527
+ } else {
1528
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
1529
+ }
1530
+ }
1531
+ } else {
1532
+ $rows = 0;
1533
+ $contents = null;
1534
+ }
1535
+ // TODO: for now, an empty value will be serialized as a zero element
1536
+ // array. Revisit this when coding the handling of null/nil values.
1537
+ if ($use == 'literal') {
1538
+ $xml = "<$name$elementNS>"
1539
+ .$contents
1540
+ ."</$name>";
1541
+ } else {
1542
+ $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
1543
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
1544
+ .':arrayType="'
1545
+ .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
1546
+ .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
1547
+ .$contents
1548
+ ."</$name>";
1549
+ }
1550
+ } elseif ($phpType == 'scalar') {
1551
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
1552
+ $elementNS = " xmlns=\"$ns\"";
1553
+ } else {
1554
+ if ($unqualified) {
1555
+ $elementNS = " xmlns=\"\"";
1556
+ } else {
1557
+ $elementNS = '';
1558
+ }
1559
+ }
1560
+ if ($use == 'literal') {
1561
+ if ($forceType) {
1562
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
1563
+ } else {
1564
+ $xml = "<$name$elementNS>$value</$name>";
1565
+ }
1566
+ } else {
1567
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
1568
+ }
1569
+ }
1570
+ $this->debug("in serializeType: returning: $xml");
1571
+ return $xml;
1572
+ }
1573
+
1574
+ /**
1575
+ * serializes the attributes for a complexType
1576
+ *
1577
+ * @param array $typeDef our internal representation of an XML schema type (or element)
1578
+ * @param mixed $value a native PHP value (parameter value)
1579
+ * @param string $ns the namespace of the type
1580
+ * @param string $uqType the local part of the type
1581
+ * @return string value serialized as an XML string
1582
+ * @access private
1583
+ */
1584
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
1585
+ $xml = '';
1586
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
1587
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
1588
+ if (is_array($value)) {
1589
+ $xvalue = $value;
1590
+ } elseif (is_object($value)) {
1591
+ $xvalue = get_object_vars($value);
1592
+ } else {
1593
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1594
+ $xvalue = array();
1595
+ }
1596
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
1597
+ if (isset($xvalue['!' . $aName])) {
1598
+ $xname = '!' . $aName;
1599
+ $this->debug("value provided for attribute $aName with key $xname");
1600
+ } elseif (isset($xvalue[$aName])) {
1601
+ $xname = $aName;
1602
+ $this->debug("value provided for attribute $aName with key $xname");
1603
+ } elseif (isset($attrs['default'])) {
1604
+ $xname = '!' . $aName;
1605
+ $xvalue[$xname] = $attrs['default'];
1606
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
1607
+ } else {
1608
+ $xname = '';
1609
+ $this->debug("no value provided for attribute $aName");
1610
+ }
1611
+ if ($xname) {
1612
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
1613
+ }
1614
+ }
1615
+ } else {
1616
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
1617
+ }
1618
+ if (isset($typeDef['extensionBase'])) {
1619
+ $ns = $this->getPrefix($typeDef['extensionBase']);
1620
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
1621
+ if ($this->getNamespaceFromPrefix($ns)) {
1622
+ $ns = $this->getNamespaceFromPrefix($ns);
1623
+ }
1624
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1625
+ $this->debug("serialize attributes for extension base $ns:$uqType");
1626
+ $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
1627
+ } else {
1628
+ $this->debug("extension base $ns:$uqType is not a supported type");
1629
+ }
1630
+ }
1631
+ return $xml;
1632
+ }
1633
+
1634
+ /**
1635
+ * serializes the elements for a complexType
1636
+ *
1637
+ * @param array $typeDef our internal representation of an XML schema type (or element)
1638
+ * @param mixed $value a native PHP value (parameter value)
1639
+ * @param string $ns the namespace of the type
1640
+ * @param string $uqType the local part of the type
1641
+ * @param string $use use for part (encoded|literal)
1642
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
1643
+ * @return string value serialized as an XML string
1644
+ * @access private
1645
+ */
1646
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
1647
+ $xml = '';
1648
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
1649
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
1650
+ if (is_array($value)) {
1651
+ $xvalue = $value;
1652
+ } elseif (is_object($value)) {
1653
+ $xvalue = get_object_vars($value);
1654
+ } else {
1655
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
1656
+ $xvalue = array();
1657
+ }
1658
+ // toggle whether all elements are present - ideally should validate against schema
1659
+ if (count($typeDef['elements']) != count($xvalue)){
1660
+ $optionals = true;
1661
+ }
1662
+ foreach ($typeDef['elements'] as $eName => $attrs) {
1663
+ if (!isset($xvalue[$eName])) {
1664
+ if (isset($attrs['default'])) {
1665
+ $xvalue[$eName] = $attrs['default'];
1666
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
1667
+ }
1668
+ }
1669
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
1670
+ if (isset($optionals)
1671
+ && (!isset($xvalue[$eName]))
1672
+ && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
1673
+ ){
1674
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
1675
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
1676
+ }
1677
+ // do nothing
1678
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
1679
+ } else {
1680
+ // get value
1681
+ if (isset($xvalue[$eName])) {
1682
+ $v = $xvalue[$eName];
1683
+ } else {
1684
+ $v = null;
1685
+ }
1686
+ if (isset($attrs['form'])) {
1687
+ $unqualified = ($attrs['form'] == 'unqualified');
1688
+ } else {
1689
+ $unqualified = false;
1690
+ }
1691
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
1692
+ $vv = $v;
1693
+ foreach ($vv as $k => $v) {
1694
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
1695
+ // serialize schema-defined type
1696
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1697
+ } else {
1698
+ // serialize generic type (can this ever really happen?)
1699
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1700
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1701
+ }
1702
+ }
1703
+ } else {
1704
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
1705
+ // serialize schema-defined type
1706
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
1707
+ } else {
1708
+ // serialize generic type (can this ever really happen?)
1709
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
1710
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
1711
+ }
1712
+ }
1713
+ }
1714
+ }
1715
+ } else {
1716
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
1717
+ }
1718
+ if (isset($typeDef['extensionBase'])) {
1719
+ $ns = $this->getPrefix($typeDef['extensionBase']);
1720
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
1721
+ if ($this->getNamespaceFromPrefix($ns)) {
1722
+ $ns = $this->getNamespaceFromPrefix($ns);
1723
+ }
1724
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
1725
+ $this->debug("serialize elements for extension base $ns:$uqType");
1726
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
1727
+ } else {
1728
+ $this->debug("extension base $ns:$uqType is not a supported type");
1729
+ }
1730
+ }
1731
+ return $xml;
1732
+ }
1733
+
1734
+ /**
1735
+ * adds an XML Schema complex type to the WSDL types
1736
+ *
1737
+ * @param string $name
1738
+ * @param string $typeClass (complexType|simpleType|attribute)
1739
+ * @param string $phpType currently supported are array and struct (php assoc array)
1740
+ * @param string $compositor (all|sequence|choice)
1741
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1742
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
1743
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
1744
+ * @param string $arrayType as namespace:name (xsd:string)
1745
+ * @see nusoap_xmlschema
1746
+ * @access public
1747
+ */
1748
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
1749
+ if (count($elements) > 0) {
1750
+ $eElements = array();
1751
+ foreach($elements as $n => $e){
1752
+ // expand each element
1753
+ $ee = array();
1754
+ foreach ($e as $k => $v) {
1755
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1756
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1757
+ $ee[$k] = $v;
1758
+ }
1759
+ $eElements[$n] = $ee;
1760
+ }
1761
+ $elements = $eElements;
1762
+ }
1763
+
1764
+ if (count($attrs) > 0) {
1765
+ foreach($attrs as $n => $a){
1766
+ // expand each attribute
1767
+ foreach ($a as $k => $v) {
1768
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1769
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1770
+ $aa[$k] = $v;
1771
+ }
1772
+ $eAttrs[$n] = $aa;
1773
+ }
1774
+ $attrs = $eAttrs;
1775
+ }
1776
+
1777
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1778
+ $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
1779
+
1780
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1781
+ $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
1782
+ }
1783
+
1784
+ /**
1785
+ * adds an XML Schema simple type to the WSDL types
1786
+ *
1787
+ * @param string $name
1788
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1789
+ * @param string $typeClass (should always be simpleType)
1790
+ * @param string $phpType (should always be scalar)
1791
+ * @param array $enumeration array of values
1792
+ * @see nusoap_xmlschema
1793
+ * @access public
1794
+ */
1795
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1796
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
1797
+
1798
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1799
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
1800
+ }
1801
+
1802
+ /**
1803
+ * adds an element to the WSDL types
1804
+ *
1805
+ * @param array $attrs attributes that must include name and type
1806
+ * @see nusoap_xmlschema
1807
+ * @access public
1808
+ */
1809
+ function addElement($attrs) {
1810
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
1811
+ $this->schemas[$typens][0]->addElement($attrs);
1812
+ }
1813
+
1814
+ /**
1815
+ * register an operation with the server
1816
+ *
1817
+ * @param string $name operation (method) name
1818
+ * @param array $in assoc array of input values: key = param name, value = param type
1819
+ * @param array $out assoc array of output values: key = param name, value = param type
1820
+ * @param string $namespace optional The namespace for the operation
1821
+ * @param string $soapaction optional The soapaction for the operation
1822
+ * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
1823
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
1824
+ * @param string $documentation optional The description to include in the WSDL
1825
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
1826
+ * @access public
1827
+ */
1828
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
1829
+ if ($use == 'encoded' && $encodingStyle == '') {
1830
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
1831
+ }
1832
+
1833
+ if ($style == 'document') {
1834
+ $elements = array();
1835
+ foreach ($in as $n => $t) {
1836
+ $elements[$n] = array('name' => $n, 'type' => $t);
1837
+ }
1838
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
1839
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
1840
+ $in = array('parameters' => 'tns:' . $name . '^');
1841
+
1842
+ $elements = array();
1843
+ foreach ($out as $n => $t) {
1844
+ $elements[$n] = array('name' => $n, 'type' => $t);
1845
+ }
1846
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
1847
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
1848
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
1849
+ }
1850
+
1851
+ // get binding
1852
+ $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
1853
+ array(
1854
+ 'name' => $name,
1855
+ 'binding' => $this->serviceName . 'Binding',
1856
+ 'endpoint' => $this->endpoint,
1857
+ 'soapAction' => $soapaction,
1858
+ 'style' => $style,
1859
+ 'input' => array(
1860
+ 'use' => $use,
1861
+ 'namespace' => $namespace,
1862
+ 'encodingStyle' => $encodingStyle,
1863
+ 'message' => $name . 'Request',
1864
+ 'parts' => $in),
1865
+ 'output' => array(
1866
+ 'use' => $use,
1867
+ 'namespace' => $namespace,
1868
+ 'encodingStyle' => $encodingStyle,
1869
+ 'message' => $name . 'Response',
1870
+ 'parts' => $out),
1871
+ 'namespace' => $namespace,
1872
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
1873
+ 'documentation' => $documentation);
1874
+ // add portTypes
1875
+ // add messages
1876
+ if($in)
1877
+ {
1878
+ foreach($in as $pName => $pType)
1879
+ {
1880
+ if(strpos($pType,':')) {
1881
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1882
+ }
1883
+ $this->messages[$name.'Request'][$pName] = $pType;
1884
+ }
1885
+ } else {
1886
+ $this->messages[$name.'Request']= '0';
1887
+ }
1888
+ if($out)
1889
+ {
1890
+ foreach($out as $pName => $pType)
1891
+ {
1892
+ if(strpos($pType,':')) {
1893
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
1894
+ }
1895
+ $this->messages[$name.'Response'][$pName] = $pType;
1896
+ }
1897
+ } else {
1898
+ $this->messages[$name.'Response']= '0';
1899
+ }
1900
+ return true;
1901
+ }
1902
+ }
1903
+
1904
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.wsdlcache.php ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ The NuSOAP project home is:
4
+ http://sourceforge.net/projects/nusoap/
5
+
6
+ The primary support for NuSOAP is the mailing list:
7
+ nusoap-general@lists.sourceforge.net
8
+ */
9
+
10
+ /**
11
+ * caches instances of the wsdl class
12
+ *
13
+ * @author Scott Nichol <snichol@users.sourceforge.net>
14
+ * @author Ingo Fischer <ingo@apollon.de>
15
+ * @version $Id: class.wsdlcache.php,v 1.7 2007/04/17 16:34:03 snichol Exp $
16
+ * @access public
17
+ */
18
+ class nusoap_wsdlcache {
19
+ /**
20
+ * @var resource
21
+ * @access private
22
+ */
23
+ var $fplock;
24
+ /**
25
+ * @var integer
26
+ * @access private
27
+ */
28
+ var $cache_lifetime;
29
+ /**
30
+ * @var string
31
+ * @access private
32
+ */
33
+ var $cache_dir;
34
+ /**
35
+ * @var string
36
+ * @access public
37
+ */
38
+ var $debug_str = '';
39
+
40
+ /**
41
+ * constructor
42
+ *
43
+ * @param string $cache_dir directory for cache-files
44
+ * @param integer $cache_lifetime lifetime for caching-files in seconds or 0 for unlimited
45
+ * @access public
46
+ */
47
+ function nusoap_wsdlcache($cache_dir='.', $cache_lifetime=0) {
48
+ $this->fplock = array();
49
+ $this->cache_dir = $cache_dir != '' ? $cache_dir : '.';
50
+ $this->cache_lifetime = $cache_lifetime;
51
+ }
52
+
53
+ /**
54
+ * creates the filename used to cache a wsdl instance
55
+ *
56
+ * @param string $wsdl The URL of the wsdl instance
57
+ * @return string The filename used to cache the instance
58
+ * @access private
59
+ */
60
+ function createFilename($wsdl) {
61
+ return $this->cache_dir.'/wsdlcache-' . md5($wsdl);
62
+ }
63
+
64
+ /**
65
+ * adds debug data to the class level debug string
66
+ *
67
+ * @param string $string debug data
68
+ * @access private
69
+ */
70
+ function debug($string){
71
+ $this->debug_str .= get_class($this).": $string\n";
72
+ }
73
+
74
+ /**
75
+ * gets a wsdl instance from the cache
76
+ *
77
+ * @param string $wsdl The URL of the wsdl instance
78
+ * @return object wsdl The cached wsdl instance, null if the instance is not in the cache
79
+ * @access public
80
+ */
81
+ function get($wsdl) {
82
+ $filename = $this->createFilename($wsdl);
83
+ if ($this->obtainMutex($filename, "r")) {
84
+ // check for expired WSDL that must be removed from the cache
85
+ if ($this->cache_lifetime > 0) {
86
+ if (file_exists($filename) && (time() - filemtime($filename) > $this->cache_lifetime)) {
87
+ unlink($filename);
88
+ $this->debug("Expired $wsdl ($filename) from cache");
89
+ $this->releaseMutex($filename);
90
+ return null;
91
+ }
92
+ }
93
+ // see what there is to return
94
+ if (!file_exists($filename)) {
95
+ $this->debug("$wsdl ($filename) not in cache (1)");
96
+ $this->releaseMutex($filename);
97
+ return null;
98
+ }
99
+ $fp = @fopen($filename, "r");
100
+ if ($fp) {
101
+ $s = implode("", @file($filename));
102
+ fclose($fp);
103
+ $this->debug("Got $wsdl ($filename) from cache");
104
+ } else {
105
+ $s = null;
106
+ $this->debug("$wsdl ($filename) not in cache (2)");
107
+ }
108
+ $this->releaseMutex($filename);
109
+ return (!is_null($s)) ? unserialize($s) : null;
110
+ } else {
111
+ $this->debug("Unable to obtain mutex for $filename in get");
112
+ }
113
+ return null;
114
+ }
115
+
116
+ /**
117
+ * obtains the local mutex
118
+ *
119
+ * @param string $filename The Filename of the Cache to lock
120
+ * @param string $mode The open-mode ("r" or "w") or the file - affects lock-mode
121
+ * @return boolean Lock successfully obtained ?!
122
+ * @access private
123
+ */
124
+ function obtainMutex($filename, $mode) {
125
+ if (isset($this->fplock[md5($filename)])) {
126
+ $this->debug("Lock for $filename already exists");
127
+ return false;
128
+ }
129
+ $this->fplock[md5($filename)] = fopen($filename.".lock", "w");
130
+ if ($mode == "r") {
131
+ return flock($this->fplock[md5($filename)], LOCK_SH);
132
+ } else {
133
+ return flock($this->fplock[md5($filename)], LOCK_EX);
134
+ }
135
+ }
136
+
137
+ /**
138
+ * adds a wsdl instance to the cache
139
+ *
140
+ * @param object wsdl $wsdl_instance The wsdl instance to add
141
+ * @return boolean WSDL successfully cached
142
+ * @access public
143
+ */
144
+ function put($wsdl_instance) {
145
+ $filename = $this->createFilename($wsdl_instance->wsdl);
146
+ $s = serialize($wsdl_instance);
147
+ if ($this->obtainMutex($filename, "w")) {
148
+ $fp = fopen($filename, "w");
149
+ if (! $fp) {
150
+ $this->debug("Cannot write $wsdl_instance->wsdl ($filename) in cache");
151
+ $this->releaseMutex($filename);
152
+ return false;
153
+ }
154
+ fputs($fp, $s);
155
+ fclose($fp);
156
+ $this->debug("Put $wsdl_instance->wsdl ($filename) in cache");
157
+ $this->releaseMutex($filename);
158
+ return true;
159
+ } else {
160
+ $this->debug("Unable to obtain mutex for $filename in put");
161
+ }
162
+ return false;
163
+ }
164
+
165
+ /**
166
+ * releases the local mutex
167
+ *
168
+ * @param string $filename The Filename of the Cache to lock
169
+ * @return boolean Lock successfully released
170
+ * @access private
171
+ */
172
+ function releaseMutex($filename) {
173
+ $ret = flock($this->fplock[md5($filename)], LOCK_UN);
174
+ fclose($this->fplock[md5($filename)]);
175
+ unset($this->fplock[md5($filename)]);
176
+ if (! $ret) {
177
+ $this->debug("Not able to release lock for $filename");
178
+ }
179
+ return $ret;
180
+ }
181
+
182
+ /**
183
+ * removes a wsdl instance from the cache
184
+ *
185
+ * @param string $wsdl The URL of the wsdl instance
186
+ * @return boolean Whether there was an instance to remove
187
+ * @access public
188
+ */
189
+ function remove($wsdl) {
190
+ $filename = $this->createFilename($wsdl);
191
+ if (!file_exists($filename)) {
192
+ $this->debug("$wsdl ($filename) not in cache to be removed");
193
+ return false;
194
+ }
195
+ // ignore errors obtaining mutex
196
+ $this->obtainMutex($filename, "w");
197
+ $ret = unlink($filename);
198
+ $this->debug("Removed ($ret) $wsdl ($filename) from cache");
199
+ $this->releaseMutex($filename);
200
+ return $ret;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * For backward compatibility
206
+ */
207
+ class wsdlcache extends nusoap_wsdlcache {
208
+ }
209
+ ?>
app/code/community/Easy/CEM/Model/Soap/class.xmlschema.php ADDED
@@ -0,0 +1,938 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+
5
+
6
+ /**
7
+ * parses an XML Schema, allows access to it's data, other utility methods.
8
+ * imperfect, no validation... yet, but quite functional.
9
+ *
10
+ * @author Dietrich Ayala <dietrich@ganx4.com>
11
+ * @author Scott Nichol <snichol@users.sourceforge.net>
12
+ * @version $Id: class.xmlschema.php,v 1.49 2007/11/06 14:17:53 snichol Exp $
13
+ * @access public
14
+ */
15
+ class nusoap_xmlschema extends nusoap_base {
16
+
17
+ // files
18
+ var $schema = '';
19
+ var $xml = '';
20
+ // namespaces
21
+ var $enclosingNamespaces;
22
+ // schema info
23
+ var $schemaInfo = array();
24
+ var $schemaTargetNamespace = '';
25
+ // types, elements, attributes defined by the schema
26
+ var $attributes = array();
27
+ var $complexTypes = array();
28
+ var $complexTypeStack = array();
29
+ var $currentComplexType = null;
30
+ var $elements = array();
31
+ var $elementStack = array();
32
+ var $currentElement = null;
33
+ var $simpleTypes = array();
34
+ var $simpleTypeStack = array();
35
+ var $currentSimpleType = null;
36
+ // imports
37
+ var $imports = array();
38
+ // parser vars
39
+ var $parser;
40
+ var $position = 0;
41
+ var $depth = 0;
42
+ var $depth_array = array();
43
+ var $message = array();
44
+ var $defaultNamespace = array();
45
+
46
+ /**
47
+ * constructor
48
+ *
49
+ * @param string $schema schema document URI
50
+ * @param string $xml xml document URI
51
+ * @param string $namespaces namespaces defined in enclosing XML
52
+ * @access public
53
+ */
54
+ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
55
+ parent::nusoap_base();
56
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
57
+ // files
58
+ $this->schema = $schema;
59
+ $this->xml = $xml;
60
+
61
+ // namespaces
62
+ $this->enclosingNamespaces = $namespaces;
63
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
64
+
65
+ // parse schema file
66
+ if($schema != ''){
67
+ $this->debug('initial schema file: '.$schema);
68
+ $this->parseFile($schema, 'schema');
69
+ }
70
+
71
+ // parse xml file
72
+ if($xml != ''){
73
+ $this->debug('initial xml file: '.$xml);
74
+ $this->parseFile($xml, 'xml');
75
+ }
76
+
77
+ }
78
+
79
+ /**
80
+ * parse an XML file
81
+ *
82
+ * @param string $xml path/URL to XML file
83
+ * @param string $type (schema | xml)
84
+ * @return boolean
85
+ * @access public
86
+ */
87
+ function parseFile($xml,$type){
88
+ // parse xml file
89
+ if($xml != ""){
90
+ $xmlStr = @join("",@file($xml));
91
+ if($xmlStr == ""){
92
+ $msg = 'Error reading XML from '.$xml;
93
+ $this->setError($msg);
94
+ $this->debug($msg);
95
+ return false;
96
+ } else {
97
+ $this->debug("parsing $xml");
98
+ $this->parseString($xmlStr,$type);
99
+ $this->debug("done parsing $xml");
100
+ return true;
101
+ }
102
+ }
103
+ return false;
104
+ }
105
+
106
+ /**
107
+ * parse an XML string
108
+ *
109
+ * @param string $xml path or URL
110
+ * @param string $type (schema|xml)
111
+ * @access private
112
+ */
113
+ function parseString($xml,$type){
114
+ // parse xml string
115
+ if($xml != ""){
116
+
117
+ // Create an XML parser.
118
+ $this->parser = xml_parser_create();
119
+ // Set the options for parsing the XML data.
120
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
121
+
122
+ // Set the object for the parser.
123
+ xml_set_object($this->parser, $this);
124
+
125
+ // Set the element handlers for the parser.
126
+ if($type == "schema"){
127
+ xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
128
+ xml_set_character_data_handler($this->parser,'schemaCharacterData');
129
+ } elseif($type == "xml"){
130
+ xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
131
+ xml_set_character_data_handler($this->parser,'xmlCharacterData');
132
+ }
133
+
134
+ // Parse the XML file.
135
+ if(!xml_parse($this->parser,$xml,true)){
136
+ // Display an error message.
137
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
138
+ xml_get_current_line_number($this->parser),
139
+ xml_error_string(xml_get_error_code($this->parser))
140
+ );
141
+ $this->debug($errstr);
142
+ $this->debug("XML payload:\n" . $xml);
143
+ $this->setError($errstr);
144
+ }
145
+
146
+ xml_parser_free($this->parser);
147
+ } else{
148
+ $this->debug('no xml passed to parseString()!!');
149
+ $this->setError('no xml passed to parseString()!!');
150
+ }
151
+ }
152
+
153
+ /**
154
+ * gets a type name for an unnamed type
155
+ *
156
+ * @param string Element name
157
+ * @return string A type name for an unnamed type
158
+ * @access private
159
+ */
160
+ function CreateTypeName($ename) {
161
+ $scope = '';
162
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
163
+ $scope .= $this->complexTypeStack[$i] . '_';
164
+ }
165
+ return $scope . $ename . '_ContainedType';
166
+ }
167
+
168
+ /**
169
+ * start-element handler
170
+ *
171
+ * @param string $parser XML parser object
172
+ * @param string $name element name
173
+ * @param string $attrs associative array of attributes
174
+ * @access private
175
+ */
176
+ function schemaStartElement($parser, $name, $attrs) {
177
+
178
+ // position in the total number of elements, starting from 0
179
+ $pos = $this->position++;
180
+ $depth = $this->depth++;
181
+ // set self as current value for this depth
182
+ $this->depth_array[$depth] = $pos;
183
+ $this->message[$pos] = array('cdata' => '');
184
+ if ($depth > 0) {
185
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
186
+ } else {
187
+ $this->defaultNamespace[$pos] = false;
188
+ }
189
+
190
+ // get element prefix
191
+ if($prefix = $this->getPrefix($name)){
192
+ // get unqualified name
193
+ $name = $this->getLocalPart($name);
194
+ } else {
195
+ $prefix = '';
196
+ }
197
+
198
+ // loop thru attributes, expanding, and registering namespace declarations
199
+ if(count($attrs) > 0){
200
+ foreach($attrs as $k => $v){
201
+ // if ns declarations, add to class level array of valid namespaces
202
+ if(ereg("^xmlns",$k)){
203
+ //$this->xdebug("$k: $v");
204
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
205
+ if($ns_prefix = substr(strrchr($k,':'),1)){
206
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
207
+ $this->namespaces[$ns_prefix] = $v;
208
+ } else {
209
+ $this->defaultNamespace[$pos] = $v;
210
+ if (! $this->getPrefixFromNamespace($v)) {
211
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
212
+ }
213
+ }
214
+ if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
215
+ $this->XMLSchemaVersion = $v;
216
+ $this->namespaces['xsi'] = $v.'-instance';
217
+ }
218
+ }
219
+ }
220
+ foreach($attrs as $k => $v){
221
+ // expand each attribute
222
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
223
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
224
+ $eAttrs[$k] = $v;
225
+ }
226
+ $attrs = $eAttrs;
227
+ } else {
228
+ $attrs = array();
229
+ }
230
+ // find status, register data
231
+ switch($name){
232
+ case 'all': // (optional) compositor content for a complexType
233
+ case 'choice':
234
+ case 'group':
235
+ case 'sequence':
236
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
237
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
238
+ //if($name == 'all' || $name == 'sequence'){
239
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
240
+ //}
241
+ break;
242
+ case 'attribute': // complexType attribute
243
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
244
+ $this->xdebug("parsing attribute:");
245
+ $this->appendDebug($this->varDump($attrs));
246
+ if (!isset($attrs['form'])) {
247
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
248
+ }
249
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
250
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
251
+ if (!strpos($v, ':')) {
252
+ // no namespace in arrayType attribute value...
253
+ if ($this->defaultNamespace[$pos]) {
254
+ // ...so use the default
255
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
256
+ }
257
+ }
258
+ }
259
+ if(isset($attrs['name'])){
260
+ $this->attributes[$attrs['name']] = $attrs;
261
+ $aname = $attrs['name'];
262
+ } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
263
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
264
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
265
+ } else {
266
+ $aname = '';
267
+ }
268
+ } elseif(isset($attrs['ref'])){
269
+ $aname = $attrs['ref'];
270
+ $this->attributes[$attrs['ref']] = $attrs;
271
+ }
272
+
273
+ if($this->currentComplexType){ // This should *always* be
274
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
275
+ }
276
+ // arrayType attribute
277
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
278
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
279
+ $prefix = $this->getPrefix($aname);
280
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
281
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
282
+ } else {
283
+ $v = '';
284
+ }
285
+ if(strpos($v,'[,]')){
286
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
287
+ }
288
+ $v = substr($v,0,strpos($v,'[')); // clip the []
289
+ if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
290
+ $v = $this->XMLSchemaVersion.':'.$v;
291
+ }
292
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
293
+ }
294
+ break;
295
+ case 'complexContent': // (optional) content for a complexType
296
+ break;
297
+ case 'complexType':
298
+ array_push($this->complexTypeStack, $this->currentComplexType);
299
+ if(isset($attrs['name'])){
300
+ // TODO: what is the scope of named complexTypes that appear
301
+ // nested within other c complexTypes?
302
+ $this->xdebug('processing named complexType '.$attrs['name']);
303
+ //$this->currentElement = false;
304
+ $this->currentComplexType = $attrs['name'];
305
+ $this->complexTypes[$this->currentComplexType] = $attrs;
306
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
307
+ // This is for constructs like
308
+ // <complexType name="ListOfString" base="soap:Array">
309
+ // <sequence>
310
+ // <element name="string" type="xsd:string"
311
+ // minOccurs="0" maxOccurs="unbounded" />
312
+ // </sequence>
313
+ // </complexType>
314
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
315
+ $this->xdebug('complexType is unusual array');
316
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
317
+ } else {
318
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
319
+ }
320
+ } else {
321
+ $name = $this->CreateTypeName($this->currentElement);
322
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
323
+ $this->currentComplexType = $name;
324
+ //$this->currentElement = false;
325
+ $this->complexTypes[$this->currentComplexType] = $attrs;
326
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
327
+ // This is for constructs like
328
+ // <complexType name="ListOfString" base="soap:Array">
329
+ // <sequence>
330
+ // <element name="string" type="xsd:string"
331
+ // minOccurs="0" maxOccurs="unbounded" />
332
+ // </sequence>
333
+ // </complexType>
334
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
335
+ $this->xdebug('complexType is unusual array');
336
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
337
+ } else {
338
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
339
+ }
340
+ }
341
+ break;
342
+ case 'element':
343
+ array_push($this->elementStack, $this->currentElement);
344
+ if (!isset($attrs['form'])) {
345
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
346
+ }
347
+ if(isset($attrs['type'])){
348
+ $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
349
+ if (! $this->getPrefix($attrs['type'])) {
350
+ if ($this->defaultNamespace[$pos]) {
351
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
352
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
353
+ }
354
+ }
355
+ // This is for constructs like
356
+ // <complexType name="ListOfString" base="soap:Array">
357
+ // <sequence>
358
+ // <element name="string" type="xsd:string"
359
+ // minOccurs="0" maxOccurs="unbounded" />
360
+ // </sequence>
361
+ // </complexType>
362
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
363
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
364
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
365
+ }
366
+ $this->currentElement = $attrs['name'];
367
+ $ename = $attrs['name'];
368
+ } elseif(isset($attrs['ref'])){
369
+ $this->xdebug("processing element as ref to ".$attrs['ref']);
370
+ $this->currentElement = "ref to ".$attrs['ref'];
371
+ $ename = $this->getLocalPart($attrs['ref']);
372
+ } else {
373
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
374
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
375
+ $this->currentElement = $attrs['name'];
376
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
377
+ $ename = $attrs['name'];
378
+ }
379
+ if (isset($ename) && $this->currentComplexType) {
380
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
381
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
382
+ } elseif (!isset($attrs['ref'])) {
383
+ $this->xdebug("add element $ename to elements array");
384
+ $this->elements[ $attrs['name'] ] = $attrs;
385
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
386
+ }
387
+ break;
388
+ case 'enumeration': // restriction value list member
389
+ $this->xdebug('enumeration ' . $attrs['value']);
390
+ if ($this->currentSimpleType) {
391
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
392
+ } elseif ($this->currentComplexType) {
393
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
394
+ }
395
+ break;
396
+ case 'extension': // simpleContent or complexContent type extension
397
+ $this->xdebug('extension ' . $attrs['base']);
398
+ if ($this->currentComplexType) {
399
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
400
+ }
401
+ break;
402
+ case 'import':
403
+ if (isset($attrs['schemaLocation'])) {
404
+ //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
405
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
406
+ } else {
407
+ //$this->xdebug('import namespace ' . $attrs['namespace']);
408
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
409
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
410
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
411
+ }
412
+ }
413
+ break;
414
+ case 'list': // simpleType value list
415
+ break;
416
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
417
+ $this->xdebug('restriction ' . $attrs['base']);
418
+ if($this->currentSimpleType){
419
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
420
+ } elseif($this->currentComplexType){
421
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
422
+ if(strstr($attrs['base'],':') == ':Array'){
423
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
424
+ }
425
+ }
426
+ break;
427
+ case 'schema':
428
+ $this->schemaInfo = $attrs;
429
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
430
+ if (isset($attrs['targetNamespace'])) {
431
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
432
+ }
433
+ if (!isset($attrs['elementFormDefault'])) {
434
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
435
+ }
436
+ if (!isset($attrs['attributeFormDefault'])) {
437
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
438
+ }
439
+ break;
440
+ case 'simpleContent': // (optional) content for a complexType
441
+ break;
442
+ case 'simpleType':
443
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
444
+ if(isset($attrs['name'])){
445
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
446
+ $this->currentSimpleType = $attrs['name'];
447
+ $this->simpleTypes[ $attrs['name'] ] = $attrs;
448
+ $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
449
+ $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
450
+ } else {
451
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
452
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
453
+ $this->currentSimpleType = $name;
454
+ //$this->currentElement = false;
455
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
456
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
457
+ }
458
+ break;
459
+ case 'union': // simpleType type list
460
+ break;
461
+ default:
462
+ //$this->xdebug("do not have anything to do for element $name");
463
+ }
464
+ }
465
+
466
+ /**
467
+ * end-element handler
468
+ *
469
+ * @param string $parser XML parser object
470
+ * @param string $name element name
471
+ * @access private
472
+ */
473
+ function schemaEndElement($parser, $name) {
474
+ // bring depth down a notch
475
+ $this->depth--;
476
+ // position of current element is equal to the last value left in depth_array for my depth
477
+ if(isset($this->depth_array[$this->depth])){
478
+ $pos = $this->depth_array[$this->depth];
479
+ }
480
+ // get element prefix
481
+ if ($prefix = $this->getPrefix($name)){
482
+ // get unqualified name
483
+ $name = $this->getLocalPart($name);
484
+ } else {
485
+ $prefix = '';
486
+ }
487
+ // move on...
488
+ if($name == 'complexType'){
489
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
490
+ $this->currentComplexType = array_pop($this->complexTypeStack);
491
+ //$this->currentElement = false;
492
+ }
493
+ if($name == 'element'){
494
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
495
+ $this->currentElement = array_pop($this->elementStack);
496
+ }
497
+ if($name == 'simpleType'){
498
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
499
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
500
+ }
501
+ }
502
+
503
+ /**
504
+ * element content handler
505
+ *
506
+ * @param string $parser XML parser object
507
+ * @param string $data element content
508
+ * @access private
509
+ */
510
+ function schemaCharacterData($parser, $data){
511
+ $pos = $this->depth_array[$this->depth - 1];
512
+ $this->message[$pos]['cdata'] .= $data;
513
+ }
514
+
515
+ /**
516
+ * serialize the schema
517
+ *
518
+ * @access public
519
+ */
520
+ function serializeSchema(){
521
+
522
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
523
+ $xml = '';
524
+ // imports
525
+ if (sizeof($this->imports) > 0) {
526
+ foreach($this->imports as $ns => $list) {
527
+ foreach ($list as $ii) {
528
+ if ($ii['location'] != '') {
529
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
530
+ } else {
531
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
532
+ }
533
+ }
534
+ }
535
+ }
536
+ // complex types
537
+ foreach($this->complexTypes as $typeName => $attrs){
538
+ $contentStr = '';
539
+ // serialize child elements
540
+ if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
541
+ foreach($attrs['elements'] as $element => $eParts){
542
+ if(isset($eParts['ref'])){
543
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
544
+ } else {
545
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
546
+ foreach ($eParts as $aName => $aValue) {
547
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
548
+ if ($aName != 'name' && $aName != 'type') {
549
+ $contentStr .= " $aName=\"$aValue\"";
550
+ }
551
+ }
552
+ $contentStr .= "/>\n";
553
+ }
554
+ }
555
+ // compositor wraps elements
556
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
557
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
558
+ }
559
+ }
560
+ // attributes
561
+ if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
562
+ foreach($attrs['attrs'] as $attr => $aParts){
563
+ $contentStr .= " <$schemaPrefix:attribute";
564
+ foreach ($aParts as $a => $v) {
565
+ if ($a == 'ref' || $a == 'type') {
566
+ $contentStr .= " $a=\"".$this->contractQName($v).'"';
567
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
568
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
569
+ $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
570
+ } else {
571
+ $contentStr .= " $a=\"$v\"";
572
+ }
573
+ }
574
+ $contentStr .= "/>\n";
575
+ }
576
+ }
577
+ // if restriction
578
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
579
+ $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
580
+ // complex or simple content
581
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
582
+ $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
583
+ }
584
+ }
585
+ // finalize complex type
586
+ if($contentStr != ''){
587
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
588
+ } else {
589
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
590
+ }
591
+ $xml .= $contentStr;
592
+ }
593
+ // simple types
594
+ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
595
+ foreach($this->simpleTypes as $typeName => $eParts){
596
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
597
+ if (isset($eParts['enumeration'])) {
598
+ foreach ($eParts['enumeration'] as $e) {
599
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
600
+ }
601
+ }
602
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
603
+ }
604
+ }
605
+ // elements
606
+ if(isset($this->elements) && count($this->elements) > 0){
607
+ foreach($this->elements as $element => $eParts){
608
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
609
+ }
610
+ }
611
+ // attributes
612
+ if(isset($this->attributes) && count($this->attributes) > 0){
613
+ foreach($this->attributes as $attr => $aParts){
614
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
615
+ }
616
+ }
617
+ // finish 'er up
618
+ $attr = '';
619
+ foreach ($this->schemaInfo as $k => $v) {
620
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
621
+ $attr .= " $k=\"$v\"";
622
+ }
623
+ }
624
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
625
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
626
+ $el .= " xmlns:$nsp=\"$ns\"";
627
+ }
628
+ $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
629
+ return $xml;
630
+ }
631
+
632
+ /**
633
+ * adds debug data to the clas level debug string
634
+ *
635
+ * @param string $string debug data
636
+ * @access private
637
+ */
638
+ function xdebug($string){
639
+ $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
640
+ }
641
+
642
+ /**
643
+ * get the PHP type of a user defined type in the schema
644
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
645
+ * returns false if no type exists, or not w/ the given namespace
646
+ * else returns a string that is either a native php type, or 'struct'
647
+ *
648
+ * @param string $type name of defined type
649
+ * @param string $ns namespace of type
650
+ * @return mixed
651
+ * @access public
652
+ * @deprecated
653
+ */
654
+ function getPHPType($type,$ns){
655
+ if(isset($this->typemap[$ns][$type])){
656
+ //print "found type '$type' and ns $ns in typemap<br>";
657
+ return $this->typemap[$ns][$type];
658
+ } elseif(isset($this->complexTypes[$type])){
659
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
660
+ return $this->complexTypes[$type]['phpType'];
661
+ }
662
+ return false;
663
+ }
664
+
665
+ /**
666
+ * returns an associative array of information about a given type
667
+ * returns false if no type exists by the given name
668
+ *
669
+ * For a complexType typeDef = array(
670
+ * 'restrictionBase' => '',
671
+ * 'phpType' => '',
672
+ * 'compositor' => '(sequence|all)',
673
+ * 'elements' => array(), // refs to elements array
674
+ * 'attrs' => array() // refs to attributes array
675
+ * ... and so on (see addComplexType)
676
+ * )
677
+ *
678
+ * For simpleType or element, the array has different keys.
679
+ *
680
+ * @param string $type
681
+ * @return mixed
682
+ * @access public
683
+ * @see addComplexType
684
+ * @see addSimpleType
685
+ * @see addElement
686
+ */
687
+ function getTypeDef($type){
688
+ //$this->debug("in getTypeDef for type $type");
689
+ if (substr($type, -1) == '^') {
690
+ $is_element = 1;
691
+ $type = substr($type, 0, -1);
692
+ } else {
693
+ $is_element = 0;
694
+ }
695
+
696
+ if((! $is_element) && isset($this->complexTypes[$type])){
697
+ $this->xdebug("in getTypeDef, found complexType $type");
698
+ return $this->complexTypes[$type];
699
+ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
700
+ $this->xdebug("in getTypeDef, found simpleType $type");
701
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
702
+ // get info for type to tack onto the simple type
703
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
704
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
705
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
706
+ $etype = $this->getTypeDef($uqType);
707
+ if ($etype) {
708
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
709
+ $this->xdebug($this->varDump($etype));
710
+ if (isset($etype['phpType'])) {
711
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
712
+ }
713
+ if (isset($etype['elements'])) {
714
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
715
+ }
716
+ }
717
+ }
718
+ return $this->simpleTypes[$type];
719
+ } elseif(isset($this->elements[$type])){
720
+ $this->xdebug("in getTypeDef, found element $type");
721
+ if (!isset($this->elements[$type]['phpType'])) {
722
+ // get info for type to tack onto the element
723
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
724
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
725
+ $etype = $this->getTypeDef($uqType);
726
+ if ($etype) {
727
+ $this->xdebug("in getTypeDef, found type for element $type:");
728
+ $this->xdebug($this->varDump($etype));
729
+ if (isset($etype['phpType'])) {
730
+ $this->elements[$type]['phpType'] = $etype['phpType'];
731
+ }
732
+ if (isset($etype['elements'])) {
733
+ $this->elements[$type]['elements'] = $etype['elements'];
734
+ }
735
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
736
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
737
+ $this->elements[$type]['phpType'] = 'scalar';
738
+ }
739
+ }
740
+ return $this->elements[$type];
741
+ } elseif(isset($this->attributes[$type])){
742
+ $this->xdebug("in getTypeDef, found attribute $type");
743
+ return $this->attributes[$type];
744
+ } elseif (ereg('_ContainedType$', $type)) {
745
+ $this->xdebug("in getTypeDef, have an untyped element $type");
746
+ $typeDef['typeClass'] = 'simpleType';
747
+ $typeDef['phpType'] = 'scalar';
748
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
749
+ return $typeDef;
750
+ }
751
+ $this->xdebug("in getTypeDef, did not find $type");
752
+ return false;
753
+ }
754
+
755
+ /**
756
+ * returns a sample serialization of a given type, or false if no type by the given name
757
+ *
758
+ * @param string $type name of type
759
+ * @return mixed
760
+ * @access public
761
+ * @deprecated
762
+ */
763
+ function serializeTypeDef($type){
764
+ //print "in sTD() for type $type<br>";
765
+ if($typeDef = $this->getTypeDef($type)){
766
+ $str .= '<'.$type;
767
+ if(is_array($typeDef['attrs'])){
768
+ foreach($typeDef['attrs'] as $attName => $data){
769
+ $str .= " $attName=\"{type = ".$data['type']."}\"";
770
+ }
771
+ }
772
+ $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
773
+ if(count($typeDef['elements']) > 0){
774
+ $str .= ">";
775
+ foreach($typeDef['elements'] as $element => $eData){
776
+ $str .= $this->serializeTypeDef($element);
777
+ }
778
+ $str .= "</$type>";
779
+ } elseif($typeDef['typeClass'] == 'element') {
780
+ $str .= "></$type>";
781
+ } else {
782
+ $str .= "/>";
783
+ }
784
+ return $str;
785
+ }
786
+ return false;
787
+ }
788
+
789
+ /**
790
+ * returns HTML form elements that allow a user
791
+ * to enter values for creating an instance of the given type.
792
+ *
793
+ * @param string $name name for type instance
794
+ * @param string $type name of type
795
+ * @return string
796
+ * @access public
797
+ * @deprecated
798
+ */
799
+ function typeToForm($name,$type){
800
+ // get typedef
801
+ if($typeDef = $this->getTypeDef($type)){
802
+ // if struct
803
+ if($typeDef['phpType'] == 'struct'){
804
+ $buffer .= '<table>';
805
+ foreach($typeDef['elements'] as $child => $childDef){
806
+ $buffer .= "
807
+ <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
808
+ <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
809
+ }
810
+ $buffer .= '</table>';
811
+ // if array
812
+ } elseif($typeDef['phpType'] == 'array'){
813
+ $buffer .= '<table>';
814
+ for($i=0;$i < 3; $i++){
815
+ $buffer .= "
816
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
817
+ <td><input type='text' name='parameters[".$name."][]'></td></tr>";
818
+ }
819
+ $buffer .= '</table>';
820
+ // if scalar
821
+ } else {
822
+ $buffer .= "<input type='text' name='parameters[$name]'>";
823
+ }
824
+ } else {
825
+ $buffer .= "<input type='text' name='parameters[$name]'>";
826
+ }
827
+ return $buffer;
828
+ }
829
+
830
+ /**
831
+ * adds a complex type to the schema
832
+ *
833
+ * example: array
834
+ *
835
+ * addType(
836
+ * 'ArrayOfstring',
837
+ * 'complexType',
838
+ * 'array',
839
+ * '',
840
+ * 'SOAP-ENC:Array',
841
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
842
+ * 'xsd:string'
843
+ * );
844
+ *
845
+ * example: PHP associative array ( SOAP Struct )
846
+ *
847
+ * addType(
848
+ * 'SOAPStruct',
849
+ * 'complexType',
850
+ * 'struct',
851
+ * 'all',
852
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
853
+ * );
854
+ *
855
+ * @param name
856
+ * @param typeClass (complexType|simpleType|attribute)
857
+ * @param phpType: currently supported are array and struct (php assoc array)
858
+ * @param compositor (all|sequence|choice)
859
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
860
+ * @param elements = array ( name = array(name=>'',type=>'') )
861
+ * @param attrs = array(
862
+ * array(
863
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
864
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
865
+ * )
866
+ * )
867
+ * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
868
+ * @access public
869
+ * @see getTypeDef
870
+ */
871
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
872
+ $this->complexTypes[$name] = array(
873
+ 'name' => $name,
874
+ 'typeClass' => $typeClass,
875
+ 'phpType' => $phpType,
876
+ 'compositor'=> $compositor,
877
+ 'restrictionBase' => $restrictionBase,
878
+ 'elements' => $elements,
879
+ 'attrs' => $attrs,
880
+ 'arrayType' => $arrayType
881
+ );
882
+
883
+ $this->xdebug("addComplexType $name:");
884
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
885
+ }
886
+
887
+ /**
888
+ * adds a simple type to the schema
889
+ *
890
+ * @param string $name
891
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
892
+ * @param string $typeClass (should always be simpleType)
893
+ * @param string $phpType (should always be scalar)
894
+ * @param array $enumeration array of values
895
+ * @access public
896
+ * @see nusoap_xmlschema
897
+ * @see getTypeDef
898
+ */
899
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
900
+ $this->simpleTypes[$name] = array(
901
+ 'name' => $name,
902
+ 'typeClass' => $typeClass,
903
+ 'phpType' => $phpType,
904
+ 'type' => $restrictionBase,
905
+ 'enumeration' => $enumeration
906
+ );
907
+
908
+ $this->xdebug("addSimpleType $name:");
909
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
910
+ }
911
+
912
+ /**
913
+ * adds an element to the schema
914
+ *
915
+ * @param array $attrs attributes that must include name and type
916
+ * @see nusoap_xmlschema
917
+ * @access public
918
+ */
919
+ function addElement($attrs) {
920
+ if (! $this->getPrefix($attrs['type'])) {
921
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
922
+ }
923
+ $this->elements[ $attrs['name'] ] = $attrs;
924
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
925
+
926
+ $this->xdebug("addElement " . $attrs['name']);
927
+ $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
928
+ }
929
+ }
930
+
931
+ /**
932
+ * Backward compatibility
933
+ */
934
+ class XMLSchema extends nusoap_xmlschema {
935
+ }
936
+
937
+
938
+ ?>
app/code/community/Easy/CEM/Model/Soap/nusoap.php ADDED
@@ -0,0 +1,7993 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
5
+
6
+ NuSOAP - Web Services Toolkit for PHP
7
+
8
+ Copyright (c) 2002 NuSphere Corporation
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General Public
21
+ License along with this library; if not, write to the Free Software
22
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
+
24
+ The NuSOAP project home is:
25
+ http://sourceforge.net/projects/nusoap/
26
+
27
+ The primary support for NuSOAP is the mailing list:
28
+ nusoap-general@lists.sourceforge.net
29
+
30
+ If you have any questions or comments, please email:
31
+
32
+ Dietrich Ayala
33
+ dietrich@ganx4.com
34
+ http://dietrich.ganx4.com/nusoap
35
+
36
+ NuSphere Corporation
37
+ http://www.nusphere.com
38
+
39
+ */
40
+
41
+ /*
42
+ * Some of the standards implmented in whole or part by NuSOAP:
43
+ *
44
+ * SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
45
+ * WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
46
+ * SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
47
+ * XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
48
+ * Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
49
+ * XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
50
+ * RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
51
+ * RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
52
+ * RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
53
+ */
54
+
55
+ /* load classes
56
+
57
+ // necessary classes
58
+ require_once('class.soapclient.php');
59
+ require_once('class.soap_val.php');
60
+ require_once('class.soap_parser.php');
61
+ require_once('class.soap_fault.php');
62
+
63
+ // transport classes
64
+ require_once('class.soap_transport_http.php');
65
+
66
+ // optional add-on classes
67
+ require_once('class.xmlschema.php');
68
+ require_once('class.wsdl.php');
69
+
70
+ // server class
71
+ require_once('class.soap_server.php');*/
72
+
73
+ // class variable emulation
74
+ // cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
75
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = 9;
76
+
77
+ /**
78
+ *
79
+ * nusoap_base
80
+ *
81
+ * @author Dietrich Ayala <dietrich@ganx4.com>
82
+ * @author Scott Nichol <snichol@users.sourceforge.net>
83
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
84
+ * @access public
85
+ */
86
+ class nusoap_base {
87
+ /**
88
+ * Identification for HTTP headers.
89
+ *
90
+ * @var string
91
+ * @access private
92
+ */
93
+ var $title = 'NuSOAP';
94
+ /**
95
+ * Version for HTTP headers.
96
+ *
97
+ * @var string
98
+ * @access private
99
+ */
100
+ var $version = '0.7.3';
101
+ /**
102
+ * CVS revision for HTTP headers.
103
+ *
104
+ * @var string
105
+ * @access private
106
+ */
107
+ var $revision = '$Revision: 1.114 $';
108
+ /**
109
+ * Current error string (manipulated by getError/setError)
110
+ *
111
+ * @var string
112
+ * @access private
113
+ */
114
+ var $error_str = '';
115
+ /**
116
+ * Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
117
+ *
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $debug_str = '';
122
+ /**
123
+ * toggles automatic encoding of special characters as entities
124
+ * (should always be true, I think)
125
+ *
126
+ * @var boolean
127
+ * @access private
128
+ */
129
+ var $charencoding = true;
130
+ /**
131
+ * the debug level for this instance
132
+ *
133
+ * @var integer
134
+ * @access private
135
+ */
136
+ var $debugLevel;
137
+
138
+ /**
139
+ * set schema version
140
+ *
141
+ * @var string
142
+ * @access public
143
+ */
144
+ var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
145
+
146
+ /**
147
+ * charset encoding for outgoing messages
148
+ *
149
+ * @var string
150
+ * @access public
151
+ */
152
+ var $soap_defencoding = 'ISO-8859-1';
153
+ //var $soap_defencoding = 'UTF-8';
154
+
155
+ /**
156
+ * namespaces in an array of prefix => uri
157
+ *
158
+ * this is "seeded" by a set of constants, but it may be altered by code
159
+ *
160
+ * @var array
161
+ * @access public
162
+ */
163
+ var $namespaces = array(
164
+ 'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
165
+ 'xsd' => 'http://www.w3.org/2001/XMLSchema',
166
+ 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
167
+ 'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
168
+ );
169
+
170
+ /**
171
+ * namespaces used in the current context, e.g. during serialization
172
+ *
173
+ * @var array
174
+ * @access private
175
+ */
176
+ var $usedNamespaces = array();
177
+
178
+ /**
179
+ * XML Schema types in an array of uri => (array of xml type => php type)
180
+ * is this legacy yet?
181
+ * no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
182
+ * @var array
183
+ * @access public
184
+ */
185
+ var $typemap = array(
186
+ 'http://www.w3.org/2001/XMLSchema' => array(
187
+ 'string'=>'string','boolean'=>'boolean','float'=>'double','double'=>'double','decimal'=>'double',
188
+ 'duration'=>'','dateTime'=>'string','time'=>'string','date'=>'string','gYearMonth'=>'',
189
+ 'gYear'=>'','gMonthDay'=>'','gDay'=>'','gMonth'=>'','hexBinary'=>'string','base64Binary'=>'string',
190
+ // abstract "any" types
191
+ 'anyType'=>'string','anySimpleType'=>'string',
192
+ // derived datatypes
193
+ 'normalizedString'=>'string','token'=>'string','language'=>'','NMTOKEN'=>'','NMTOKENS'=>'','Name'=>'','NCName'=>'','ID'=>'',
194
+ 'IDREF'=>'','IDREFS'=>'','ENTITY'=>'','ENTITIES'=>'','integer'=>'integer','nonPositiveInteger'=>'integer',
195
+ 'negativeInteger'=>'integer','long'=>'integer','int'=>'integer','short'=>'integer','byte'=>'integer','nonNegativeInteger'=>'integer',
196
+ 'unsignedLong'=>'','unsignedInt'=>'','unsignedShort'=>'','unsignedByte'=>'','positiveInteger'=>''),
197
+ 'http://www.w3.org/2000/10/XMLSchema' => array(
198
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
199
+ 'float'=>'double','dateTime'=>'string',
200
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
201
+ 'http://www.w3.org/1999/XMLSchema' => array(
202
+ 'i4'=>'','int'=>'integer','boolean'=>'boolean','string'=>'string','double'=>'double',
203
+ 'float'=>'double','dateTime'=>'string',
204
+ 'timeInstant'=>'string','base64Binary'=>'string','base64'=>'string','ur-type'=>'array'),
205
+ 'http://soapinterop.org/xsd' => array('SOAPStruct'=>'struct'),
206
+ 'http://schemas.xmlsoap.org/soap/encoding/' => array('base64'=>'string','array'=>'array','Array'=>'array'),
207
+ 'http://xml.apache.org/xml-soap' => array('Map')
208
+ );
209
+
210
+ /**
211
+ * XML entities to convert
212
+ *
213
+ * @var array
214
+ * @access public
215
+ * @deprecated
216
+ * @see expandEntities
217
+ */
218
+ var $xmlEntities = array('quot' => '"','amp' => '&',
219
+ 'lt' => '<','gt' => '>','apos' => "'");
220
+
221
+ /**
222
+ * constructor
223
+ *
224
+ * @access public
225
+ */
226
+ function nusoap_base() {
227
+ $this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
228
+ }
229
+
230
+ /**
231
+ * gets the global debug level, which applies to future instances
232
+ *
233
+ * @return integer Debug level 0-9, where 0 turns off
234
+ * @access public
235
+ */
236
+ function getGlobalDebugLevel() {
237
+ return $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel;
238
+ }
239
+
240
+ /**
241
+ * sets the global debug level, which applies to future instances
242
+ *
243
+ * @param int $level Debug level 0-9, where 0 turns off
244
+ * @access public
245
+ */
246
+ function setGlobalDebugLevel($level) {
247
+ $GLOBALS['_transient']['static']['nusoap_base']->globalDebugLevel = $level;
248
+ }
249
+
250
+ /**
251
+ * gets the debug level for this instance
252
+ *
253
+ * @return int Debug level 0-9, where 0 turns off
254
+ * @access public
255
+ */
256
+ function getDebugLevel() {
257
+ return $this->debugLevel;
258
+ }
259
+
260
+ /**
261
+ * sets the debug level for this instance
262
+ *
263
+ * @param int $level Debug level 0-9, where 0 turns off
264
+ * @access public
265
+ */
266
+ function setDebugLevel($level) {
267
+ $this->debugLevel = $level;
268
+ }
269
+
270
+ /**
271
+ * adds debug data to the instance debug string with formatting
272
+ *
273
+ * @param string $string debug data
274
+ * @access private
275
+ */
276
+ function debug($string){
277
+ if ($this->debugLevel > 0) {
278
+ $this->appendDebug($this->getmicrotime().' '.get_class($this).": $string\n");
279
+ }
280
+ }
281
+
282
+ /**
283
+ * adds debug data to the instance debug string without formatting
284
+ *
285
+ * @param string $string debug data
286
+ * @access public
287
+ */
288
+ function appendDebug($string){
289
+ if ($this->debugLevel > 0) {
290
+ // it would be nice to use a memory stream here to use
291
+ // memory more efficiently
292
+ $this->debug_str .= $string;
293
+ }
294
+ }
295
+
296
+ /**
297
+ * clears the current debug data for this instance
298
+ *
299
+ * @access public
300
+ */
301
+ function clearDebug() {
302
+ // it would be nice to use a memory stream here to use
303
+ // memory more efficiently
304
+ $this->debug_str = '';
305
+ }
306
+
307
+ /**
308
+ * gets the current debug data for this instance
309
+ *
310
+ * @return debug data
311
+ * @access public
312
+ */
313
+ function &getDebug() {
314
+ // it would be nice to use a memory stream here to use
315
+ // memory more efficiently
316
+ return $this->debug_str;
317
+ }
318
+
319
+ /**
320
+ * gets the current debug data for this instance as an XML comment
321
+ * this may change the contents of the debug data
322
+ *
323
+ * @return debug data as an XML comment
324
+ * @access public
325
+ */
326
+ function &getDebugAsXMLComment() {
327
+ // it would be nice to use a memory stream here to use
328
+ // memory more efficiently
329
+ while (strpos($this->debug_str, '--')) {
330
+ $this->debug_str = str_replace('--', '- -', $this->debug_str);
331
+ }
332
+ $ret = "<!--\n" . $this->debug_str . "\n-->";
333
+ return $ret;
334
+ }
335
+
336
+ /**
337
+ * expands entities, e.g. changes '<' to '&lt;'.
338
+ *
339
+ * @param string $val The string in which to expand entities.
340
+ * @access private
341
+ */
342
+ function expandEntities($val) {
343
+ if ($this->charencoding) {
344
+ $val = str_replace('&', '&amp;', $val);
345
+ $val = str_replace("'", '&apos;', $val);
346
+ $val = str_replace('"', '&quot;', $val);
347
+ $val = str_replace('<', '&lt;', $val);
348
+ $val = str_replace('>', '&gt;', $val);
349
+ }
350
+ return $val;
351
+ }
352
+
353
+ /**
354
+ * returns error string if present
355
+ *
356
+ * @return mixed error string or false
357
+ * @access public
358
+ */
359
+ function getError(){
360
+ if($this->error_str != ''){
361
+ return $this->error_str;
362
+ }
363
+ return false;
364
+ }
365
+
366
+ /**
367
+ * sets error string
368
+ *
369
+ * @return boolean $string error string
370
+ * @access private
371
+ */
372
+ function setError($str){
373
+ $this->error_str = $str;
374
+ }
375
+
376
+ /**
377
+ * detect if array is a simple array or a struct (associative array)
378
+ *
379
+ * @param mixed $val The PHP array
380
+ * @return string (arraySimple|arrayStruct)
381
+ * @access private
382
+ */
383
+ function isArraySimpleOrStruct($val) {
384
+ $keyList = array_keys($val);
385
+ foreach ($keyList as $keyListValue) {
386
+ if (!is_int($keyListValue)) {
387
+ return 'arrayStruct';
388
+ }
389
+ }
390
+ return 'arraySimple';
391
+ }
392
+
393
+ /**
394
+ * serializes PHP values in accordance w/ section 5. Type information is
395
+ * not serialized if $use == 'literal'.
396
+ *
397
+ * @param mixed $val The value to serialize
398
+ * @param string $name The name (local part) of the XML element
399
+ * @param string $type The XML schema type (local part) for the element
400
+ * @param string $name_ns The namespace for the name of the XML element
401
+ * @param string $type_ns The namespace for the type of the element
402
+ * @param array $attributes The attributes to serialize as name=>value pairs
403
+ * @param string $use The WSDL "use" (encoded|literal)
404
+ * @param boolean $soapval Whether this is called from soapval.
405
+ * @return string The serialized element, possibly with child elements
406
+ * @access public
407
+ */
408
+ function serialize_val($val,$name=false,$type=false,$name_ns=false,$type_ns=false,$attributes=false,$use='encoded',$soapval=false) {
409
+ $this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
410
+ $this->appendDebug('value=' . $this->varDump($val));
411
+ $this->appendDebug('attributes=' . $this->varDump($attributes));
412
+
413
+ if (is_object($val) && get_class($val) == 'soapval' && (! $soapval)) {
414
+ $this->debug("serialize_val: serialize soapval");
415
+ $xml = $val->serialize($use);
416
+ $this->appendDebug($val->getDebug());
417
+ $val->clearDebug();
418
+ $this->debug("serialize_val of soapval returning $xml");
419
+ return $xml;
420
+ }
421
+ // force valid name if necessary
422
+ if (is_numeric($name)) {
423
+ $name = '__numeric_' . $name;
424
+ } elseif (! $name) {
425
+ $name = 'noname';
426
+ }
427
+ // if name has ns, add ns prefix to name
428
+ $xmlns = '';
429
+ if($name_ns){
430
+ $prefix = 'nu'.rand(1000,9999);
431
+ $name = $prefix.':'.$name;
432
+ $xmlns .= " xmlns:$prefix=\"$name_ns\"";
433
+ }
434
+ // if type is prefixed, create type prefix
435
+ if($type_ns != '' && $type_ns == $this->namespaces['xsd']){
436
+ // need to fix this. shouldn't default to xsd if no ns specified
437
+ // w/o checking against typemap
438
+ $type_prefix = 'xsd';
439
+ } elseif($type_ns){
440
+ $type_prefix = 'ns'.rand(1000,9999);
441
+ $xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
442
+ }
443
+ // serialize attributes if present
444
+ $atts = '';
445
+ if($attributes){
446
+ foreach($attributes as $k => $v){
447
+ $atts .= " $k=\"".$this->expandEntities($v).'"';
448
+ }
449
+ }
450
+ // serialize null value
451
+ if (is_null($val)) {
452
+ $this->debug("serialize_val: serialize null");
453
+ if ($use == 'literal') {
454
+ // TODO: depends on minOccurs
455
+ $xml = "<$name$xmlns$atts/>";
456
+ $this->debug("serialize_val returning $xml");
457
+ return $xml;
458
+ } else {
459
+ if (isset($type) && isset($type_prefix)) {
460
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
461
+ } else {
462
+ $type_str = '';
463
+ }
464
+ $xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
465
+ $this->debug("serialize_val returning $xml");
466
+ return $xml;
467
+ }
468
+ }
469
+ // serialize if an xsd built-in primitive type
470
+ if($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])){
471
+ $this->debug("serialize_val: serialize xsd built-in primitive type");
472
+ if (is_bool($val)) {
473
+ if ($type == 'boolean') {
474
+ $val = $val ? 'true' : 'false';
475
+ } elseif (! $val) {
476
+ $val = 0;
477
+ }
478
+ } else if (is_string($val)) {
479
+ $val = $this->expandEntities($val);
480
+ }
481
+ if ($use == 'literal') {
482
+ $xml = "<$name$xmlns$atts>$val</$name>";
483
+ $this->debug("serialize_val returning $xml");
484
+ return $xml;
485
+ } else {
486
+ $xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
487
+ $this->debug("serialize_val returning $xml");
488
+ return $xml;
489
+ }
490
+ }
491
+ // detect type and serialize
492
+ $xml = '';
493
+ switch(true) {
494
+ case (is_bool($val) || $type == 'boolean'):
495
+ $this->debug("serialize_val: serialize boolean");
496
+ if ($type == 'boolean') {
497
+ $val = $val ? 'true' : 'false';
498
+ } elseif (! $val) {
499
+ $val = 0;
500
+ }
501
+ if ($use == 'literal') {
502
+ $xml .= "<$name$xmlns$atts>$val</$name>";
503
+ } else {
504
+ $xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
505
+ }
506
+ break;
507
+ case (is_int($val) || is_long($val) || $type == 'int'):
508
+ $this->debug("serialize_val: serialize int");
509
+ if ($use == 'literal') {
510
+ $xml .= "<$name$xmlns$atts>$val</$name>";
511
+ } else {
512
+ $xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
513
+ }
514
+ break;
515
+ case (is_float($val)|| is_double($val) || $type == 'float'):
516
+ $this->debug("serialize_val: serialize float");
517
+ if ($use == 'literal') {
518
+ $xml .= "<$name$xmlns$atts>$val</$name>";
519
+ } else {
520
+ $xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
521
+ }
522
+ break;
523
+ case (is_string($val) || $type == 'string'):
524
+ $this->debug("serialize_val: serialize string");
525
+ $val = $this->expandEntities($val);
526
+ if ($use == 'literal') {
527
+ $xml .= "<$name$xmlns$atts>$val</$name>";
528
+ } else {
529
+ $xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
530
+ }
531
+ break;
532
+ case is_object($val):
533
+ $this->debug("serialize_val: serialize object");
534
+ if (get_class($val) == 'soapval') {
535
+ $this->debug("serialize_val: serialize soapval object");
536
+ $pXml = $val->serialize($use);
537
+ $this->appendDebug($val->getDebug());
538
+ $val->clearDebug();
539
+ } else {
540
+ if (! $name) {
541
+ $name = get_class($val);
542
+ $this->debug("In serialize_val, used class name $name as element name");
543
+ } else {
544
+ $this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
545
+ }
546
+ foreach(get_object_vars($val) as $k => $v){
547
+ $pXml = isset($pXml) ? $pXml.$this->serialize_val($v,$k,false,false,false,false,$use) : $this->serialize_val($v,$k,false,false,false,false,$use);
548
+ }
549
+ }
550
+ if(isset($type) && isset($type_prefix)){
551
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
552
+ } else {
553
+ $type_str = '';
554
+ }
555
+ if ($use == 'literal') {
556
+ $xml .= "<$name$xmlns$atts>$pXml</$name>";
557
+ } else {
558
+ $xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
559
+ }
560
+ break;
561
+ break;
562
+ case (is_array($val) || $type):
563
+ // detect if struct or array
564
+ $valueType = $this->isArraySimpleOrStruct($val);
565
+ if($valueType=='arraySimple' || ereg('^ArrayOf',$type)){
566
+ $this->debug("serialize_val: serialize array");
567
+ $i = 0;
568
+ if(is_array($val) && count($val)> 0){
569
+ foreach($val as $v){
570
+ if(is_object($v) && get_class($v) == 'soapval'){
571
+ $tt_ns = $v->type_ns;
572
+ $tt = $v->type;
573
+ } elseif (is_array($v)) {
574
+ $tt = $this->isArraySimpleOrStruct($v);
575
+ } else {
576
+ $tt = gettype($v);
577
+ }
578
+ $array_types[$tt] = 1;
579
+ // TODO: for literal, the name should be $name
580
+ $xml .= $this->serialize_val($v,'item',false,false,false,false,$use);
581
+ ++$i;
582
+ }
583
+ if(count($array_types) > 1){
584
+ $array_typename = 'xsd:anyType';
585
+ } elseif(isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
586
+ if ($tt == 'integer') {
587
+ $tt = 'int';
588
+ }
589
+ $array_typename = 'xsd:'.$tt;
590
+ } elseif(isset($tt) && $tt == 'arraySimple'){
591
+ $array_typename = 'SOAP-ENC:Array';
592
+ } elseif(isset($tt) && $tt == 'arrayStruct'){
593
+ $array_typename = 'unnamed_struct_use_soapval';
594
+ } else {
595
+ // if type is prefixed, create type prefix
596
+ if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']){
597
+ $array_typename = 'xsd:' . $tt;
598
+ } elseif ($tt_ns) {
599
+ $tt_prefix = 'ns' . rand(1000, 9999);
600
+ $array_typename = "$tt_prefix:$tt";
601
+ $xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
602
+ } else {
603
+ $array_typename = $tt;
604
+ }
605
+ }
606
+ $array_type = $i;
607
+ if ($use == 'literal') {
608
+ $type_str = '';
609
+ } else if (isset($type) && isset($type_prefix)) {
610
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
611
+ } else {
612
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"".$array_typename."[$array_type]\"";
613
+ }
614
+ // empty array
615
+ } else {
616
+ if ($use == 'literal') {
617
+ $type_str = '';
618
+ } else if (isset($type) && isset($type_prefix)) {
619
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
620
+ } else {
621
+ $type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
622
+ }
623
+ }
624
+ // TODO: for array in literal, there is no wrapper here
625
+ $xml = "<$name$xmlns$type_str$atts>".$xml."</$name>";
626
+ } else {
627
+ // got a struct
628
+ $this->debug("serialize_val: serialize struct");
629
+ if(isset($type) && isset($type_prefix)){
630
+ $type_str = " xsi:type=\"$type_prefix:$type\"";
631
+ } else {
632
+ $type_str = '';
633
+ }
634
+ if ($use == 'literal') {
635
+ $xml .= "<$name$xmlns$atts>";
636
+ } else {
637
+ $xml .= "<$name$xmlns$type_str$atts>";
638
+ }
639
+ foreach($val as $k => $v){
640
+ // Apache Map
641
+ if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
642
+ $xml .= '<item>';
643
+ $xml .= $this->serialize_val($k,'key',false,false,false,false,$use);
644
+ $xml .= $this->serialize_val($v,'value',false,false,false,false,$use);
645
+ $xml .= '</item>';
646
+ } else {
647
+ $xml .= $this->serialize_val($v,$k,false,false,false,false,$use);
648
+ }
649
+ }
650
+ $xml .= "</$name>";
651
+ }
652
+ break;
653
+ default:
654
+ $this->debug("serialize_val: serialize unknown");
655
+ $xml .= 'not detected, got '.gettype($val).' for '.$val;
656
+ break;
657
+ }
658
+ $this->debug("serialize_val returning $xml");
659
+ return $xml;
660
+ }
661
+
662
+ /**
663
+ * serializes a message
664
+ *
665
+ * @param string $body the XML of the SOAP body
666
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
667
+ * @param array $namespaces optional the namespaces used in generating the body and headers
668
+ * @param string $style optional (rpc|document)
669
+ * @param string $use optional (encoded|literal)
670
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
671
+ * @return string the message
672
+ * @access public
673
+ */
674
+ function serializeEnvelope($body,$headers=false,$namespaces=array(),$style='rpc',$use='encoded',$encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'){
675
+ // TODO: add an option to automatically run utf8_encode on $body and $headers
676
+ // if $this->soap_defencoding is UTF-8. Not doing this automatically allows
677
+ // one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
678
+
679
+ $this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
680
+ $this->debug("headers:");
681
+ $this->appendDebug($this->varDump($headers));
682
+ $this->debug("namespaces:");
683
+ $this->appendDebug($this->varDump($namespaces));
684
+
685
+ // serialize namespaces
686
+ $ns_string = '';
687
+ foreach(array_merge($this->namespaces,$namespaces) as $k => $v){
688
+ $ns_string .= " xmlns:$k=\"$v\"";
689
+ }
690
+ if($encodingStyle) {
691
+ $ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
692
+ }
693
+
694
+ // serialize headers
695
+ if($headers){
696
+ if (is_array($headers)) {
697
+ $xml = '';
698
+ foreach ($headers as $k => $v) {
699
+ if (is_object($v) && get_class($v) == 'soapval') {
700
+ $xml .= $this->serialize_val($v, false, false, false, false, false, $use);
701
+ } else {
702
+ $xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
703
+ }
704
+ }
705
+ $headers = $xml;
706
+ $this->debug("In serializeEnvelope, serialized array of headers to $headers");
707
+ }
708
+ $headers = "<SOAP-ENV:Header>".$headers."</SOAP-ENV:Header>";
709
+ }
710
+ // serialize envelope
711
+ return
712
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding .'"?'.">".
713
+ '<SOAP-ENV:Envelope'.$ns_string.">".
714
+ $headers.
715
+ "<SOAP-ENV:Body>".
716
+ $body.
717
+ "</SOAP-ENV:Body>".
718
+ "</SOAP-ENV:Envelope>";
719
+ }
720
+
721
+ /**
722
+ * formats a string to be inserted into an HTML stream
723
+ *
724
+ * @param string $str The string to format
725
+ * @return string The formatted string
726
+ * @access public
727
+ * @deprecated
728
+ */
729
+ function formatDump($str){
730
+ $str = htmlspecialchars($str);
731
+ return nl2br($str);
732
+ }
733
+
734
+ /**
735
+ * contracts (changes namespace to prefix) a qualified name
736
+ *
737
+ * @param string $qname qname
738
+ * @return string contracted qname
739
+ * @access private
740
+ */
741
+ function contractQname($qname){
742
+ // get element namespace
743
+ //$this->xdebug("Contract $qname");
744
+ if (strrpos($qname, ':')) {
745
+ // get unqualified name
746
+ $name = substr($qname, strrpos($qname, ':') + 1);
747
+ // get ns
748
+ $ns = substr($qname, 0, strrpos($qname, ':'));
749
+ $p = $this->getPrefixFromNamespace($ns);
750
+ if ($p) {
751
+ return $p . ':' . $name;
752
+ }
753
+ return $qname;
754
+ } else {
755
+ return $qname;
756
+ }
757
+ }
758
+
759
+ /**
760
+ * expands (changes prefix to namespace) a qualified name
761
+ *
762
+ * @param string $qname qname
763
+ * @return string expanded qname
764
+ * @access private
765
+ */
766
+ function expandQname($qname){
767
+ // get element prefix
768
+ if(strpos($qname,':') && !ereg('^http://',$qname)){
769
+ // get unqualified name
770
+ $name = substr(strstr($qname,':'),1);
771
+ // get ns prefix
772
+ $prefix = substr($qname,0,strpos($qname,':'));
773
+ if(isset($this->namespaces[$prefix])){
774
+ return $this->namespaces[$prefix].':'.$name;
775
+ } else {
776
+ return $qname;
777
+ }
778
+ } else {
779
+ return $qname;
780
+ }
781
+ }
782
+
783
+ /**
784
+ * returns the local part of a prefixed string
785
+ * returns the original string, if not prefixed
786
+ *
787
+ * @param string $str The prefixed string
788
+ * @return string The local part
789
+ * @access public
790
+ */
791
+ function getLocalPart($str){
792
+ if($sstr = strrchr($str,':')){
793
+ // get unqualified name
794
+ return substr( $sstr, 1 );
795
+ } else {
796
+ return $str;
797
+ }
798
+ }
799
+
800
+ /**
801
+ * returns the prefix part of a prefixed string
802
+ * returns false, if not prefixed
803
+ *
804
+ * @param string $str The prefixed string
805
+ * @return mixed The prefix or false if there is no prefix
806
+ * @access public
807
+ */
808
+ function getPrefix($str){
809
+ if($pos = strrpos($str,':')){
810
+ // get prefix
811
+ return substr($str,0,$pos);
812
+ }
813
+ return false;
814
+ }
815
+
816
+ /**
817
+ * pass it a prefix, it returns a namespace
818
+ *
819
+ * @param string $prefix The prefix
820
+ * @return mixed The namespace, false if no namespace has the specified prefix
821
+ * @access public
822
+ */
823
+ function getNamespaceFromPrefix($prefix){
824
+ if (isset($this->namespaces[$prefix])) {
825
+ return $this->namespaces[$prefix];
826
+ }
827
+ //$this->setError("No namespace registered for prefix '$prefix'");
828
+ return false;
829
+ }
830
+
831
+ /**
832
+ * returns the prefix for a given namespace (or prefix)
833
+ * or false if no prefixes registered for the given namespace
834
+ *
835
+ * @param string $ns The namespace
836
+ * @return mixed The prefix, false if the namespace has no prefixes
837
+ * @access public
838
+ */
839
+ function getPrefixFromNamespace($ns) {
840
+ foreach ($this->namespaces as $p => $n) {
841
+ if ($ns == $n || $ns == $p) {
842
+ $this->usedNamespaces[$p] = $n;
843
+ return $p;
844
+ }
845
+ }
846
+ return false;
847
+ }
848
+
849
+ /**
850
+ * returns the time in ODBC canonical form with microseconds
851
+ *
852
+ * @return string The time in ODBC canonical form with microseconds
853
+ * @access public
854
+ */
855
+ function getmicrotime() {
856
+ if (function_exists('gettimeofday')) {
857
+ $tod = gettimeofday();
858
+ $sec = $tod['sec'];
859
+ $usec = $tod['usec'];
860
+ } else {
861
+ $sec = time();
862
+ $usec = 0;
863
+ }
864
+ return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
865
+ }
866
+
867
+ /**
868
+ * Returns a string with the output of var_dump
869
+ *
870
+ * @param mixed $data The variable to var_dump
871
+ * @return string The output of var_dump
872
+ * @access public
873
+ */
874
+ function varDump($data) {
875
+ ob_start();
876
+ var_dump($data);
877
+ $ret_val = ob_get_contents();
878
+ ob_end_clean();
879
+ return $ret_val;
880
+ }
881
+
882
+ /**
883
+ * represents the object as a string
884
+ *
885
+ * @return string
886
+ * @access public
887
+ */
888
+ function __toString() {
889
+ return $this->varDump($this);
890
+ }
891
+ }
892
+
893
+ // XML Schema Datatype Helper Functions
894
+
895
+ //xsd:dateTime helpers
896
+
897
+ /**
898
+ * convert unix timestamp to ISO 8601 compliant date string
899
+ *
900
+ * @param string $timestamp Unix time stamp
901
+ * @param boolean $utc Whether the time stamp is UTC or local
902
+ * @access public
903
+ */
904
+ function timestamp_to_iso8601($timestamp,$utc=true){
905
+ $datestr = date('Y-m-d\TH:i:sO',$timestamp);
906
+ if($utc){
907
+ $eregStr =
908
+ '([0-9]{4})-'. // centuries & years CCYY-
909
+ '([0-9]{2})-'. // months MM-
910
+ '([0-9]{2})'. // days DD
911
+ 'T'. // separator T
912
+ '([0-9]{2}):'. // hours hh:
913
+ '([0-9]{2}):'. // minutes mm:
914
+ '([0-9]{2})(\.[0-9]*)?'. // seconds ss.ss...
915
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
916
+
917
+ if(ereg($eregStr,$datestr,$regs)){
918
+ return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ',$regs[1],$regs[2],$regs[3],$regs[4],$regs[5],$regs[6]);
919
+ }
920
+ return false;
921
+ } else {
922
+ return $datestr;
923
+ }
924
+ }
925
+
926
+ /**
927
+ * convert ISO 8601 compliant date string to unix timestamp
928
+ *
929
+ * @param string $datestr ISO 8601 compliant date string
930
+ * @access public
931
+ */
932
+ function iso8601_to_timestamp($datestr){
933
+ $eregStr =
934
+ '([0-9]{4})-'. // centuries & years CCYY-
935
+ '([0-9]{2})-'. // months MM-
936
+ '([0-9]{2})'. // days DD
937
+ 'T'. // separator T
938
+ '([0-9]{2}):'. // hours hh:
939
+ '([0-9]{2}):'. // minutes mm:
940
+ '([0-9]{2})(\.[0-9]+)?'. // seconds ss.ss...
941
+ '(Z|[+\-][0-9]{2}:?[0-9]{2})?'; // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
942
+ if(ereg($eregStr,$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
+ }
962
+
963
+ /**
964
+ * sleeps some number of microseconds
965
+ *
966
+ * @param string $usec the number of microseconds to sleep
967
+ * @access public
968
+ * @deprecated
969
+ */
970
+ function usleepWindows($usec)
971
+ {
972
+ $start = gettimeofday();
973
+
974
+ do
975
+ {
976
+ $stop = gettimeofday();
977
+ $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
978
+ + $stop['usec'] - $start['usec'];
979
+ }
980
+ while ($timePassed < $usec);
981
+ }
982
+
983
+ ?><?php
984
+
985
+
986
+
987
+ /**
988
+ * Contains information for a SOAP fault.
989
+ * Mainly used for returning faults from deployed functions
990
+ * in a server instance.
991
+ * @author Dietrich Ayala <dietrich@ganx4.com>
992
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
993
+ * @access public
994
+ */
995
+ class nusoap_fault extends nusoap_base {
996
+ /**
997
+ * The fault code (client|server)
998
+ * @var string
999
+ * @access private
1000
+ */
1001
+ var $faultcode;
1002
+ /**
1003
+ * The fault actor
1004
+ * @var string
1005
+ * @access private
1006
+ */
1007
+ var $faultactor;
1008
+ /**
1009
+ * The fault string, a description of the fault
1010
+ * @var string
1011
+ * @access private
1012
+ */
1013
+ var $faultstring;
1014
+ /**
1015
+ * The fault detail, typically a string or array of string
1016
+ * @var mixed
1017
+ * @access private
1018
+ */
1019
+ var $faultdetail;
1020
+
1021
+ /**
1022
+ * constructor
1023
+ *
1024
+ * @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
1025
+ * @param string $faultactor only used when msg routed between multiple actors
1026
+ * @param string $faultstring human readable error message
1027
+ * @param mixed $faultdetail detail, typically a string or array of string
1028
+ */
1029
+ function nusoap_fault($faultcode,$faultactor='',$faultstring='',$faultdetail=''){
1030
+ parent::nusoap_base();
1031
+ $this->faultcode = $faultcode;
1032
+ $this->faultactor = $faultactor;
1033
+ $this->faultstring = $faultstring;
1034
+ $this->faultdetail = $faultdetail;
1035
+ }
1036
+
1037
+ /**
1038
+ * serialize a fault
1039
+ *
1040
+ * @return string The serialization of the fault instance.
1041
+ * @access public
1042
+ */
1043
+ function serialize(){
1044
+ $ns_string = '';
1045
+ foreach($this->namespaces as $k => $v){
1046
+ $ns_string .= "\n xmlns:$k=\"$v\"";
1047
+ }
1048
+ $return_msg =
1049
+ '<?xml version="1.0" encoding="'.$this->soap_defencoding.'"?>'.
1050
+ '<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"'.$ns_string.">\n".
1051
+ '<SOAP-ENV:Body>'.
1052
+ '<SOAP-ENV:Fault>'.
1053
+ $this->serialize_val($this->faultcode, 'faultcode').
1054
+ $this->serialize_val($this->faultactor, 'faultactor').
1055
+ $this->serialize_val($this->faultstring, 'faultstring').
1056
+ $this->serialize_val($this->faultdetail, 'detail').
1057
+ '</SOAP-ENV:Fault>'.
1058
+ '</SOAP-ENV:Body>'.
1059
+ '</SOAP-ENV:Envelope>';
1060
+ return $return_msg;
1061
+ }
1062
+ }
1063
+
1064
+ /**
1065
+ * Backward compatibility
1066
+ */
1067
+ class soap_fault extends nusoap_fault {
1068
+ }
1069
+
1070
+ ?><?php
1071
+
1072
+
1073
+
1074
+ /**
1075
+ * parses an XML Schema, allows access to it's data, other utility methods.
1076
+ * imperfect, no validation... yet, but quite functional.
1077
+ *
1078
+ * @author Dietrich Ayala <dietrich@ganx4.com>
1079
+ * @author Scott Nichol <snichol@users.sourceforge.net>
1080
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
1081
+ * @access public
1082
+ */
1083
+ class nusoap_xmlschema extends nusoap_base {
1084
+
1085
+ // files
1086
+ var $schema = '';
1087
+ var $xml = '';
1088
+ // namespaces
1089
+ var $enclosingNamespaces;
1090
+ // schema info
1091
+ var $schemaInfo = array();
1092
+ var $schemaTargetNamespace = '';
1093
+ // types, elements, attributes defined by the schema
1094
+ var $attributes = array();
1095
+ var $complexTypes = array();
1096
+ var $complexTypeStack = array();
1097
+ var $currentComplexType = null;
1098
+ var $elements = array();
1099
+ var $elementStack = array();
1100
+ var $currentElement = null;
1101
+ var $simpleTypes = array();
1102
+ var $simpleTypeStack = array();
1103
+ var $currentSimpleType = null;
1104
+ // imports
1105
+ var $imports = array();
1106
+ // parser vars
1107
+ var $parser;
1108
+ var $position = 0;
1109
+ var $depth = 0;
1110
+ var $depth_array = array();
1111
+ var $message = array();
1112
+ var $defaultNamespace = array();
1113
+
1114
+ /**
1115
+ * constructor
1116
+ *
1117
+ * @param string $schema schema document URI
1118
+ * @param string $xml xml document URI
1119
+ * @param string $namespaces namespaces defined in enclosing XML
1120
+ * @access public
1121
+ */
1122
+ function nusoap_xmlschema($schema='',$xml='',$namespaces=array()){
1123
+ parent::nusoap_base();
1124
+ $this->debug('nusoap_xmlschema class instantiated, inside constructor');
1125
+ // files
1126
+ $this->schema = $schema;
1127
+ $this->xml = $xml;
1128
+
1129
+ // namespaces
1130
+ $this->enclosingNamespaces = $namespaces;
1131
+ $this->namespaces = array_merge($this->namespaces, $namespaces);
1132
+
1133
+ // parse schema file
1134
+ if($schema != ''){
1135
+ $this->debug('initial schema file: '.$schema);
1136
+ $this->parseFile($schema, 'schema');
1137
+ }
1138
+
1139
+ // parse xml file
1140
+ if($xml != ''){
1141
+ $this->debug('initial xml file: '.$xml);
1142
+ $this->parseFile($xml, 'xml');
1143
+ }
1144
+
1145
+ }
1146
+
1147
+ /**
1148
+ * parse an XML file
1149
+ *
1150
+ * @param string $xml path/URL to XML file
1151
+ * @param string $type (schema | xml)
1152
+ * @return boolean
1153
+ * @access public
1154
+ */
1155
+ function parseFile($xml,$type){
1156
+ // parse xml file
1157
+ if($xml != ""){
1158
+ $xmlStr = @join("",@file($xml));
1159
+ if($xmlStr == ""){
1160
+ $msg = 'Error reading XML from '.$xml;
1161
+ $this->setError($msg);
1162
+ $this->debug($msg);
1163
+ return false;
1164
+ } else {
1165
+ $this->debug("parsing $xml");
1166
+ $this->parseString($xmlStr,$type);
1167
+ $this->debug("done parsing $xml");
1168
+ return true;
1169
+ }
1170
+ }
1171
+ return false;
1172
+ }
1173
+
1174
+ /**
1175
+ * parse an XML string
1176
+ *
1177
+ * @param string $xml path or URL
1178
+ * @param string $type (schema|xml)
1179
+ * @access private
1180
+ */
1181
+ function parseString($xml,$type){
1182
+ // parse xml string
1183
+ if($xml != ""){
1184
+
1185
+ // Create an XML parser.
1186
+ $this->parser = xml_parser_create();
1187
+ // Set the options for parsing the XML data.
1188
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
1189
+
1190
+ // Set the object for the parser.
1191
+ xml_set_object($this->parser, $this);
1192
+
1193
+ // Set the element handlers for the parser.
1194
+ if($type == "schema"){
1195
+ xml_set_element_handler($this->parser, 'schemaStartElement','schemaEndElement');
1196
+ xml_set_character_data_handler($this->parser,'schemaCharacterData');
1197
+ } elseif($type == "xml"){
1198
+ xml_set_element_handler($this->parser, 'xmlStartElement','xmlEndElement');
1199
+ xml_set_character_data_handler($this->parser,'xmlCharacterData');
1200
+ }
1201
+
1202
+ // Parse the XML file.
1203
+ if(!xml_parse($this->parser,$xml,true)){
1204
+ // Display an error message.
1205
+ $errstr = sprintf('XML error parsing XML schema on line %d: %s',
1206
+ xml_get_current_line_number($this->parser),
1207
+ xml_error_string(xml_get_error_code($this->parser))
1208
+ );
1209
+ $this->debug($errstr);
1210
+ $this->debug("XML payload:\n" . $xml);
1211
+ $this->setError($errstr);
1212
+ }
1213
+
1214
+ xml_parser_free($this->parser);
1215
+ } else{
1216
+ $this->debug('no xml passed to parseString()!!');
1217
+ $this->setError('no xml passed to parseString()!!');
1218
+ }
1219
+ }
1220
+
1221
+ /**
1222
+ * gets a type name for an unnamed type
1223
+ *
1224
+ * @param string Element name
1225
+ * @return string A type name for an unnamed type
1226
+ * @access private
1227
+ */
1228
+ function CreateTypeName($ename) {
1229
+ $scope = '';
1230
+ for ($i = 0; $i < count($this->complexTypeStack); $i++) {
1231
+ $scope .= $this->complexTypeStack[$i] . '_';
1232
+ }
1233
+ return $scope . $ename . '_ContainedType';
1234
+ }
1235
+
1236
+ /**
1237
+ * start-element handler
1238
+ *
1239
+ * @param string $parser XML parser object
1240
+ * @param string $name element name
1241
+ * @param string $attrs associative array of attributes
1242
+ * @access private
1243
+ */
1244
+ function schemaStartElement($parser, $name, $attrs) {
1245
+
1246
+ // position in the total number of elements, starting from 0
1247
+ $pos = $this->position++;
1248
+ $depth = $this->depth++;
1249
+ // set self as current value for this depth
1250
+ $this->depth_array[$depth] = $pos;
1251
+ $this->message[$pos] = array('cdata' => '');
1252
+ if ($depth > 0) {
1253
+ $this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
1254
+ } else {
1255
+ $this->defaultNamespace[$pos] = false;
1256
+ }
1257
+
1258
+ // get element prefix
1259
+ if($prefix = $this->getPrefix($name)){
1260
+ // get unqualified name
1261
+ $name = $this->getLocalPart($name);
1262
+ } else {
1263
+ $prefix = '';
1264
+ }
1265
+
1266
+ // loop thru attributes, expanding, and registering namespace declarations
1267
+ if(count($attrs) > 0){
1268
+ foreach($attrs as $k => $v){
1269
+ // if ns declarations, add to class level array of valid namespaces
1270
+ if(ereg("^xmlns",$k)){
1271
+ //$this->xdebug("$k: $v");
1272
+ //$this->xdebug('ns_prefix: '.$this->getPrefix($k));
1273
+ if($ns_prefix = substr(strrchr($k,':'),1)){
1274
+ //$this->xdebug("Add namespace[$ns_prefix] = $v");
1275
+ $this->namespaces[$ns_prefix] = $v;
1276
+ } else {
1277
+ $this->defaultNamespace[$pos] = $v;
1278
+ if (! $this->getPrefixFromNamespace($v)) {
1279
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $v;
1280
+ }
1281
+ }
1282
+ if($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema'){
1283
+ $this->XMLSchemaVersion = $v;
1284
+ $this->namespaces['xsi'] = $v.'-instance';
1285
+ }
1286
+ }
1287
+ }
1288
+ foreach($attrs as $k => $v){
1289
+ // expand each attribute
1290
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
1291
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
1292
+ $eAttrs[$k] = $v;
1293
+ }
1294
+ $attrs = $eAttrs;
1295
+ } else {
1296
+ $attrs = array();
1297
+ }
1298
+ // find status, register data
1299
+ switch($name){
1300
+ case 'all': // (optional) compositor content for a complexType
1301
+ case 'choice':
1302
+ case 'group':
1303
+ case 'sequence':
1304
+ //$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
1305
+ $this->complexTypes[$this->currentComplexType]['compositor'] = $name;
1306
+ //if($name == 'all' || $name == 'sequence'){
1307
+ // $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1308
+ //}
1309
+ break;
1310
+ case 'attribute': // complexType attribute
1311
+ //$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
1312
+ $this->xdebug("parsing attribute:");
1313
+ $this->appendDebug($this->varDump($attrs));
1314
+ if (!isset($attrs['form'])) {
1315
+ $attrs['form'] = $this->schemaInfo['attributeFormDefault'];
1316
+ }
1317
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1318
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1319
+ if (!strpos($v, ':')) {
1320
+ // no namespace in arrayType attribute value...
1321
+ if ($this->defaultNamespace[$pos]) {
1322
+ // ...so use the default
1323
+ $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1324
+ }
1325
+ }
1326
+ }
1327
+ if(isset($attrs['name'])){
1328
+ $this->attributes[$attrs['name']] = $attrs;
1329
+ $aname = $attrs['name'];
1330
+ } elseif(isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType'){
1331
+ if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
1332
+ $aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1333
+ } else {
1334
+ $aname = '';
1335
+ }
1336
+ } elseif(isset($attrs['ref'])){
1337
+ $aname = $attrs['ref'];
1338
+ $this->attributes[$attrs['ref']] = $attrs;
1339
+ }
1340
+
1341
+ if($this->currentComplexType){ // This should *always* be
1342
+ $this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
1343
+ }
1344
+ // arrayType attribute
1345
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType'){
1346
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1347
+ $prefix = $this->getPrefix($aname);
1348
+ if(isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])){
1349
+ $v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
1350
+ } else {
1351
+ $v = '';
1352
+ }
1353
+ if(strpos($v,'[,]')){
1354
+ $this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
1355
+ }
1356
+ $v = substr($v,0,strpos($v,'[')); // clip the []
1357
+ if(!strpos($v,':') && isset($this->typemap[$this->XMLSchemaVersion][$v])){
1358
+ $v = $this->XMLSchemaVersion.':'.$v;
1359
+ }
1360
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
1361
+ }
1362
+ break;
1363
+ case 'complexContent': // (optional) content for a complexType
1364
+ break;
1365
+ case 'complexType':
1366
+ array_push($this->complexTypeStack, $this->currentComplexType);
1367
+ if(isset($attrs['name'])){
1368
+ // TODO: what is the scope of named complexTypes that appear
1369
+ // nested within other c complexTypes?
1370
+ $this->xdebug('processing named complexType '.$attrs['name']);
1371
+ //$this->currentElement = false;
1372
+ $this->currentComplexType = $attrs['name'];
1373
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1374
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1375
+ // This is for constructs like
1376
+ // <complexType name="ListOfString" base="soap:Array">
1377
+ // <sequence>
1378
+ // <element name="string" type="xsd:string"
1379
+ // minOccurs="0" maxOccurs="unbounded" />
1380
+ // </sequence>
1381
+ // </complexType>
1382
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1383
+ $this->xdebug('complexType is unusual array');
1384
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1385
+ } else {
1386
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1387
+ }
1388
+ } else {
1389
+ $name = $this->CreateTypeName($this->currentElement);
1390
+ $this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
1391
+ $this->currentComplexType = $name;
1392
+ //$this->currentElement = false;
1393
+ $this->complexTypes[$this->currentComplexType] = $attrs;
1394
+ $this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
1395
+ // This is for constructs like
1396
+ // <complexType name="ListOfString" base="soap:Array">
1397
+ // <sequence>
1398
+ // <element name="string" type="xsd:string"
1399
+ // minOccurs="0" maxOccurs="unbounded" />
1400
+ // </sequence>
1401
+ // </complexType>
1402
+ if(isset($attrs['base']) && ereg(':Array$',$attrs['base'])){
1403
+ $this->xdebug('complexType is unusual array');
1404
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1405
+ } else {
1406
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
1407
+ }
1408
+ }
1409
+ break;
1410
+ case 'element':
1411
+ array_push($this->elementStack, $this->currentElement);
1412
+ if (!isset($attrs['form'])) {
1413
+ $attrs['form'] = $this->schemaInfo['elementFormDefault'];
1414
+ }
1415
+ if(isset($attrs['type'])){
1416
+ $this->xdebug("processing typed element ".$attrs['name']." of type ".$attrs['type']);
1417
+ if (! $this->getPrefix($attrs['type'])) {
1418
+ if ($this->defaultNamespace[$pos]) {
1419
+ $attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
1420
+ $this->xdebug('used default namespace to make type ' . $attrs['type']);
1421
+ }
1422
+ }
1423
+ // This is for constructs like
1424
+ // <complexType name="ListOfString" base="soap:Array">
1425
+ // <sequence>
1426
+ // <element name="string" type="xsd:string"
1427
+ // minOccurs="0" maxOccurs="unbounded" />
1428
+ // </sequence>
1429
+ // </complexType>
1430
+ if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
1431
+ $this->xdebug('arrayType for unusual array is ' . $attrs['type']);
1432
+ $this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
1433
+ }
1434
+ $this->currentElement = $attrs['name'];
1435
+ $ename = $attrs['name'];
1436
+ } elseif(isset($attrs['ref'])){
1437
+ $this->xdebug("processing element as ref to ".$attrs['ref']);
1438
+ $this->currentElement = "ref to ".$attrs['ref'];
1439
+ $ename = $this->getLocalPart($attrs['ref']);
1440
+ } else {
1441
+ $type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
1442
+ $this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
1443
+ $this->currentElement = $attrs['name'];
1444
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
1445
+ $ename = $attrs['name'];
1446
+ }
1447
+ if (isset($ename) && $this->currentComplexType) {
1448
+ $this->xdebug("add element $ename to complexType $this->currentComplexType");
1449
+ $this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
1450
+ } elseif (!isset($attrs['ref'])) {
1451
+ $this->xdebug("add element $ename to elements array");
1452
+ $this->elements[ $attrs['name'] ] = $attrs;
1453
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1454
+ }
1455
+ break;
1456
+ case 'enumeration': // restriction value list member
1457
+ $this->xdebug('enumeration ' . $attrs['value']);
1458
+ if ($this->currentSimpleType) {
1459
+ $this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
1460
+ } elseif ($this->currentComplexType) {
1461
+ $this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
1462
+ }
1463
+ break;
1464
+ case 'extension': // simpleContent or complexContent type extension
1465
+ $this->xdebug('extension ' . $attrs['base']);
1466
+ if ($this->currentComplexType) {
1467
+ $this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
1468
+ }
1469
+ break;
1470
+ case 'import':
1471
+ if (isset($attrs['schemaLocation'])) {
1472
+ //$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
1473
+ $this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
1474
+ } else {
1475
+ //$this->xdebug('import namespace ' . $attrs['namespace']);
1476
+ $this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
1477
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
1478
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
1479
+ }
1480
+ }
1481
+ break;
1482
+ case 'list': // simpleType value list
1483
+ break;
1484
+ case 'restriction': // simpleType, simpleContent or complexContent value restriction
1485
+ $this->xdebug('restriction ' . $attrs['base']);
1486
+ if($this->currentSimpleType){
1487
+ $this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
1488
+ } elseif($this->currentComplexType){
1489
+ $this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
1490
+ if(strstr($attrs['base'],':') == ':Array'){
1491
+ $this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
1492
+ }
1493
+ }
1494
+ break;
1495
+ case 'schema':
1496
+ $this->schemaInfo = $attrs;
1497
+ $this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
1498
+ if (isset($attrs['targetNamespace'])) {
1499
+ $this->schemaTargetNamespace = $attrs['targetNamespace'];
1500
+ }
1501
+ if (!isset($attrs['elementFormDefault'])) {
1502
+ $this->schemaInfo['elementFormDefault'] = 'unqualified';
1503
+ }
1504
+ if (!isset($attrs['attributeFormDefault'])) {
1505
+ $this->schemaInfo['attributeFormDefault'] = 'unqualified';
1506
+ }
1507
+ break;
1508
+ case 'simpleContent': // (optional) content for a complexType
1509
+ break;
1510
+ case 'simpleType':
1511
+ array_push($this->simpleTypeStack, $this->currentSimpleType);
1512
+ if(isset($attrs['name'])){
1513
+ $this->xdebug("processing simpleType for name " . $attrs['name']);
1514
+ $this->currentSimpleType = $attrs['name'];
1515
+ $this->simpleTypes[ $attrs['name'] ] = $attrs;
1516
+ $this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
1517
+ $this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
1518
+ } else {
1519
+ $name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
1520
+ $this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
1521
+ $this->currentSimpleType = $name;
1522
+ //$this->currentElement = false;
1523
+ $this->simpleTypes[$this->currentSimpleType] = $attrs;
1524
+ $this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
1525
+ }
1526
+ break;
1527
+ case 'union': // simpleType type list
1528
+ break;
1529
+ default:
1530
+ //$this->xdebug("do not have anything to do for element $name");
1531
+ }
1532
+ }
1533
+
1534
+ /**
1535
+ * end-element handler
1536
+ *
1537
+ * @param string $parser XML parser object
1538
+ * @param string $name element name
1539
+ * @access private
1540
+ */
1541
+ function schemaEndElement($parser, $name) {
1542
+ // bring depth down a notch
1543
+ $this->depth--;
1544
+ // position of current element is equal to the last value left in depth_array for my depth
1545
+ if(isset($this->depth_array[$this->depth])){
1546
+ $pos = $this->depth_array[$this->depth];
1547
+ }
1548
+ // get element prefix
1549
+ if ($prefix = $this->getPrefix($name)){
1550
+ // get unqualified name
1551
+ $name = $this->getLocalPart($name);
1552
+ } else {
1553
+ $prefix = '';
1554
+ }
1555
+ // move on...
1556
+ if($name == 'complexType'){
1557
+ $this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
1558
+ $this->currentComplexType = array_pop($this->complexTypeStack);
1559
+ //$this->currentElement = false;
1560
+ }
1561
+ if($name == 'element'){
1562
+ $this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
1563
+ $this->currentElement = array_pop($this->elementStack);
1564
+ }
1565
+ if($name == 'simpleType'){
1566
+ $this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
1567
+ $this->currentSimpleType = array_pop($this->simpleTypeStack);
1568
+ }
1569
+ }
1570
+
1571
+ /**
1572
+ * element content handler
1573
+ *
1574
+ * @param string $parser XML parser object
1575
+ * @param string $data element content
1576
+ * @access private
1577
+ */
1578
+ function schemaCharacterData($parser, $data){
1579
+ $pos = $this->depth_array[$this->depth - 1];
1580
+ $this->message[$pos]['cdata'] .= $data;
1581
+ }
1582
+
1583
+ /**
1584
+ * serialize the schema
1585
+ *
1586
+ * @access public
1587
+ */
1588
+ function serializeSchema(){
1589
+
1590
+ $schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
1591
+ $xml = '';
1592
+ // imports
1593
+ if (sizeof($this->imports) > 0) {
1594
+ foreach($this->imports as $ns => $list) {
1595
+ foreach ($list as $ii) {
1596
+ if ($ii['location'] != '') {
1597
+ $xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
1598
+ } else {
1599
+ $xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
1600
+ }
1601
+ }
1602
+ }
1603
+ }
1604
+ // complex types
1605
+ foreach($this->complexTypes as $typeName => $attrs){
1606
+ $contentStr = '';
1607
+ // serialize child elements
1608
+ if(isset($attrs['elements']) && (count($attrs['elements']) > 0)){
1609
+ foreach($attrs['elements'] as $element => $eParts){
1610
+ if(isset($eParts['ref'])){
1611
+ $contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
1612
+ } else {
1613
+ $contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
1614
+ foreach ($eParts as $aName => $aValue) {
1615
+ // handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
1616
+ if ($aName != 'name' && $aName != 'type') {
1617
+ $contentStr .= " $aName=\"$aValue\"";
1618
+ }
1619
+ }
1620
+ $contentStr .= "/>\n";
1621
+ }
1622
+ }
1623
+ // compositor wraps elements
1624
+ if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
1625
+ $contentStr = " <$schemaPrefix:$attrs[compositor]>\n".$contentStr." </$schemaPrefix:$attrs[compositor]>\n";
1626
+ }
1627
+ }
1628
+ // attributes
1629
+ if(isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)){
1630
+ foreach($attrs['attrs'] as $attr => $aParts){
1631
+ $contentStr .= " <$schemaPrefix:attribute";
1632
+ foreach ($aParts as $a => $v) {
1633
+ if ($a == 'ref' || $a == 'type') {
1634
+ $contentStr .= " $a=\"".$this->contractQName($v).'"';
1635
+ } elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
1636
+ $this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
1637
+ $contentStr .= ' wsdl:arrayType="'.$this->contractQName($v).'"';
1638
+ } else {
1639
+ $contentStr .= " $a=\"$v\"";
1640
+ }
1641
+ }
1642
+ $contentStr .= "/>\n";
1643
+ }
1644
+ }
1645
+ // if restriction
1646
+ if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != ''){
1647
+ $contentStr = " <$schemaPrefix:restriction base=\"".$this->contractQName($attrs['restrictionBase'])."\">\n".$contentStr." </$schemaPrefix:restriction>\n";
1648
+ // complex or simple content
1649
+ if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)){
1650
+ $contentStr = " <$schemaPrefix:complexContent>\n".$contentStr." </$schemaPrefix:complexContent>\n";
1651
+ }
1652
+ }
1653
+ // finalize complex type
1654
+ if($contentStr != ''){
1655
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n".$contentStr." </$schemaPrefix:complexType>\n";
1656
+ } else {
1657
+ $contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
1658
+ }
1659
+ $xml .= $contentStr;
1660
+ }
1661
+ // simple types
1662
+ if(isset($this->simpleTypes) && count($this->simpleTypes) > 0){
1663
+ foreach($this->simpleTypes as $typeName => $eParts){
1664
+ $xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"".$this->contractQName($eParts['type'])."\">\n";
1665
+ if (isset($eParts['enumeration'])) {
1666
+ foreach ($eParts['enumeration'] as $e) {
1667
+ $xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
1668
+ }
1669
+ }
1670
+ $xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
1671
+ }
1672
+ }
1673
+ // elements
1674
+ if(isset($this->elements) && count($this->elements) > 0){
1675
+ foreach($this->elements as $element => $eParts){
1676
+ $xml .= " <$schemaPrefix:element name=\"$element\" type=\"".$this->contractQName($eParts['type'])."\"/>\n";
1677
+ }
1678
+ }
1679
+ // attributes
1680
+ if(isset($this->attributes) && count($this->attributes) > 0){
1681
+ foreach($this->attributes as $attr => $aParts){
1682
+ $xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"".$this->contractQName($aParts['type'])."\"\n/>";
1683
+ }
1684
+ }
1685
+ // finish 'er up
1686
+ $attr = '';
1687
+ foreach ($this->schemaInfo as $k => $v) {
1688
+ if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
1689
+ $attr .= " $k=\"$v\"";
1690
+ }
1691
+ }
1692
+ $el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
1693
+ foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
1694
+ $el .= " xmlns:$nsp=\"$ns\"";
1695
+ }
1696
+ $xml = $el . ">\n".$xml."</$schemaPrefix:schema>\n";
1697
+ return $xml;
1698
+ }
1699
+
1700
+ /**
1701
+ * adds debug data to the clas level debug string
1702
+ *
1703
+ * @param string $string debug data
1704
+ * @access private
1705
+ */
1706
+ function xdebug($string){
1707
+ $this->debug('<' . $this->schemaTargetNamespace . '> '.$string);
1708
+ }
1709
+
1710
+ /**
1711
+ * get the PHP type of a user defined type in the schema
1712
+ * PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
1713
+ * returns false if no type exists, or not w/ the given namespace
1714
+ * else returns a string that is either a native php type, or 'struct'
1715
+ *
1716
+ * @param string $type name of defined type
1717
+ * @param string $ns namespace of type
1718
+ * @return mixed
1719
+ * @access public
1720
+ * @deprecated
1721
+ */
1722
+ function getPHPType($type,$ns){
1723
+ if(isset($this->typemap[$ns][$type])){
1724
+ //print "found type '$type' and ns $ns in typemap<br>";
1725
+ return $this->typemap[$ns][$type];
1726
+ } elseif(isset($this->complexTypes[$type])){
1727
+ //print "getting type '$type' and ns $ns from complexTypes array<br>";
1728
+ return $this->complexTypes[$type]['phpType'];
1729
+ }
1730
+ return false;
1731
+ }
1732
+
1733
+ /**
1734
+ * returns an associative array of information about a given type
1735
+ * returns false if no type exists by the given name
1736
+ *
1737
+ * For a complexType typeDef = array(
1738
+ * 'restrictionBase' => '',
1739
+ * 'phpType' => '',
1740
+ * 'compositor' => '(sequence|all)',
1741
+ * 'elements' => array(), // refs to elements array
1742
+ * 'attrs' => array() // refs to attributes array
1743
+ * ... and so on (see addComplexType)
1744
+ * )
1745
+ *
1746
+ * For simpleType or element, the array has different keys.
1747
+ *
1748
+ * @param string $type
1749
+ * @return mixed
1750
+ * @access public
1751
+ * @see addComplexType
1752
+ * @see addSimpleType
1753
+ * @see addElement
1754
+ */
1755
+ function getTypeDef($type){
1756
+ //$this->debug("in getTypeDef for type $type");
1757
+ if (substr($type, -1) == '^') {
1758
+ $is_element = 1;
1759
+ $type = substr($type, 0, -1);
1760
+ } else {
1761
+ $is_element = 0;
1762
+ }
1763
+
1764
+ if((! $is_element) && isset($this->complexTypes[$type])){
1765
+ $this->xdebug("in getTypeDef, found complexType $type");
1766
+ return $this->complexTypes[$type];
1767
+ } elseif((! $is_element) && isset($this->simpleTypes[$type])){
1768
+ $this->xdebug("in getTypeDef, found simpleType $type");
1769
+ if (!isset($this->simpleTypes[$type]['phpType'])) {
1770
+ // get info for type to tack onto the simple type
1771
+ // TODO: can this ever really apply (i.e. what is a simpleType really?)
1772
+ $uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
1773
+ $ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
1774
+ $etype = $this->getTypeDef($uqType);
1775
+ if ($etype) {
1776
+ $this->xdebug("in getTypeDef, found type for simpleType $type:");
1777
+ $this->xdebug($this->varDump($etype));
1778
+ if (isset($etype['phpType'])) {
1779
+ $this->simpleTypes[$type]['phpType'] = $etype['phpType'];
1780
+ }
1781
+ if (isset($etype['elements'])) {
1782
+ $this->simpleTypes[$type]['elements'] = $etype['elements'];
1783
+ }
1784
+ }
1785
+ }
1786
+ return $this->simpleTypes[$type];
1787
+ } elseif(isset($this->elements[$type])){
1788
+ $this->xdebug("in getTypeDef, found element $type");
1789
+ if (!isset($this->elements[$type]['phpType'])) {
1790
+ // get info for type to tack onto the element
1791
+ $uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
1792
+ $ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
1793
+ $etype = $this->getTypeDef($uqType);
1794
+ if ($etype) {
1795
+ $this->xdebug("in getTypeDef, found type for element $type:");
1796
+ $this->xdebug($this->varDump($etype));
1797
+ if (isset($etype['phpType'])) {
1798
+ $this->elements[$type]['phpType'] = $etype['phpType'];
1799
+ }
1800
+ if (isset($etype['elements'])) {
1801
+ $this->elements[$type]['elements'] = $etype['elements'];
1802
+ }
1803
+ } elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
1804
+ $this->xdebug("in getTypeDef, element $type is an XSD type");
1805
+ $this->elements[$type]['phpType'] = 'scalar';
1806
+ }
1807
+ }
1808
+ return $this->elements[$type];
1809
+ } elseif(isset($this->attributes[$type])){
1810
+ $this->xdebug("in getTypeDef, found attribute $type");
1811
+ return $this->attributes[$type];
1812
+ } elseif (ereg('_ContainedType$', $type)) {
1813
+ $this->xdebug("in getTypeDef, have an untyped element $type");
1814
+ $typeDef['typeClass'] = 'simpleType';
1815
+ $typeDef['phpType'] = 'scalar';
1816
+ $typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
1817
+ return $typeDef;
1818
+ }
1819
+ $this->xdebug("in getTypeDef, did not find $type");
1820
+ return false;
1821
+ }
1822
+
1823
+ /**
1824
+ * returns a sample serialization of a given type, or false if no type by the given name
1825
+ *
1826
+ * @param string $type name of type
1827
+ * @return mixed
1828
+ * @access public
1829
+ * @deprecated
1830
+ */
1831
+ function serializeTypeDef($type){
1832
+ //print "in sTD() for type $type<br>";
1833
+ if($typeDef = $this->getTypeDef($type)){
1834
+ $str .= '<'.$type;
1835
+ if(is_array($typeDef['attrs'])){
1836
+ foreach($typeDef['attrs'] as $attName => $data){
1837
+ $str .= " $attName=\"{type = ".$data['type']."}\"";
1838
+ }
1839
+ }
1840
+ $str .= " xmlns=\"".$this->schema['targetNamespace']."\"";
1841
+ if(count($typeDef['elements']) > 0){
1842
+ $str .= ">";
1843
+ foreach($typeDef['elements'] as $element => $eData){
1844
+ $str .= $this->serializeTypeDef($element);
1845
+ }
1846
+ $str .= "</$type>";
1847
+ } elseif($typeDef['typeClass'] == 'element') {
1848
+ $str .= "></$type>";
1849
+ } else {
1850
+ $str .= "/>";
1851
+ }
1852
+ return $str;
1853
+ }
1854
+ return false;
1855
+ }
1856
+
1857
+ /**
1858
+ * returns HTML form elements that allow a user
1859
+ * to enter values for creating an instance of the given type.
1860
+ *
1861
+ * @param string $name name for type instance
1862
+ * @param string $type name of type
1863
+ * @return string
1864
+ * @access public
1865
+ * @deprecated
1866
+ */
1867
+ function typeToForm($name,$type){
1868
+ // get typedef
1869
+ if($typeDef = $this->getTypeDef($type)){
1870
+ // if struct
1871
+ if($typeDef['phpType'] == 'struct'){
1872
+ $buffer .= '<table>';
1873
+ foreach($typeDef['elements'] as $child => $childDef){
1874
+ $buffer .= "
1875
+ <tr><td align='right'>$childDef[name] (type: ".$this->getLocalPart($childDef['type'])."):</td>
1876
+ <td><input type='text' name='parameters[".$name."][$childDef[name]]'></td></tr>";
1877
+ }
1878
+ $buffer .= '</table>';
1879
+ // if array
1880
+ } elseif($typeDef['phpType'] == 'array'){
1881
+ $buffer .= '<table>';
1882
+ for($i=0;$i < 3; $i++){
1883
+ $buffer .= "
1884
+ <tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
1885
+ <td><input type='text' name='parameters[".$name."][]'></td></tr>";
1886
+ }
1887
+ $buffer .= '</table>';
1888
+ // if scalar
1889
+ } else {
1890
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1891
+ }
1892
+ } else {
1893
+ $buffer .= "<input type='text' name='parameters[$name]'>";
1894
+ }
1895
+ return $buffer;
1896
+ }
1897
+
1898
+ /**
1899
+ * adds a complex type to the schema
1900
+ *
1901
+ * example: array
1902
+ *
1903
+ * addType(
1904
+ * 'ArrayOfstring',
1905
+ * 'complexType',
1906
+ * 'array',
1907
+ * '',
1908
+ * 'SOAP-ENC:Array',
1909
+ * array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
1910
+ * 'xsd:string'
1911
+ * );
1912
+ *
1913
+ * example: PHP associative array ( SOAP Struct )
1914
+ *
1915
+ * addType(
1916
+ * 'SOAPStruct',
1917
+ * 'complexType',
1918
+ * 'struct',
1919
+ * 'all',
1920
+ * array('myVar'=> array('name'=>'myVar','type'=>'string')
1921
+ * );
1922
+ *
1923
+ * @param name
1924
+ * @param typeClass (complexType|simpleType|attribute)
1925
+ * @param phpType: currently supported are array and struct (php assoc array)
1926
+ * @param compositor (all|sequence|choice)
1927
+ * @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1928
+ * @param elements = array ( name = array(name=>'',type=>'') )
1929
+ * @param attrs = array(
1930
+ * array(
1931
+ * 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
1932
+ * "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
1933
+ * )
1934
+ * )
1935
+ * @param arrayType: namespace:name (http://www.w3.org/2001/XMLSchema:string)
1936
+ * @access public
1937
+ * @see getTypeDef
1938
+ */
1939
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType=''){
1940
+ $this->complexTypes[$name] = array(
1941
+ 'name' => $name,
1942
+ 'typeClass' => $typeClass,
1943
+ 'phpType' => $phpType,
1944
+ 'compositor'=> $compositor,
1945
+ 'restrictionBase' => $restrictionBase,
1946
+ 'elements' => $elements,
1947
+ 'attrs' => $attrs,
1948
+ 'arrayType' => $arrayType
1949
+ );
1950
+
1951
+ $this->xdebug("addComplexType $name:");
1952
+ $this->appendDebug($this->varDump($this->complexTypes[$name]));
1953
+ }
1954
+
1955
+ /**
1956
+ * adds a simple type to the schema
1957
+ *
1958
+ * @param string $name
1959
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
1960
+ * @param string $typeClass (should always be simpleType)
1961
+ * @param string $phpType (should always be scalar)
1962
+ * @param array $enumeration array of values
1963
+ * @access public
1964
+ * @see nusoap_xmlschema
1965
+ * @see getTypeDef
1966
+ */
1967
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
1968
+ $this->simpleTypes[$name] = array(
1969
+ 'name' => $name,
1970
+ 'typeClass' => $typeClass,
1971
+ 'phpType' => $phpType,
1972
+ 'type' => $restrictionBase,
1973
+ 'enumeration' => $enumeration
1974
+ );
1975
+
1976
+ $this->xdebug("addSimpleType $name:");
1977
+ $this->appendDebug($this->varDump($this->simpleTypes[$name]));
1978
+ }
1979
+
1980
+ /**
1981
+ * adds an element to the schema
1982
+ *
1983
+ * @param array $attrs attributes that must include name and type
1984
+ * @see nusoap_xmlschema
1985
+ * @access public
1986
+ */
1987
+ function addElement($attrs) {
1988
+ if (! $this->getPrefix($attrs['type'])) {
1989
+ $attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
1990
+ }
1991
+ $this->elements[ $attrs['name'] ] = $attrs;
1992
+ $this->elements[ $attrs['name'] ]['typeClass'] = 'element';
1993
+
1994
+ $this->xdebug("addElement " . $attrs['name']);
1995
+ $this->appendDebug($this->varDump($this->elements[ $attrs['name'] ]));
1996
+ }
1997
+ }
1998
+
1999
+ /**
2000
+ * Backward compatibility
2001
+ */
2002
+ class XMLSchema extends nusoap_xmlschema {
2003
+ }
2004
+
2005
+ ?><?php
2006
+
2007
+
2008
+
2009
+ /**
2010
+ * For creating serializable abstractions of native PHP types. This class
2011
+ * allows element name/namespace, XSD type, and XML attributes to be
2012
+ * associated with a value. This is extremely useful when WSDL is not
2013
+ * used, but is also useful when WSDL is used with polymorphic types, including
2014
+ * xsd:anyType and user-defined types.
2015
+ *
2016
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2017
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
2018
+ * @access public
2019
+ */
2020
+ class soapval extends nusoap_base {
2021
+ /**
2022
+ * The XML element name
2023
+ *
2024
+ * @var string
2025
+ * @access private
2026
+ */
2027
+ var $name;
2028
+ /**
2029
+ * The XML type name (string or false)
2030
+ *
2031
+ * @var mixed
2032
+ * @access private
2033
+ */
2034
+ var $type;
2035
+ /**
2036
+ * The PHP value
2037
+ *
2038
+ * @var mixed
2039
+ * @access private
2040
+ */
2041
+ var $value;
2042
+ /**
2043
+ * The XML element namespace (string or false)
2044
+ *
2045
+ * @var mixed
2046
+ * @access private
2047
+ */
2048
+ var $element_ns;
2049
+ /**
2050
+ * The XML type namespace (string or false)
2051
+ *
2052
+ * @var mixed
2053
+ * @access private
2054
+ */
2055
+ var $type_ns;
2056
+ /**
2057
+ * The XML element attributes (array or false)
2058
+ *
2059
+ * @var mixed
2060
+ * @access private
2061
+ */
2062
+ var $attributes;
2063
+
2064
+ /**
2065
+ * constructor
2066
+ *
2067
+ * @param string $name optional name
2068
+ * @param mixed $type optional type name
2069
+ * @param mixed $value optional value
2070
+ * @param mixed $element_ns optional namespace of value
2071
+ * @param mixed $type_ns optional namespace of type
2072
+ * @param mixed $attributes associative array of attributes to add to element serialization
2073
+ * @access public
2074
+ */
2075
+ function soapval($name='soapval',$type=false,$value=-1,$element_ns=false,$type_ns=false,$attributes=false) {
2076
+ parent::nusoap_base();
2077
+ $this->name = $name;
2078
+ $this->type = $type;
2079
+ $this->value = $value;
2080
+ $this->element_ns = $element_ns;
2081
+ $this->type_ns = $type_ns;
2082
+ $this->attributes = $attributes;
2083
+ }
2084
+
2085
+ /**
2086
+ * return serialized value
2087
+ *
2088
+ * @param string $use The WSDL use value (encoded|literal)
2089
+ * @return string XML data
2090
+ * @access public
2091
+ */
2092
+ function serialize($use='encoded') {
2093
+ return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
2094
+ }
2095
+
2096
+ /**
2097
+ * decodes a soapval object into a PHP native type
2098
+ *
2099
+ * @return mixed
2100
+ * @access public
2101
+ */
2102
+ function decode(){
2103
+ return $this->value;
2104
+ }
2105
+ }
2106
+
2107
+
2108
+
2109
+ ?><?php
2110
+
2111
+
2112
+
2113
+ /**
2114
+ * transport class for sending/receiving data via HTTP and HTTPS
2115
+ * NOTE: PHP must be compiled with the CURL extension for HTTPS support
2116
+ *
2117
+ * @author Dietrich Ayala <dietrich@ganx4.com>
2118
+ * @author Scott Nichol <snichol@users.sourceforge.net>
2119
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
2120
+ * @access public
2121
+ */
2122
+ class soap_transport_http extends nusoap_base {
2123
+
2124
+ var $url = '';
2125
+ var $uri = '';
2126
+ var $digest_uri = '';
2127
+ var $scheme = '';
2128
+ var $host = '';
2129
+ var $port = '';
2130
+ var $path = '';
2131
+ var $request_method = 'POST';
2132
+ var $protocol_version = '1.0';
2133
+ var $encoding = '';
2134
+ var $outgoing_headers = array();
2135
+ var $incoming_headers = array();
2136
+ var $incoming_cookies = array();
2137
+ var $outgoing_payload = '';
2138
+ var $incoming_payload = '';
2139
+ var $response_status_line; // HTTP response status line
2140
+ var $useSOAPAction = true;
2141
+ var $persistentConnection = false;
2142
+ var $ch = false; // cURL handle
2143
+ var $ch_options = array(); // cURL custom options
2144
+ var $use_curl = false; // force cURL use
2145
+ var $proxy = null; // proxy information (associative array)
2146
+ var $username = '';
2147
+ var $password = '';
2148
+ var $authtype = '';
2149
+ var $digestRequest = array();
2150
+ var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
2151
+ // cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
2152
+ // sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
2153
+ // sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
2154
+ // passphrase: SSL key password/passphrase
2155
+ // certpassword: SSL certificate password
2156
+ // verifypeer: default is 1
2157
+ // verifyhost: default is 1
2158
+
2159
+ /**
2160
+ * constructor
2161
+ *
2162
+ * @param string $url The URL to which to connect
2163
+ * @param array $curl_options User-specified cURL options
2164
+ * @param boolean $use_curl Whether to try to force cURL use
2165
+ * @access public
2166
+ */
2167
+ function soap_transport_http($url, $curl_options = NULL, $use_curl = false){
2168
+ parent::nusoap_base();
2169
+ $this->debug("ctor url=$url use_curl=$use_curl curl_options:");
2170
+ $this->appendDebug($this->varDump($curl_options));
2171
+ $this->setURL($url);
2172
+ if (is_array($curl_options)) {
2173
+ $this->ch_options = $curl_options;
2174
+ }
2175
+ $this->use_curl = $use_curl;
2176
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
2177
+ $this->setHeader('User-Agent', $this->title.'/'.$this->version.' ('.$rev[1].')');
2178
+ }
2179
+
2180
+ /**
2181
+ * sets a cURL option
2182
+ *
2183
+ * @param mixed $option The cURL option (always integer?)
2184
+ * @param mixed $value The cURL option value
2185
+ * @access private
2186
+ */
2187
+ function setCurlOption($option, $value) {
2188
+ $this->debug("setCurlOption option=$option, value=");
2189
+ $this->appendDebug($this->varDump($value));
2190
+ curl_setopt($this->ch, $option, $value);
2191
+ }
2192
+
2193
+ /**
2194
+ * sets an HTTP header
2195
+ *
2196
+ * @param string $name The name of the header
2197
+ * @param string $value The value of the header
2198
+ * @access private
2199
+ */
2200
+ function setHeader($name, $value) {
2201
+ $this->outgoing_headers[$name] = $value;
2202
+ $this->debug("set header $name: $value");
2203
+ }
2204
+
2205
+ /**
2206
+ * unsets an HTTP header
2207
+ *
2208
+ * @param string $name The name of the header
2209
+ * @access private
2210
+ */
2211
+ function unsetHeader($name) {
2212
+ if (isset($this->outgoing_headers[$name])) {
2213
+ $this->debug("unset header $name");
2214
+ unset($this->outgoing_headers[$name]);
2215
+ }
2216
+ }
2217
+
2218
+ /**
2219
+ * sets the URL to which to connect
2220
+ *
2221
+ * @param string $url The URL to which to connect
2222
+ * @access private
2223
+ */
2224
+ function setURL($url) {
2225
+ $this->url = $url;
2226
+
2227
+ $u = parse_url($url);
2228
+ foreach($u as $k => $v){
2229
+ $this->debug("parsed URL $k = $v");
2230
+ $this->$k = $v;
2231
+ }
2232
+
2233
+ // add any GET params to path
2234
+ if(isset($u['query']) && $u['query'] != ''){
2235
+ $this->path .= '?' . $u['query'];
2236
+ }
2237
+
2238
+ // set default port
2239
+ if(!isset($u['port'])){
2240
+ if($u['scheme'] == 'https'){
2241
+ $this->port = 443;
2242
+ } else {
2243
+ $this->port = 80;
2244
+ }
2245
+ }
2246
+
2247
+ $this->uri = $this->path;
2248
+ $this->digest_uri = $this->uri;
2249
+
2250
+ // build headers
2251
+ if (!isset($u['port'])) {
2252
+ $this->setHeader('Host', $this->host);
2253
+ } else {
2254
+ $this->setHeader('Host', $this->host.':'.$this->port);
2255
+ }
2256
+
2257
+ if (isset($u['user']) && $u['user'] != '') {
2258
+ $this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
2259
+ }
2260
+ }
2261
+
2262
+ /**
2263
+ * gets the I/O method to use
2264
+ *
2265
+ * @return string I/O method to use (socket|curl|unknown)
2266
+ * @access private
2267
+ */
2268
+ function io_method() {
2269
+ if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm'))
2270
+ return 'curl';
2271
+ if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm'))
2272
+ return 'socket';
2273
+ return 'unknown';
2274
+ }
2275
+
2276
+ /**
2277
+ * establish an HTTP connection
2278
+ *
2279
+ * @param integer $timeout set connection timeout in seconds
2280
+ * @param integer $response_timeout set response timeout in seconds
2281
+ * @return boolean true if connected, false if not
2282
+ * @access private
2283
+ */
2284
+ function connect($connection_timeout=0,$response_timeout=30){
2285
+ // For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
2286
+ // "regular" socket.
2287
+ // TODO: disabled for now because OpenSSL must be *compiled* in (not just
2288
+ // loaded), and until PHP5 stream_get_wrappers is not available.
2289
+ // if ($this->scheme == 'https') {
2290
+ // if (version_compare(phpversion(), '4.3.0') >= 0) {
2291
+ // if (extension_loaded('openssl')) {
2292
+ // $this->scheme = 'ssl';
2293
+ // $this->debug('Using SSL over OpenSSL');
2294
+ // }
2295
+ // }
2296
+ // }
2297
+ $this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
2298
+ if ($this->io_method() == 'socket') {
2299
+ if (!is_array($this->proxy)) {
2300
+ $host = $this->host;
2301
+ $port = $this->port;
2302
+ } else {
2303
+ $host = $this->proxy['host'];
2304
+ $port = $this->proxy['port'];
2305
+ }
2306
+
2307
+ // use persistent connection
2308
+ if($this->persistentConnection && isset($this->fp) && is_resource($this->fp)){
2309
+ if (!feof($this->fp)) {
2310
+ $this->debug('Re-use persistent connection');
2311
+ return true;
2312
+ }
2313
+ fclose($this->fp);
2314
+ $this->debug('Closed persistent connection at EOF');
2315
+ }
2316
+
2317
+ // munge host if using OpenSSL
2318
+ if ($this->scheme == 'ssl') {
2319
+ $host = 'ssl://' . $host;
2320
+ }
2321
+ $this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
2322
+
2323
+ // open socket
2324
+ if($connection_timeout > 0){
2325
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout);
2326
+ } else {
2327
+ $this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str);
2328
+ }
2329
+
2330
+ // test pointer
2331
+ if(!$this->fp) {
2332
+ $msg = 'Couldn\'t open socket connection to server ' . $this->url;
2333
+ if ($this->errno) {
2334
+ $msg .= ', Error ('.$this->errno.'): '.$this->error_str;
2335
+ } else {
2336
+ $msg .= ' prior to connect(). This is often a problem looking up the host name.';
2337
+ }
2338
+ $this->debug($msg);
2339
+ $this->setError($msg);
2340
+ return false;
2341
+ }
2342
+
2343
+ // set response timeout
2344
+ $this->debug('set response timeout to ' . $response_timeout);
2345
+ socket_set_timeout( $this->fp, $response_timeout);
2346
+
2347
+ $this->debug('socket connected');
2348
+ return true;
2349
+ } else if ($this->io_method() == 'curl') {
2350
+ if (!extension_loaded('curl')) {
2351
+ // $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
2352
+ $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.');
2353
+ return false;
2354
+ }
2355
+ // Avoid warnings when PHP does not have these options
2356
+ if (defined('CURLOPT_CONNECTIONTIMEOUT'))
2357
+ $CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
2358
+ else
2359
+ $CURLOPT_CONNECTIONTIMEOUT = 78;
2360
+ if (defined('CURLOPT_HTTPAUTH'))
2361
+ $CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
2362
+ else
2363
+ $CURLOPT_HTTPAUTH = 107;
2364
+ if (defined('CURLOPT_PROXYAUTH'))
2365
+ $CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
2366
+ else
2367
+ $CURLOPT_PROXYAUTH = 111;
2368
+ if (defined('CURLAUTH_BASIC'))
2369
+ $CURLAUTH_BASIC = CURLAUTH_BASIC;
2370
+ else
2371
+ $CURLAUTH_BASIC = 1;
2372
+ if (defined('CURLAUTH_DIGEST'))
2373
+ $CURLAUTH_DIGEST = CURLAUTH_DIGEST;
2374
+ else
2375
+ $CURLAUTH_DIGEST = 2;
2376
+ if (defined('CURLAUTH_NTLM'))
2377
+ $CURLAUTH_NTLM = CURLAUTH_NTLM;
2378
+ else
2379
+ $CURLAUTH_NTLM = 8;
2380
+
2381
+ $this->debug('connect using cURL');
2382
+ // init CURL
2383
+ $this->ch = curl_init();
2384
+ // set url
2385
+ $hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
2386
+ // add path
2387
+ $hostURL .= $this->path;
2388
+ $this->setCurlOption(CURLOPT_URL, $hostURL);
2389
+ // follow location headers (re-directs)
2390
+ if (ini_get('safe_mode') || ini_get('open_basedir')) {
2391
+ $this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
2392
+ $this->debug('safe_mode = ');
2393
+ $this->appendDebug($this->varDump(ini_get('safe_mode')));
2394
+ $this->debug('open_basedir = ');
2395
+ $this->appendDebug($this->varDump(ini_get('open_basedir')));
2396
+ } else {
2397
+ $this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
2398
+ }
2399
+ // ask for headers in the response output
2400
+ $this->setCurlOption(CURLOPT_HEADER, 1);
2401
+ // ask for the response output as the return value
2402
+ $this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
2403
+ // encode
2404
+ // We manage this ourselves through headers and encoding
2405
+ // if(function_exists('gzuncompress')){
2406
+ // $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
2407
+ // }
2408
+ // persistent connection
2409
+ if ($this->persistentConnection) {
2410
+ // I believe the following comment is now bogus, having applied to
2411
+ // the code when it used CURLOPT_CUSTOMREQUEST to send the request.
2412
+ // The way we send data, we cannot use persistent connections, since
2413
+ // there will be some "junk" at the end of our request.
2414
+ //$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
2415
+ $this->persistentConnection = false;
2416
+ $this->setHeader('Connection', 'close');
2417
+ }
2418
+ // set timeouts
2419
+ if ($connection_timeout != 0) {
2420
+ $this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
2421
+ }
2422
+ if ($response_timeout != 0) {
2423
+ $this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
2424
+ }
2425
+
2426
+ if ($this->scheme == 'https') {
2427
+ $this->debug('set cURL SSL verify options');
2428
+ // recent versions of cURL turn on peer/host checking by default,
2429
+ // while PHP binaries are not compiled with a default location for the
2430
+ // CA cert bundle, so disable peer/host checking.
2431
+ //$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
2432
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
2433
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
2434
+
2435
+ // support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
2436
+ if ($this->authtype == 'certificate') {
2437
+ $this->debug('set cURL certificate options');
2438
+ if (isset($this->certRequest['cainfofile'])) {
2439
+ $this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
2440
+ }
2441
+ if (isset($this->certRequest['verifypeer'])) {
2442
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
2443
+ } else {
2444
+ $this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
2445
+ }
2446
+ if (isset($this->certRequest['verifyhost'])) {
2447
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
2448
+ } else {
2449
+ $this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
2450
+ }
2451
+ if (isset($this->certRequest['sslcertfile'])) {
2452
+ $this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
2453
+ }
2454
+ if (isset($this->certRequest['sslkeyfile'])) {
2455
+ $this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
2456
+ }
2457
+ if (isset($this->certRequest['passphrase'])) {
2458
+ $this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
2459
+ }
2460
+ if (isset($this->certRequest['certpassword'])) {
2461
+ $this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
2462
+ }
2463
+ }
2464
+ }
2465
+ if ($this->authtype && ($this->authtype != 'certificate')) {
2466
+ if ($this->username) {
2467
+ $this->debug('set cURL username/password');
2468
+ $this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
2469
+ }
2470
+ if ($this->authtype == 'basic') {
2471
+ $this->debug('set cURL for Basic authentication');
2472
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
2473
+ }
2474
+ if ($this->authtype == 'digest') {
2475
+ $this->debug('set cURL for digest authentication');
2476
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
2477
+ }
2478
+ if ($this->authtype == 'ntlm') {
2479
+ $this->debug('set cURL for NTLM authentication');
2480
+ $this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
2481
+ }
2482
+ }
2483
+ if (is_array($this->proxy)) {
2484
+ $this->debug('set cURL proxy options');
2485
+ if ($this->proxy['port'] != '') {
2486
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'].':'.$this->proxy['port']);
2487
+ } else {
2488
+ $this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
2489
+ }
2490
+ if ($this->proxy['username'] || $this->proxy['password']) {
2491
+ $this->debug('set cURL proxy authentication options');
2492
+ $this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'].':'.$this->proxy['password']);
2493
+ if ($this->proxy['authtype'] == 'basic') {
2494
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
2495
+ }
2496
+ if ($this->proxy['authtype'] == 'ntlm') {
2497
+ $this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
2498
+ }
2499
+ }
2500
+ }
2501
+ $this->debug('cURL connection set up');
2502
+ return true;
2503
+ } else {
2504
+ $this->setError('Unknown scheme ' . $this->scheme);
2505
+ $this->debug('Unknown scheme ' . $this->scheme);
2506
+ return false;
2507
+ }
2508
+ }
2509
+
2510
+ /**
2511
+ * sends the SOAP request and gets the SOAP response via HTTP[S]
2512
+ *
2513
+ * @param string $data message data
2514
+ * @param integer $timeout set connection timeout in seconds
2515
+ * @param integer $response_timeout set response timeout in seconds
2516
+ * @param array $cookies cookies to send
2517
+ * @return string data
2518
+ * @access public
2519
+ */
2520
+ function send($data, $timeout=0, $response_timeout=30, $cookies=NULL) {
2521
+
2522
+ $this->debug('entered send() with data of length: '.strlen($data));
2523
+
2524
+ $this->tryagain = true;
2525
+ $tries = 0;
2526
+ while ($this->tryagain) {
2527
+ $this->tryagain = false;
2528
+ if ($tries++ < 2) {
2529
+ // make connnection
2530
+ if (!$this->connect($timeout, $response_timeout)){
2531
+ return false;
2532
+ }
2533
+
2534
+ // send request
2535
+ if (!$this->sendRequest($data, $cookies)){
2536
+ return false;
2537
+ }
2538
+
2539
+ // get response
2540
+ $respdata = $this->getResponse();
2541
+ } else {
2542
+ $this->setError("Too many tries to get an OK response ($this->response_status_line)");
2543
+ }
2544
+ }
2545
+ $this->debug('end of send()');
2546
+ return $respdata;
2547
+ }
2548
+
2549
+
2550
+ /**
2551
+ * sends the SOAP request and gets the SOAP response via HTTPS using CURL
2552
+ *
2553
+ * @param string $data message data
2554
+ * @param integer $timeout set connection timeout in seconds
2555
+ * @param integer $response_timeout set response timeout in seconds
2556
+ * @param array $cookies cookies to send
2557
+ * @return string data
2558
+ * @access public
2559
+ * @deprecated
2560
+ */
2561
+ function sendHTTPS($data, $timeout=0, $response_timeout=30, $cookies) {
2562
+ return $this->send($data, $timeout, $response_timeout, $cookies);
2563
+ }
2564
+
2565
+ /**
2566
+ * if authenticating, set user credentials here
2567
+ *
2568
+ * @param string $username
2569
+ * @param string $password
2570
+ * @param string $authtype (basic|digest|certificate|ntlm)
2571
+ * @param array $digestRequest (keys must be nonce, nc, realm, qop)
2572
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
2573
+ * @access public
2574
+ */
2575
+ function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array()) {
2576
+ $this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
2577
+ $this->appendDebug($this->varDump($digestRequest));
2578
+ $this->debug("certRequest=");
2579
+ $this->appendDebug($this->varDump($certRequest));
2580
+ // cf. RFC 2617
2581
+ if ($authtype == 'basic') {
2582
+ $this->setHeader('Authorization', 'Basic '.base64_encode(str_replace(':','',$username).':'.$password));
2583
+ } elseif ($authtype == 'digest') {
2584
+ if (isset($digestRequest['nonce'])) {
2585
+ $digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
2586
+
2587
+ // calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
2588
+
2589
+ // A1 = unq(username-value) ":" unq(realm-value) ":" passwd
2590
+ $A1 = $username. ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
2591
+
2592
+ // H(A1) = MD5(A1)
2593
+ $HA1 = md5($A1);
2594
+
2595
+ // A2 = Method ":" digest-uri-value
2596
+ $A2 = $this->request_method . ':' . $this->digest_uri;
2597
+
2598
+ // H(A2)
2599
+ $HA2 = md5($A2);
2600
+
2601
+ // KD(secret, data) = H(concat(secret, ":", data))
2602
+ // if qop == auth:
2603
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value)
2604
+ // ":" nc-value
2605
+ // ":" unq(cnonce-value)
2606
+ // ":" unq(qop-value)
2607
+ // ":" H(A2)
2608
+ // ) <">
2609
+ // if qop is missing,
2610
+ // request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
2611
+
2612
+ $unhashedDigest = '';
2613
+ $nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
2614
+ $cnonce = $nonce;
2615
+ if ($digestRequest['qop'] != '') {
2616
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
2617
+ } else {
2618
+ $unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
2619
+ }
2620
+
2621
+ $hashedDigest = md5($unhashedDigest);
2622
+
2623
+ $opaque = '';
2624
+ if (isset($digestRequest['opaque'])) {
2625
+ $opaque = ', opaque="' . $digestRequest['opaque'] . '"';
2626
+ }
2627
+
2628
+ $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 . '"');
2629
+ }
2630
+ } elseif ($authtype == 'certificate') {
2631
+ $this->certRequest = $certRequest;
2632
+ $this->debug('Authorization header not set for certificate');
2633
+ } elseif ($authtype == 'ntlm') {
2634
+ // do nothing
2635
+ $this->debug('Authorization header not set for ntlm');
2636
+ }
2637
+ $this->username = $username;
2638
+ $this->password = $password;
2639
+ $this->authtype = $authtype;
2640
+ $this->digestRequest = $digestRequest;
2641
+ }
2642
+
2643
+ /**
2644
+ * set the soapaction value
2645
+ *
2646
+ * @param string $soapaction
2647
+ * @access public
2648
+ */
2649
+ function setSOAPAction($soapaction) {
2650
+ $this->setHeader('SOAPAction', '"' . $soapaction . '"');
2651
+ }
2652
+
2653
+ /**
2654
+ * use http encoding
2655
+ *
2656
+ * @param string $enc encoding style. supported values: gzip, deflate, or both
2657
+ * @access public
2658
+ */
2659
+ function setEncoding($enc='gzip, deflate') {
2660
+ if (function_exists('gzdeflate')) {
2661
+ $this->protocol_version = '1.1';
2662
+ $this->setHeader('Accept-Encoding', $enc);
2663
+ if (!isset($this->outgoing_headers['Connection'])) {
2664
+ $this->setHeader('Connection', 'close');
2665
+ $this->persistentConnection = false;
2666
+ }
2667
+ set_magic_quotes_runtime(0);
2668
+ // deprecated
2669
+ $this->encoding = $enc;
2670
+ }
2671
+ }
2672
+
2673
+ /**
2674
+ * set proxy info here
2675
+ *
2676
+ * @param string $proxyhost use an empty string to remove proxy
2677
+ * @param string $proxyport
2678
+ * @param string $proxyusername
2679
+ * @param string $proxypassword
2680
+ * @param string $proxyauthtype (basic|ntlm)
2681
+ * @access public
2682
+ */
2683
+ function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic') {
2684
+ if ($proxyhost) {
2685
+ $this->proxy = array(
2686
+ 'host' => $proxyhost,
2687
+ 'port' => $proxyport,
2688
+ 'username' => $proxyusername,
2689
+ 'password' => $proxypassword,
2690
+ 'authtype' => $proxyauthtype
2691
+ );
2692
+ if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
2693
+ $this->setHeader('Proxy-Authorization', ' Basic '.base64_encode($proxyusername.':'.$proxypassword));
2694
+ }
2695
+ } else {
2696
+ $this->debug('remove proxy');
2697
+ $proxy = null;
2698
+ unsetHeader('Proxy-Authorization');
2699
+ }
2700
+ }
2701
+
2702
+
2703
+ /**
2704
+ * Test if the given string starts with a header that is to be skipped.
2705
+ * Skippable headers result from chunked transfer and proxy requests.
2706
+ *
2707
+ * @param string $data The string to check.
2708
+ * @returns boolean Whether a skippable header was found.
2709
+ * @access private
2710
+ */
2711
+ function isSkippableCurlHeader(&$data) {
2712
+ $skipHeaders = array( 'HTTP/1.1 100',
2713
+ 'HTTP/1.0 301',
2714
+ 'HTTP/1.1 301',
2715
+ 'HTTP/1.0 302',
2716
+ 'HTTP/1.1 302',
2717
+ 'HTTP/1.0 401',
2718
+ 'HTTP/1.1 401',
2719
+ 'HTTP/1.0 200 Connection established');
2720
+ foreach ($skipHeaders as $hd) {
2721
+ $prefix = substr($data, 0, strlen($hd));
2722
+ if ($prefix == $hd) return true;
2723
+ }
2724
+
2725
+ return false;
2726
+ }
2727
+
2728
+ /**
2729
+ * decode a string that is encoded w/ "chunked' transfer encoding
2730
+ * as defined in RFC2068 19.4.6
2731
+ *
2732
+ * @param string $buffer
2733
+ * @param string $lb
2734
+ * @returns string
2735
+ * @access public
2736
+ * @deprecated
2737
+ */
2738
+ function decodeChunked($buffer, $lb){
2739
+ // length := 0
2740
+ $length = 0;
2741
+ $new = '';
2742
+
2743
+ // read chunk-size, chunk-extension (if any) and CRLF
2744
+ // get the position of the linebreak
2745
+ $chunkend = strpos($buffer, $lb);
2746
+ if ($chunkend == FALSE) {
2747
+ $this->debug('no linebreak found in decodeChunked');
2748
+ return $new;
2749
+ }
2750
+ $temp = substr($buffer,0,$chunkend);
2751
+ $chunk_size = hexdec( trim($temp) );
2752
+ $chunkstart = $chunkend + strlen($lb);
2753
+ // while (chunk-size > 0) {
2754
+ while ($chunk_size > 0) {
2755
+ $this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
2756
+ $chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size);
2757
+
2758
+ // Just in case we got a broken connection
2759
+ if ($chunkend == FALSE) {
2760
+ $chunk = substr($buffer,$chunkstart);
2761
+ // append chunk-data to entity-body
2762
+ $new .= $chunk;
2763
+ $length += strlen($chunk);
2764
+ break;
2765
+ }
2766
+
2767
+ // read chunk-data and CRLF
2768
+ $chunk = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2769
+ // append chunk-data to entity-body
2770
+ $new .= $chunk;
2771
+ // length := length + chunk-size
2772
+ $length += strlen($chunk);
2773
+ // read chunk-size and CRLF
2774
+ $chunkstart = $chunkend + strlen($lb);
2775
+
2776
+ $chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
2777
+ if ($chunkend == FALSE) {
2778
+ break; //Just in case we got a broken connection
2779
+ }
2780
+ $temp = substr($buffer,$chunkstart,$chunkend-$chunkstart);
2781
+ $chunk_size = hexdec( trim($temp) );
2782
+ $chunkstart = $chunkend;
2783
+ }
2784
+ return $new;
2785
+ }
2786
+
2787
+ /**
2788
+ * Writes the payload, including HTTP headers, to $this->outgoing_payload.
2789
+ *
2790
+ * @param string $data HTTP body
2791
+ * @param string $cookie_str data for HTTP Cookie header
2792
+ * @return void
2793
+ * @access private
2794
+ */
2795
+ function buildPayload($data, $cookie_str = '') {
2796
+ // Note: for cURL connections, $this->outgoing_payload is ignored,
2797
+ // as is the Content-Length header, but these are still created as
2798
+ // debugging guides.
2799
+
2800
+ // add content-length header
2801
+ $this->setHeader('Content-Length', strlen($data));
2802
+
2803
+ // start building outgoing payload:
2804
+ if ($this->proxy) {
2805
+ $uri = $this->url;
2806
+ } else {
2807
+ $uri = $this->uri;
2808
+ }
2809
+ $req = "$this->request_method $uri HTTP/$this->protocol_version";
2810
+ $this->debug("HTTP request: $req");
2811
+ $this->outgoing_payload = "$req\r\n";
2812
+
2813
+ // loop thru headers, serializing
2814
+ foreach($this->outgoing_headers as $k => $v){
2815
+ $hdr = $k.': '.$v;
2816
+ $this->debug("HTTP header: $hdr");
2817
+ $this->outgoing_payload .= "$hdr\r\n";
2818
+ }
2819
+
2820
+ // add any cookies
2821
+ if ($cookie_str != '') {
2822
+ $hdr = 'Cookie: '.$cookie_str;
2823
+ $this->debug("HTTP header: $hdr");
2824
+ $this->outgoing_payload .= "$hdr\r\n";
2825
+ }
2826
+
2827
+ // header/body separator
2828
+ $this->outgoing_payload .= "\r\n";
2829
+
2830
+ // add data
2831
+ $this->outgoing_payload .= $data;
2832
+ }
2833
+
2834
+ /**
2835
+ * sends the SOAP request via HTTP[S]
2836
+ *
2837
+ * @param string $data message data
2838
+ * @param array $cookies cookies to send
2839
+ * @return boolean true if OK, false if problem
2840
+ * @access private
2841
+ */
2842
+ function sendRequest($data, $cookies = NULL) {
2843
+ // build cookie string
2844
+ $cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
2845
+
2846
+ // build payload
2847
+ $this->buildPayload($data, $cookie_str);
2848
+
2849
+ if ($this->io_method() == 'socket') {
2850
+ // send payload
2851
+ if(!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
2852
+ $this->setError('couldn\'t write message data to socket');
2853
+ $this->debug('couldn\'t write message data to socket');
2854
+ return false;
2855
+ }
2856
+ $this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
2857
+ return true;
2858
+ } else if ($this->io_method() == 'curl') {
2859
+ // set payload
2860
+ // cURL does say this should only be the verb, and in fact it
2861
+ // turns out that the URI and HTTP version are appended to this, which
2862
+ // some servers refuse to work with (so we no longer use this method!)
2863
+ //$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
2864
+ $curl_headers = array();
2865
+ foreach($this->outgoing_headers as $k => $v){
2866
+ if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
2867
+ $this->debug("Skip cURL header $k: $v");
2868
+ } else {
2869
+ $curl_headers[] = "$k: $v";
2870
+ }
2871
+ }
2872
+ if ($cookie_str != '') {
2873
+ $curl_headers[] = 'Cookie: ' . $cookie_str;
2874
+ }
2875
+ $this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
2876
+ $this->debug('set cURL HTTP headers');
2877
+ if ($this->request_method == "POST") {
2878
+ $this->setCurlOption(CURLOPT_POST, 1);
2879
+ $this->setCurlOption(CURLOPT_POSTFIELDS, $data);
2880
+ $this->debug('set cURL POST data');
2881
+ } else {
2882
+ }
2883
+ // insert custom user-set cURL options
2884
+ foreach ($this->ch_options as $key => $val) {
2885
+ $this->setCurlOption($key, $val);
2886
+ }
2887
+
2888
+ $this->debug('set cURL payload');
2889
+ return true;
2890
+ }
2891
+ }
2892
+
2893
+ /**
2894
+ * gets the SOAP response via HTTP[S]
2895
+ *
2896
+ * @return string the response (also sets member variables like incoming_payload)
2897
+ * @access private
2898
+ */
2899
+ function getResponse(){
2900
+ $this->incoming_payload = '';
2901
+
2902
+ if ($this->io_method() == 'socket') {
2903
+ // loop until headers have been retrieved
2904
+ $data = '';
2905
+ while (!isset($lb)){
2906
+
2907
+ // We might EOF during header read.
2908
+ if(feof($this->fp)) {
2909
+ $this->incoming_payload = $data;
2910
+ $this->debug('found no headers before EOF after length ' . strlen($data));
2911
+ $this->debug("received before EOF:\n" . $data);
2912
+ $this->setError('server failed to send headers');
2913
+ return false;
2914
+ }
2915
+
2916
+ $tmp = fgets($this->fp, 256);
2917
+ $tmplen = strlen($tmp);
2918
+ $this->debug("read line of $tmplen bytes: " . trim($tmp));
2919
+
2920
+ if ($tmplen == 0) {
2921
+ $this->incoming_payload = $data;
2922
+ $this->debug('socket read of headers timed out after length ' . strlen($data));
2923
+ $this->debug("read before timeout: " . $data);
2924
+ $this->setError('socket read of headers timed out');
2925
+ return false;
2926
+ }
2927
+
2928
+ $data .= $tmp;
2929
+ $pos = strpos($data,"\r\n\r\n");
2930
+ if($pos > 1){
2931
+ $lb = "\r\n";
2932
+ } else {
2933
+ $pos = strpos($data,"\n\n");
2934
+ if($pos > 1){
2935
+ $lb = "\n";
2936
+ }
2937
+ }
2938
+ // remove 100 headers
2939
+ if (isset($lb) && ereg('^HTTP/1.1 100',$data)) {
2940
+ unset($lb);
2941
+ $data = '';
2942
+ }//
2943
+ }
2944
+ // store header data
2945
+ $this->incoming_payload .= $data;
2946
+ $this->debug('found end of headers after length ' . strlen($data));
2947
+ // process headers
2948
+ $header_data = trim(substr($data,0,$pos));
2949
+ $header_array = explode($lb,$header_data);
2950
+ $this->incoming_headers = array();
2951
+ $this->incoming_cookies = array();
2952
+ foreach($header_array as $header_line){
2953
+ $arr = explode(':',$header_line, 2);
2954
+ if(count($arr) > 1){
2955
+ $header_name = strtolower(trim($arr[0]));
2956
+ $this->incoming_headers[$header_name] = trim($arr[1]);
2957
+ if ($header_name == 'set-cookie') {
2958
+ // TODO: allow multiple cookies from parseCookie
2959
+ $cookie = $this->parseCookie(trim($arr[1]));
2960
+ if ($cookie) {
2961
+ $this->incoming_cookies[] = $cookie;
2962
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
2963
+ } else {
2964
+ $this->debug('did not find cookie in ' . trim($arr[1]));
2965
+ }
2966
+ }
2967
+ } else if (isset($header_name)) {
2968
+ // append continuation line to previous header
2969
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
2970
+ }
2971
+ }
2972
+
2973
+ // loop until msg has been received
2974
+ if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
2975
+ $content_length = 2147483647; // ignore any content-length header
2976
+ $chunked = true;
2977
+ $this->debug("want to read chunked content");
2978
+ } elseif (isset($this->incoming_headers['content-length'])) {
2979
+ $content_length = $this->incoming_headers['content-length'];
2980
+ $chunked = false;
2981
+ $this->debug("want to read content of length $content_length");
2982
+ } else {
2983
+ $content_length = 2147483647;
2984
+ $chunked = false;
2985
+ $this->debug("want to read content to EOF");
2986
+ }
2987
+ $data = '';
2988
+ do {
2989
+ if ($chunked) {
2990
+ $tmp = fgets($this->fp, 256);
2991
+ $tmplen = strlen($tmp);
2992
+ $this->debug("read chunk line of $tmplen bytes");
2993
+ if ($tmplen == 0) {
2994
+ $this->incoming_payload = $data;
2995
+ $this->debug('socket read of chunk length timed out after length ' . strlen($data));
2996
+ $this->debug("read before timeout:\n" . $data);
2997
+ $this->setError('socket read of chunk length timed out');
2998
+ return false;
2999
+ }
3000
+ $content_length = hexdec(trim($tmp));
3001
+ $this->debug("chunk length $content_length");
3002
+ }
3003
+ $strlen = 0;
3004
+ while (($strlen < $content_length) && (!feof($this->fp))) {
3005
+ $readlen = min(8192, $content_length - $strlen);
3006
+ $tmp = fread($this->fp, $readlen);
3007
+ $tmplen = strlen($tmp);
3008
+ $this->debug("read buffer of $tmplen bytes");
3009
+ if (($tmplen == 0) && (!feof($this->fp))) {
3010
+ $this->incoming_payload = $data;
3011
+ $this->debug('socket read of body timed out after length ' . strlen($data));
3012
+ $this->debug("read before timeout:\n" . $data);
3013
+ $this->setError('socket read of body timed out');
3014
+ return false;
3015
+ }
3016
+ $strlen += $tmplen;
3017
+ $data .= $tmp;
3018
+ }
3019
+ if ($chunked && ($content_length > 0)) {
3020
+ $tmp = fgets($this->fp, 256);
3021
+ $tmplen = strlen($tmp);
3022
+ $this->debug("read chunk terminator of $tmplen bytes");
3023
+ if ($tmplen == 0) {
3024
+ $this->incoming_payload = $data;
3025
+ $this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
3026
+ $this->debug("read before timeout:\n" . $data);
3027
+ $this->setError('socket read of chunk terminator timed out');
3028
+ return false;
3029
+ }
3030
+ }
3031
+ } while ($chunked && ($content_length > 0) && (!feof($this->fp)));
3032
+ if (feof($this->fp)) {
3033
+ $this->debug('read to EOF');
3034
+ }
3035
+ $this->debug('read body of length ' . strlen($data));
3036
+ $this->incoming_payload .= $data;
3037
+ $this->debug('received a total of '.strlen($this->incoming_payload).' bytes of data from server');
3038
+
3039
+ // close filepointer
3040
+ if(
3041
+ (isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
3042
+ (! $this->persistentConnection) || feof($this->fp)){
3043
+ fclose($this->fp);
3044
+ $this->fp = false;
3045
+ $this->debug('closed socket');
3046
+ }
3047
+
3048
+ // connection was closed unexpectedly
3049
+ if($this->incoming_payload == ''){
3050
+ $this->setError('no response from server');
3051
+ return false;
3052
+ }
3053
+
3054
+ // decode transfer-encoding
3055
+ // if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
3056
+ // if(!$data = $this->decodeChunked($data, $lb)){
3057
+ // $this->setError('Decoding of chunked data failed');
3058
+ // return false;
3059
+ // }
3060
+ //print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
3061
+ // set decoded payload
3062
+ // $this->incoming_payload = $header_data.$lb.$lb.$data;
3063
+ // }
3064
+
3065
+ } else if ($this->io_method() == 'curl') {
3066
+ // send and receive
3067
+ $this->debug('send and receive with cURL');
3068
+ $this->incoming_payload = curl_exec($this->ch);
3069
+ $data = $this->incoming_payload;
3070
+
3071
+ $cErr = curl_error($this->ch);
3072
+ if ($cErr != '') {
3073
+ $err = 'cURL ERROR: '.curl_errno($this->ch).': '.$cErr.'<br>';
3074
+ // TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
3075
+ foreach(curl_getinfo($this->ch) as $k => $v){
3076
+ $err .= "$k: $v<br>";
3077
+ }
3078
+ $this->debug($err);
3079
+ $this->setError($err);
3080
+ curl_close($this->ch);
3081
+ return false;
3082
+ } else {
3083
+ //echo '<pre>';
3084
+ //var_dump(curl_getinfo($this->ch));
3085
+ //echo '</pre>';
3086
+ }
3087
+ // close curl
3088
+ $this->debug('No cURL error, closing cURL');
3089
+ curl_close($this->ch);
3090
+
3091
+ // try removing skippable headers
3092
+ $savedata = $data;
3093
+ while ($this->isSkippableCurlHeader($data)) {
3094
+ $this->debug("Found HTTP header to skip");
3095
+ if ($pos = strpos($data,"\r\n\r\n")) {
3096
+ $data = ltrim(substr($data,$pos));
3097
+ } elseif($pos = strpos($data,"\n\n") ) {
3098
+ $data = ltrim(substr($data,$pos));
3099
+ }
3100
+ }
3101
+
3102
+ if ($data == '') {
3103
+ // have nothing left; just remove 100 header(s)
3104
+ $data = $savedata;
3105
+ while (ereg('^HTTP/1.1 100',$data)) {
3106
+ if ($pos = strpos($data,"\r\n\r\n")) {
3107
+ $data = ltrim(substr($data,$pos));
3108
+ } elseif($pos = strpos($data,"\n\n") ) {
3109
+ $data = ltrim(substr($data,$pos));
3110
+ }
3111
+ }
3112
+ }
3113
+
3114
+ // separate content from HTTP headers
3115
+ if ($pos = strpos($data,"\r\n\r\n")) {
3116
+ $lb = "\r\n";
3117
+ } elseif( $pos = strpos($data,"\n\n")) {
3118
+ $lb = "\n";
3119
+ } else {
3120
+ $this->debug('no proper separation of headers and document');
3121
+ $this->setError('no proper separation of headers and document');
3122
+ return false;
3123
+ }
3124
+ $header_data = trim(substr($data,0,$pos));
3125
+ $header_array = explode($lb,$header_data);
3126
+ $data = ltrim(substr($data,$pos));
3127
+ $this->debug('found proper separation of headers and document');
3128
+ $this->debug('cleaned data, stringlen: '.strlen($data));
3129
+ // clean headers
3130
+ foreach ($header_array as $header_line) {
3131
+ $arr = explode(':',$header_line,2);
3132
+ if(count($arr) > 1){
3133
+ $header_name = strtolower(trim($arr[0]));
3134
+ $this->incoming_headers[$header_name] = trim($arr[1]);
3135
+ if ($header_name == 'set-cookie') {
3136
+ // TODO: allow multiple cookies from parseCookie
3137
+ $cookie = $this->parseCookie(trim($arr[1]));
3138
+ if ($cookie) {
3139
+ $this->incoming_cookies[] = $cookie;
3140
+ $this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
3141
+ } else {
3142
+ $this->debug('did not find cookie in ' . trim($arr[1]));
3143
+ }
3144
+ }
3145
+ } else if (isset($header_name)) {
3146
+ // append continuation line to previous header
3147
+ $this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
3148
+ }
3149
+ }
3150
+ }
3151
+
3152
+ $this->response_status_line = $header_array[0];
3153
+ $arr = explode(' ', $this->response_status_line, 3);
3154
+ $http_version = $arr[0];
3155
+ $http_status = intval($arr[1]);
3156
+ $http_reason = count($arr) > 2 ? $arr[2] : '';
3157
+
3158
+ // see if we need to resend the request with http digest authentication
3159
+ if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
3160
+ $this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
3161
+ $this->setURL($this->incoming_headers['location']);
3162
+ $this->tryagain = true;
3163
+ return false;
3164
+ }
3165
+
3166
+ // see if we need to resend the request with http digest authentication
3167
+ if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
3168
+ $this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
3169
+ if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
3170
+ $this->debug('Server wants digest authentication');
3171
+ // remove "Digest " from our elements
3172
+ $digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
3173
+
3174
+ // parse elements into array
3175
+ $digestElements = explode(',', $digestString);
3176
+ foreach ($digestElements as $val) {
3177
+ $tempElement = explode('=', trim($val), 2);
3178
+ $digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
3179
+ }
3180
+
3181
+ // should have (at least) qop, realm, nonce
3182
+ if (isset($digestRequest['nonce'])) {
3183
+ $this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
3184
+ $this->tryagain = true;
3185
+ return false;
3186
+ }
3187
+ }
3188
+ $this->debug('HTTP authentication failed');
3189
+ $this->setError('HTTP authentication failed');
3190
+ return false;
3191
+ }
3192
+
3193
+ if (
3194
+ ($http_status >= 300 && $http_status <= 307) ||
3195
+ ($http_status >= 400 && $http_status <= 417) ||
3196
+ ($http_status >= 501 && $http_status <= 505)
3197
+ ) {
3198
+ $this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
3199
+ return false;
3200
+ }
3201
+
3202
+ // decode content-encoding
3203
+ if(isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != ''){
3204
+ if(strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip'){
3205
+ // if decoding works, use it. else assume data wasn't gzencoded
3206
+ if(function_exists('gzinflate')){
3207
+ //$timer->setMarker('starting decoding of gzip/deflated content');
3208
+ // IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
3209
+ // this means there are no Zlib headers, although there should be
3210
+ $this->debug('The gzinflate function exists');
3211
+ $datalen = strlen($data);
3212
+ if ($this->incoming_headers['content-encoding'] == 'deflate') {
3213
+ if ($degzdata = @gzinflate($data)) {
3214
+ $data = $degzdata;
3215
+ $this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
3216
+ if (strlen($data) < $datalen) {
3217
+ // test for the case that the payload has been compressed twice
3218
+ $this->debug('The inflated payload is smaller than the gzipped one; try again');
3219
+ if ($degzdata = @gzinflate($data)) {
3220
+ $data = $degzdata;
3221
+ $this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
3222
+ }
3223
+ }
3224
+ } else {
3225
+ $this->debug('Error using gzinflate to inflate the payload');
3226
+ $this->setError('Error using gzinflate to inflate the payload');
3227
+ }
3228
+ } elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
3229
+ if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
3230
+ $data = $degzdata;
3231
+ $this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
3232
+ if (strlen($data) < $datalen) {
3233
+ // test for the case that the payload has been compressed twice
3234
+ $this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
3235
+ if ($degzdata = @gzinflate(substr($data, 10))) {
3236
+ $data = $degzdata;
3237
+ $this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
3238
+ }
3239
+ }
3240
+ } else {
3241
+ $this->debug('Error using gzinflate to un-gzip the payload');
3242
+ $this->setError('Error using gzinflate to un-gzip the payload');
3243
+ }
3244
+ }
3245
+ //$timer->setMarker('finished decoding of gzip/deflated content');
3246
+ //print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
3247
+ // set decoded payload
3248
+ $this->incoming_payload = $header_data.$lb.$lb.$data;
3249
+ } else {
3250
+ $this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3251
+ $this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
3252
+ }
3253
+ } else {
3254
+ $this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3255
+ $this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
3256
+ }
3257
+ } else {
3258
+ $this->debug('No Content-Encoding header');
3259
+ }
3260
+
3261
+ if(strlen($data) == 0){
3262
+ $this->debug('no data after headers!');
3263
+ $this->setError('no data present after HTTP headers');
3264
+ return false;
3265
+ }
3266
+
3267
+ return $data;
3268
+ }
3269
+
3270
+ /**
3271
+ * sets the content-type for the SOAP message to be sent
3272
+ *
3273
+ * @param string $type the content type, MIME style
3274
+ * @param mixed $charset character set used for encoding (or false)
3275
+ * @access public
3276
+ */
3277
+ function setContentType($type, $charset = false) {
3278
+ $this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
3279
+ }
3280
+
3281
+ /**
3282
+ * specifies that an HTTP persistent connection should be used
3283
+ *
3284
+ * @return boolean whether the request was honored by this method.
3285
+ * @access public
3286
+ */
3287
+ function usePersistentConnection(){
3288
+ if (isset($this->outgoing_headers['Accept-Encoding'])) {
3289
+ return false;
3290
+ }
3291
+ $this->protocol_version = '1.1';
3292
+ $this->persistentConnection = true;
3293
+ $this->setHeader('Connection', 'Keep-Alive');
3294
+ return true;
3295
+ }
3296
+
3297
+ /**
3298
+ * parse an incoming Cookie into it's parts
3299
+ *
3300
+ * @param string $cookie_str content of cookie
3301
+ * @return array with data of that cookie
3302
+ * @access private
3303
+ */
3304
+ /*
3305
+ * TODO: allow a Set-Cookie string to be parsed into multiple cookies
3306
+ */
3307
+ function parseCookie($cookie_str) {
3308
+ $cookie_str = str_replace('; ', ';', $cookie_str) . ';';
3309
+ $data = split(';', $cookie_str);
3310
+ $value_str = $data[0];
3311
+
3312
+ $cookie_param = 'domain=';
3313
+ $start = strpos($cookie_str, $cookie_param);
3314
+ if ($start > 0) {
3315
+ $domain = substr($cookie_str, $start + strlen($cookie_param));
3316
+ $domain = substr($domain, 0, strpos($domain, ';'));
3317
+ } else {
3318
+ $domain = '';
3319
+ }
3320
+
3321
+ $cookie_param = 'expires=';
3322
+ $start = strpos($cookie_str, $cookie_param);
3323
+ if ($start > 0) {
3324
+ $expires = substr($cookie_str, $start + strlen($cookie_param));
3325
+ $expires = substr($expires, 0, strpos($expires, ';'));
3326
+ } else {
3327
+ $expires = '';
3328
+ }
3329
+
3330
+ $cookie_param = 'path=';
3331
+ $start = strpos($cookie_str, $cookie_param);
3332
+ if ( $start > 0 ) {
3333
+ $path = substr($cookie_str, $start + strlen($cookie_param));
3334
+ $path = substr($path, 0, strpos($path, ';'));
3335
+ } else {
3336
+ $path = '/';
3337
+ }
3338
+
3339
+ $cookie_param = ';secure;';
3340
+ if (strpos($cookie_str, $cookie_param) !== FALSE) {
3341
+ $secure = true;
3342
+ } else {
3343
+ $secure = false;
3344
+ }
3345
+
3346
+ $sep_pos = strpos($value_str, '=');
3347
+
3348
+ if ($sep_pos) {
3349
+ $name = substr($value_str, 0, $sep_pos);
3350
+ $value = substr($value_str, $sep_pos + 1);
3351
+ $cookie= array( 'name' => $name,
3352
+ 'value' => $value,
3353
+ 'domain' => $domain,
3354
+ 'path' => $path,
3355
+ 'expires' => $expires,
3356
+ 'secure' => $secure
3357
+ );
3358
+ return $cookie;
3359
+ }
3360
+ return false;
3361
+ }
3362
+
3363
+ /**
3364
+ * sort out cookies for the current request
3365
+ *
3366
+ * @param array $cookies array with all cookies
3367
+ * @param boolean $secure is the send-content secure or not?
3368
+ * @return string for Cookie-HTTP-Header
3369
+ * @access private
3370
+ */
3371
+ function getCookiesForRequest($cookies, $secure=false) {
3372
+ $cookie_str = '';
3373
+ if ((! is_null($cookies)) && (is_array($cookies))) {
3374
+ foreach ($cookies as $cookie) {
3375
+ if (! is_array($cookie)) {
3376
+ continue;
3377
+ }
3378
+ $this->debug("check cookie for validity: ".$cookie['name'].'='.$cookie['value']);
3379
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
3380
+ if (strtotime($cookie['expires']) <= time()) {
3381
+ $this->debug('cookie has expired');
3382
+ continue;
3383
+ }
3384
+ }
3385
+ if ((isset($cookie['domain'])) && (! empty($cookie['domain']))) {
3386
+ $domain = preg_quote($cookie['domain']);
3387
+ if (! preg_match("'.*$domain$'i", $this->host)) {
3388
+ $this->debug('cookie has different domain');
3389
+ continue;
3390
+ }
3391
+ }
3392
+ if ((isset($cookie['path'])) && (! empty($cookie['path']))) {
3393
+ $path = preg_quote($cookie['path']);
3394
+ if (! preg_match("'^$path.*'i", $this->path)) {
3395
+ $this->debug('cookie is for a different path');
3396
+ continue;
3397
+ }
3398
+ }
3399
+ if ((! $secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
3400
+ $this->debug('cookie is secure, transport is not');
3401
+ continue;
3402
+ }
3403
+ $cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
3404
+ $this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
3405
+ }
3406
+ }
3407
+ return $cookie_str;
3408
+ }
3409
+ }
3410
+
3411
+ ?><?php
3412
+
3413
+
3414
+
3415
+ /**
3416
+ *
3417
+ * nusoap_server allows the user to create a SOAP server
3418
+ * that is capable of receiving messages and returning responses
3419
+ *
3420
+ * @author Dietrich Ayala <dietrich@ganx4.com>
3421
+ * @author Scott Nichol <snichol@users.sourceforge.net>
3422
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
3423
+ * @access public
3424
+ */
3425
+ class nusoap_server extends nusoap_base {
3426
+ /**
3427
+ * HTTP headers of request
3428
+ * @var array
3429
+ * @access private
3430
+ */
3431
+ var $headers = array();
3432
+ /**
3433
+ * HTTP request
3434
+ * @var string
3435
+ * @access private
3436
+ */
3437
+ var $request = '';
3438
+ /**
3439
+ * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
3440
+ * @var string
3441
+ * @access public
3442
+ */
3443
+ var $requestHeaders = '';
3444
+ /**
3445
+ * SOAP Headers from request (parsed)
3446
+ * @var mixed
3447
+ * @access public
3448
+ */
3449
+ var $requestHeader = NULL;
3450
+ /**
3451
+ * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
3452
+ * @var string
3453
+ * @access public
3454
+ */
3455
+ var $document = '';
3456
+ /**
3457
+ * SOAP payload for request (text)
3458
+ * @var string
3459
+ * @access public
3460
+ */
3461
+ var $requestSOAP = '';
3462
+ /**
3463
+ * requested method namespace URI
3464
+ * @var string
3465
+ * @access private
3466
+ */
3467
+ var $methodURI = '';
3468
+ /**
3469
+ * name of method requested
3470
+ * @var string
3471
+ * @access private
3472
+ */
3473
+ var $methodname = '';
3474
+ /**
3475
+ * method parameters from request
3476
+ * @var array
3477
+ * @access private
3478
+ */
3479
+ var $methodparams = array();
3480
+ /**
3481
+ * SOAP Action from request
3482
+ * @var string
3483
+ * @access private
3484
+ */
3485
+ var $SOAPAction = '';
3486
+ /**
3487
+ * character set encoding of incoming (request) messages
3488
+ * @var string
3489
+ * @access public
3490
+ */
3491
+ var $xml_encoding = '';
3492
+ /**
3493
+ * toggles whether the parser decodes element content w/ utf8_decode()
3494
+ * @var boolean
3495
+ * @access public
3496
+ */
3497
+ var $decode_utf8 = true;
3498
+
3499
+ /**
3500
+ * HTTP headers of response
3501
+ * @var array
3502
+ * @access public
3503
+ */
3504
+ var $outgoing_headers = array();
3505
+ /**
3506
+ * HTTP response
3507
+ * @var string
3508
+ * @access private
3509
+ */
3510
+ var $response = '';
3511
+ /**
3512
+ * SOAP headers for response (text or array of soapval or associative array)
3513
+ * @var mixed
3514
+ * @access public
3515
+ */
3516
+ var $responseHeaders = '';
3517
+ /**
3518
+ * SOAP payload for response (text)
3519
+ * @var string
3520
+ * @access private
3521
+ */
3522
+ var $responseSOAP = '';
3523
+ /**
3524
+ * method return value to place in response
3525
+ * @var mixed
3526
+ * @access private
3527
+ */
3528
+ var $methodreturn = false;
3529
+ /**
3530
+ * whether $methodreturn is a string of literal XML
3531
+ * @var boolean
3532
+ * @access public
3533
+ */
3534
+ var $methodreturnisliteralxml = false;
3535
+ /**
3536
+ * SOAP fault for response (or false)
3537
+ * @var mixed
3538
+ * @access private
3539
+ */
3540
+ var $fault = false;
3541
+ /**
3542
+ * text indication of result (for debugging)
3543
+ * @var string
3544
+ * @access private
3545
+ */
3546
+ var $result = 'successful';
3547
+
3548
+ /**
3549
+ * assoc array of operations => opData; operations are added by the register()
3550
+ * method or by parsing an external WSDL definition
3551
+ * @var array
3552
+ * @access private
3553
+ */
3554
+ var $operations = array();
3555
+ /**
3556
+ * wsdl instance (if one)
3557
+ * @var mixed
3558
+ * @access private
3559
+ */
3560
+ var $wsdl = false;
3561
+ /**
3562
+ * URL for WSDL (if one)
3563
+ * @var mixed
3564
+ * @access private
3565
+ */
3566
+ var $externalWSDLURL = false;
3567
+ /**
3568
+ * whether to append debug to response as XML comment
3569
+ * @var boolean
3570
+ * @access public
3571
+ */
3572
+ var $debug_flag = false;
3573
+
3574
+
3575
+ /**
3576
+ * constructor
3577
+ * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
3578
+ *
3579
+ * @param mixed $wsdl file path or URL (string), or wsdl instance (object)
3580
+ * @access public
3581
+ */
3582
+ function nusoap_server($wsdl=false){
3583
+ parent::nusoap_base();
3584
+ // turn on debugging?
3585
+ global $debug;
3586
+ global $HTTP_SERVER_VARS;
3587
+
3588
+ if (isset($_SERVER)) {
3589
+ $this->debug("_SERVER is defined:");
3590
+ $this->appendDebug($this->varDump($_SERVER));
3591
+ } elseif (isset($HTTP_SERVER_VARS)) {
3592
+ $this->debug("HTTP_SERVER_VARS is defined:");
3593
+ $this->appendDebug($this->varDump($HTTP_SERVER_VARS));
3594
+ } else {
3595
+ $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
3596
+ }
3597
+
3598
+ if (isset($debug)) {
3599
+ $this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
3600
+ $this->debug_flag = $debug;
3601
+ } elseif (isset($_SERVER['QUERY_STRING'])) {
3602
+ $qs = explode('&', $_SERVER['QUERY_STRING']);
3603
+ foreach ($qs as $v) {
3604
+ if (substr($v, 0, 6) == 'debug=') {
3605
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
3606
+ $this->debug_flag = substr($v, 6);
3607
+ }
3608
+ }
3609
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3610
+ $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
3611
+ foreach ($qs as $v) {
3612
+ if (substr($v, 0, 6) == 'debug=') {
3613
+ $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
3614
+ $this->debug_flag = substr($v, 6);
3615
+ }
3616
+ }
3617
+ }
3618
+
3619
+ // wsdl
3620
+ if($wsdl){
3621
+ $this->debug("In nusoap_server, WSDL is specified");
3622
+ if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
3623
+ $this->wsdl = $wsdl;
3624
+ $this->externalWSDLURL = $this->wsdl->wsdl;
3625
+ $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
3626
+ } else {
3627
+ $this->debug('Create wsdl from ' . $wsdl);
3628
+ $this->wsdl = new wsdl($wsdl);
3629
+ $this->externalWSDLURL = $wsdl;
3630
+ }
3631
+ $this->appendDebug($this->wsdl->getDebug());
3632
+ $this->wsdl->clearDebug();
3633
+ if($err = $this->wsdl->getError()){
3634
+ die('WSDL ERROR: '.$err);
3635
+ }
3636
+ }
3637
+ }
3638
+
3639
+ /**
3640
+ * processes request and returns response
3641
+ *
3642
+ * @param string $data usually is the value of $HTTP_RAW_POST_DATA
3643
+ * @access public
3644
+ */
3645
+ function service($data){
3646
+ global $HTTP_SERVER_VARS;
3647
+
3648
+ if (isset($_SERVER['QUERY_STRING'])) {
3649
+ $qs = $_SERVER['QUERY_STRING'];
3650
+ } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
3651
+ $qs = $HTTP_SERVER_VARS['QUERY_STRING'];
3652
+ } else {
3653
+ $qs = '';
3654
+ }
3655
+ $this->debug("In service, query string=$qs");
3656
+
3657
+ if (ereg('wsdl', $qs) ){
3658
+ $this->debug("In service, this is a request for WSDL");
3659
+ if($this->externalWSDLURL){
3660
+ if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL
3661
+ header('Location: '.$this->externalWSDLURL);
3662
+ } else { // assume file
3663
+ header("Content-Type: text/xml\r\n");
3664
+ $fp = fopen($this->externalWSDLURL, 'r');
3665
+ fpassthru($fp);
3666
+ }
3667
+ } elseif ($this->wsdl) {
3668
+ header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
3669
+ print $this->wsdl->serialize($this->debug_flag);
3670
+ if ($this->debug_flag) {
3671
+ $this->debug('wsdl:');
3672
+ $this->appendDebug($this->varDump($this->wsdl));
3673
+ print $this->getDebugAsXMLComment();
3674
+ }
3675
+ } else {
3676
+ header("Content-Type: text/html; charset=ISO-8859-1\r\n");
3677
+ print "This service does not provide WSDL";
3678
+ }
3679
+ } elseif ($data == '' && $this->wsdl) {
3680
+ $this->debug("In service, there is no data, so return Web description");
3681
+ print $this->wsdl->webDescription();
3682
+ } else {
3683
+ $this->debug("In service, invoke the request");
3684
+ $this->parse_request($data);
3685
+ if (! $this->fault) {
3686
+ $this->invoke_method();
3687
+ }
3688
+ if (! $this->fault) {
3689
+ $this->serialize_return();
3690
+ }
3691
+ $this->send_response();
3692
+ }
3693
+ }
3694
+
3695
+ /**
3696
+ * parses HTTP request headers.
3697
+ *
3698
+ * The following fields are set by this function (when successful)
3699
+ *
3700
+ * headers
3701
+ * request
3702
+ * xml_encoding
3703
+ * SOAPAction
3704
+ *
3705
+ * @access private
3706
+ */
3707
+ function parse_http_headers() {
3708
+ global $HTTP_SERVER_VARS;
3709
+
3710
+ $this->request = '';
3711
+ $this->SOAPAction = '';
3712
+ if(function_exists('getallheaders')){
3713
+ $this->debug("In parse_http_headers, use getallheaders");
3714
+ $headers = getallheaders();
3715
+ foreach($headers as $k=>$v){
3716
+ $k = strtolower($k);
3717
+ $this->headers[$k] = $v;
3718
+ $this->request .= "$k: $v\r\n";
3719
+ $this->debug("$k: $v");
3720
+ }
3721
+ // get SOAPAction header
3722
+ if(isset($this->headers['soapaction'])){
3723
+ $this->SOAPAction = str_replace('"','',$this->headers['soapaction']);
3724
+ }
3725
+ // get the character encoding of the incoming request
3726
+ if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){
3727
+ $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1));
3728
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
3729
+ $this->xml_encoding = strtoupper($enc);
3730
+ } else {
3731
+ $this->xml_encoding = 'US-ASCII';
3732
+ }
3733
+ } else {
3734
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3735
+ $this->xml_encoding = 'ISO-8859-1';
3736
+ }
3737
+ } elseif(isset($_SERVER) && is_array($_SERVER)){
3738
+ $this->debug("In parse_http_headers, use _SERVER");
3739
+ foreach ($_SERVER as $k => $v) {
3740
+ if (substr($k, 0, 5) == 'HTTP_') {
3741
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
3742
+ } else {
3743
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
3744
+ }
3745
+ if ($k == 'soapaction') {
3746
+ // get SOAPAction header
3747
+ $k = 'SOAPAction';
3748
+ $v = str_replace('"', '', $v);
3749
+ $v = str_replace('\\', '', $v);
3750
+ $this->SOAPAction = $v;
3751
+ } else if ($k == 'content-type') {
3752
+ // get the character encoding of the incoming request
3753
+ if (strpos($v, '=')) {
3754
+ $enc = substr(strstr($v, '='), 1);
3755
+ $enc = str_replace('"', '', $enc);
3756
+ $enc = str_replace('\\', '', $enc);
3757
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3758
+ $this->xml_encoding = strtoupper($enc);
3759
+ } else {
3760
+ $this->xml_encoding = 'US-ASCII';
3761
+ }
3762
+ } else {
3763
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3764
+ $this->xml_encoding = 'ISO-8859-1';
3765
+ }
3766
+ }
3767
+ $this->headers[$k] = $v;
3768
+ $this->request .= "$k: $v\r\n";
3769
+ $this->debug("$k: $v");
3770
+ }
3771
+ } elseif (is_array($HTTP_SERVER_VARS)) {
3772
+ $this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
3773
+ foreach ($HTTP_SERVER_VARS as $k => $v) {
3774
+ if (substr($k, 0, 5) == 'HTTP_') {
3775
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
3776
+ } else {
3777
+ $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
3778
+ }
3779
+ if ($k == 'soapaction') {
3780
+ // get SOAPAction header
3781
+ $k = 'SOAPAction';
3782
+ $v = str_replace('"', '', $v);
3783
+ $v = str_replace('\\', '', $v);
3784
+ $this->SOAPAction = $v;
3785
+ } else if ($k == 'content-type') {
3786
+ // get the character encoding of the incoming request
3787
+ if (strpos($v, '=')) {
3788
+ $enc = substr(strstr($v, '='), 1);
3789
+ $enc = str_replace('"', '', $enc);
3790
+ $enc = str_replace('\\', '', $enc);
3791
+ if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
3792
+ $this->xml_encoding = strtoupper($enc);
3793
+ } else {
3794
+ $this->xml_encoding = 'US-ASCII';
3795
+ }
3796
+ } else {
3797
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
3798
+ $this->xml_encoding = 'ISO-8859-1';
3799
+ }
3800
+ }
3801
+ $this->headers[$k] = $v;
3802
+ $this->request .= "$k: $v\r\n";
3803
+ $this->debug("$k: $v");
3804
+ }
3805
+ } else {
3806
+ $this->debug("In parse_http_headers, HTTP headers not accessible");
3807
+ $this->setError("HTTP headers not accessible");
3808
+ }
3809
+ }
3810
+
3811
+ /**
3812
+ * parses a request
3813
+ *
3814
+ * The following fields are set by this function (when successful)
3815
+ *
3816
+ * headers
3817
+ * request
3818
+ * xml_encoding
3819
+ * SOAPAction
3820
+ * request
3821
+ * requestSOAP
3822
+ * methodURI
3823
+ * methodname
3824
+ * methodparams
3825
+ * requestHeaders
3826
+ * document
3827
+ *
3828
+ * This sets the fault field on error
3829
+ *
3830
+ * @param string $data XML string
3831
+ * @access private
3832
+ */
3833
+ function parse_request($data='') {
3834
+ $this->debug('entering parse_request()');
3835
+ $this->parse_http_headers();
3836
+ $this->debug('got character encoding: '.$this->xml_encoding);
3837
+ // uncompress if necessary
3838
+ if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
3839
+ $this->debug('got content encoding: ' . $this->headers['content-encoding']);
3840
+ if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
3841
+ // if decoding works, use it. else assume data wasn't gzencoded
3842
+ if (function_exists('gzuncompress')) {
3843
+ if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
3844
+ $data = $degzdata;
3845
+ } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
3846
+ $data = $degzdata;
3847
+ } else {
3848
+ $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
3849
+ return;
3850
+ }
3851
+ } else {
3852
+ $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
3853
+ return;
3854
+ }
3855
+ }
3856
+ }
3857
+ $this->request .= "\r\n".$data;
3858
+ $data = $this->parseRequest($this->headers, $data);
3859
+ $this->requestSOAP = $data;
3860
+ $this->debug('leaving parse_request');
3861
+ }
3862
+
3863
+ /**
3864
+ * invokes a PHP function for the requested SOAP method
3865
+ *
3866
+ * The following fields are set by this function (when successful)
3867
+ *
3868
+ * methodreturn
3869
+ *
3870
+ * Note that the PHP function that is called may also set the following
3871
+ * fields to affect the response sent to the client
3872
+ *
3873
+ * responseHeaders
3874
+ * outgoing_headers
3875
+ *
3876
+ * This sets the fault field on error
3877
+ *
3878
+ * @access private
3879
+ */
3880
+ function invoke_method() {
3881
+ $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
3882
+
3883
+ if ($this->wsdl) {
3884
+ if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
3885
+ $this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
3886
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3887
+ } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
3888
+ // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
3889
+ $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
3890
+ $this->appendDebug('opData=' . $this->varDump($this->opData));
3891
+ $this->methodname = $this->opData['name'];
3892
+ } else {
3893
+ $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
3894
+ $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
3895
+ return;
3896
+ }
3897
+ } else {
3898
+ $this->debug('in invoke_method, no WSDL to validate method');
3899
+ }
3900
+
3901
+ // if a . is present in $this->methodname, we see if there is a class in scope,
3902
+ // which could be referred to. We will also distinguish between two deliminators,
3903
+ // to allow methods to be called a the class or an instance
3904
+ $class = '';
3905
+ $method = '';
3906
+ if (strpos($this->methodname, '..') > 0) {
3907
+ $delim = '..';
3908
+ } else if (strpos($this->methodname, '.') > 0) {
3909
+ $delim = '.';
3910
+ } else {
3911
+ $delim = '';
3912
+ }
3913
+
3914
+ if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
3915
+ class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
3916
+ // get the class and method name
3917
+ $class = substr($this->methodname, 0, strpos($this->methodname, $delim));
3918
+ $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
3919
+ $this->debug("in invoke_method, class=$class method=$method delim=$delim");
3920
+ }
3921
+
3922
+ // does method exist?
3923
+ if ($class == '') {
3924
+ if (!function_exists($this->methodname)) {
3925
+ $this->debug("in invoke_method, function '$this->methodname' not found!");
3926
+ $this->result = 'fault: method not found';
3927
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3928
+ return;
3929
+ }
3930
+ } else {
3931
+ $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
3932
+ if (!in_array($method_to_compare, get_class_methods($class))) {
3933
+ $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
3934
+ $this->result = 'fault: method not found';
3935
+ $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
3936
+ return;
3937
+ }
3938
+ }
3939
+
3940
+ // evaluate message, getting back parameters
3941
+ // verify that request parameters match the method's signature
3942
+ if(! $this->verify_method($this->methodname,$this->methodparams)){
3943
+ // debug
3944
+ $this->debug('ERROR: request not verified against method signature');
3945
+ $this->result = 'fault: request failed validation against method signature';
3946
+ // return fault
3947
+ $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
3948
+ return;
3949
+ }
3950
+
3951
+ // if there are parameters to pass
3952
+ $this->debug('in invoke_method, params:');
3953
+ $this->appendDebug($this->varDump($this->methodparams));
3954
+ $this->debug("in invoke_method, calling '$this->methodname'");
3955
+ if (!function_exists('call_user_func_array')) {
3956
+ if ($class == '') {
3957
+ $this->debug('in invoke_method, calling function using eval()');
3958
+ $funcCall = "\$this->methodreturn = $this->methodname(";
3959
+ } else {
3960
+ if ($delim == '..') {
3961
+ $this->debug('in invoke_method, calling class method using eval()');
3962
+ $funcCall = "\$this->methodreturn = ".$class."::".$method."(";
3963
+ } else {
3964
+ $this->debug('in invoke_method, calling instance method using eval()');
3965
+ // generate unique instance name
3966
+ $instname = "\$inst_".time();
3967
+ $funcCall = $instname." = new ".$class."(); ";
3968
+ $funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
3969
+ }
3970
+ }
3971
+ if ($this->methodparams) {
3972
+ foreach ($this->methodparams as $param) {
3973
+ if (is_array($param) || is_object($param)) {
3974
+ $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
3975
+ return;
3976
+ }
3977
+ $funcCall .= "\"$param\",";
3978
+ }
3979
+ $funcCall = substr($funcCall, 0, -1);
3980
+ }
3981
+ $funcCall .= ');';
3982
+ $this->debug('in invoke_method, function call: '.$funcCall);
3983
+ @eval($funcCall);
3984
+ } else {
3985
+ if ($class == '') {
3986
+ $this->debug('in invoke_method, calling function using call_user_func_array()');
3987
+ $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
3988
+ } elseif ($delim == '..') {
3989
+ $this->debug('in invoke_method, calling class method using call_user_func_array()');
3990
+ $call_arg = array ($class, $method);
3991
+ } else {
3992
+ $this->debug('in invoke_method, calling instance method using call_user_func_array()');
3993
+ $instance = new $class ();
3994
+ $call_arg = array(&$instance, $method);
3995
+ }
3996
+ if (is_array($this->methodparams)) {
3997
+ $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
3998
+ } else {
3999
+ $this->methodreturn = call_user_func_array($call_arg, array());
4000
+ }
4001
+ }
4002
+ $this->debug('in invoke_method, methodreturn:');
4003
+ $this->appendDebug($this->varDump($this->methodreturn));
4004
+ $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
4005
+ }
4006
+
4007
+ /**
4008
+ * serializes the return value from a PHP function into a full SOAP Envelope
4009
+ *
4010
+ * The following fields are set by this function (when successful)
4011
+ *
4012
+ * responseSOAP
4013
+ *
4014
+ * This sets the fault field on error
4015
+ *
4016
+ * @access private
4017
+ */
4018
+ function serialize_return() {
4019
+ $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
4020
+ // if fault
4021
+ if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
4022
+ $this->debug('got a fault object from method');
4023
+ $this->fault = $this->methodreturn;
4024
+ return;
4025
+ } elseif ($this->methodreturnisliteralxml) {
4026
+ $return_val = $this->methodreturn;
4027
+ // returned value(s)
4028
+ } else {
4029
+ $this->debug('got a(n) '.gettype($this->methodreturn).' from method');
4030
+ $this->debug('serializing return value');
4031
+ if($this->wsdl){
4032
+ if (sizeof($this->opData['output']['parts']) > 1) {
4033
+ $this->debug('more than one output part, so use the method return unchanged');
4034
+ $opParams = $this->methodreturn;
4035
+ } elseif (sizeof($this->opData['output']['parts']) == 1) {
4036
+ $this->debug('exactly one output part, so wrap the method return in a simple array');
4037
+ // TODO: verify that it is not already wrapped!
4038
+ //foreach ($this->opData['output']['parts'] as $name => $type) {
4039
+ // $this->debug('wrap in element named ' . $name);
4040
+ //}
4041
+ $opParams = array($this->methodreturn);
4042
+ }
4043
+ $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
4044
+ $this->appendDebug($this->wsdl->getDebug());
4045
+ $this->wsdl->clearDebug();
4046
+ if($errstr = $this->wsdl->getError()){
4047
+ $this->debug('got wsdl error: '.$errstr);
4048
+ $this->fault('SOAP-ENV:Server', 'unable to serialize result');
4049
+ return;
4050
+ }
4051
+ } else {
4052
+ if (isset($this->methodreturn)) {
4053
+ $return_val = $this->serialize_val($this->methodreturn, 'return');
4054
+ } else {
4055
+ $return_val = '';
4056
+ $this->debug('in absence of WSDL, assume void return for backward compatibility');
4057
+ }
4058
+ }
4059
+ }
4060
+ $this->debug('return value:');
4061
+ $this->appendDebug($this->varDump($return_val));
4062
+
4063
+ $this->debug('serializing response');
4064
+ if ($this->wsdl) {
4065
+ $this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
4066
+ if ($this->opData['style'] == 'rpc') {
4067
+ $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
4068
+ if ($this->opData['output']['use'] == 'literal') {
4069
+ // 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
4070
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4071
+ } else {
4072
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4073
+ }
4074
+ } else {
4075
+ $this->debug('style is not rpc for serialization: assume document');
4076
+ $payload = $return_val;
4077
+ }
4078
+ } else {
4079
+ $this->debug('do not have WSDL for serialization: assume rpc/encoded');
4080
+ $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
4081
+ }
4082
+ $this->result = 'successful';
4083
+ if($this->wsdl){
4084
+ //if($this->debug_flag){
4085
+ $this->appendDebug($this->wsdl->getDebug());
4086
+ // }
4087
+ if (isset($opData['output']['encodingStyle'])) {
4088
+ $encodingStyle = $opData['output']['encodingStyle'];
4089
+ } else {
4090
+ $encodingStyle = '';
4091
+ }
4092
+ // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
4093
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
4094
+ } else {
4095
+ $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
4096
+ }
4097
+ $this->debug("Leaving serialize_return");
4098
+ }
4099
+
4100
+ /**
4101
+ * sends an HTTP response
4102
+ *
4103
+ * The following fields are set by this function (when successful)
4104
+ *
4105
+ * outgoing_headers
4106
+ * response
4107
+ *
4108
+ * @access private
4109
+ */
4110
+ function send_response() {
4111
+ $this->debug('Enter send_response');
4112
+ if ($this->fault) {
4113
+ $payload = $this->fault->serialize();
4114
+ $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
4115
+ $this->outgoing_headers[] = "Status: 500 Internal Server Error";
4116
+ } else {
4117
+ $payload = $this->responseSOAP;
4118
+ // Some combinations of PHP+Web server allow the Status
4119
+ // to come through as a header. Since OK is the default
4120
+ // just do nothing.
4121
+ // $this->outgoing_headers[] = "HTTP/1.0 200 OK";
4122
+ // $this->outgoing_headers[] = "Status: 200 OK";
4123
+ }
4124
+ // add debug data if in debug mode
4125
+ if(isset($this->debug_flag) && $this->debug_flag){
4126
+ $payload .= $this->getDebugAsXMLComment();
4127
+ }
4128
+ $this->outgoing_headers[] = "Server: $this->title Server v$this->version";
4129
+ ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
4130
+ $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")";
4131
+ // Let the Web server decide about this
4132
+ //$this->outgoing_headers[] = "Connection: Close\r\n";
4133
+ $payload = $this->getHTTPBody($payload);
4134
+ $type = $this->getHTTPContentType();
4135
+ $charset = $this->getHTTPContentTypeCharset();
4136
+ $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
4137
+ //begin code to compress payload - by John
4138
+ // NOTE: there is no way to know whether the Web server will also compress
4139
+ // this data.
4140
+ if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
4141
+ if (strstr($this->headers['accept-encoding'], 'gzip')) {
4142
+ if (function_exists('gzencode')) {
4143
+ if (isset($this->debug_flag) && $this->debug_flag) {
4144
+ $payload .= "<!-- Content being gzipped -->";
4145
+ }
4146
+ $this->outgoing_headers[] = "Content-Encoding: gzip";
4147
+ $payload = gzencode($payload);
4148
+ } else {
4149
+ if (isset($this->debug_flag) && $this->debug_flag) {
4150
+ $payload .= "<!-- Content will not be gzipped: no gzencode -->";
4151
+ }
4152
+ }
4153
+ } elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
4154
+ // Note: MSIE requires gzdeflate output (no Zlib header and checksum),
4155
+ // instead of gzcompress output,
4156
+ // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
4157
+ if (function_exists('gzdeflate')) {
4158
+ if (isset($this->debug_flag) && $this->debug_flag) {
4159
+ $payload .= "<!-- Content being deflated -->";
4160
+ }
4161
+ $this->outgoing_headers[] = "Content-Encoding: deflate";
4162
+ $payload = gzdeflate($payload);
4163
+ } else {
4164
+ if (isset($this->debug_flag) && $this->debug_flag) {
4165
+ $payload .= "<!-- Content will not be deflated: no gzcompress -->";
4166
+ }
4167
+ }
4168
+ }
4169
+ }
4170
+ //end code
4171
+ $this->outgoing_headers[] = "Content-Length: ".strlen($payload);
4172
+ reset($this->outgoing_headers);
4173
+ foreach($this->outgoing_headers as $hdr){
4174
+ header($hdr, false);
4175
+ }
4176
+ print $payload;
4177
+ $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload;
4178
+ }
4179
+
4180
+ /**
4181
+ * takes the value that was created by parsing the request
4182
+ * and compares to the method's signature, if available.
4183
+ *
4184
+ * @param string $operation The operation to be invoked
4185
+ * @param array $request The array of parameter values
4186
+ * @return boolean Whether the operation was found
4187
+ * @access private
4188
+ */
4189
+ function verify_method($operation,$request){
4190
+ if(isset($this->wsdl) && is_object($this->wsdl)){
4191
+ if($this->wsdl->getOperationData($operation)){
4192
+ return true;
4193
+ }
4194
+ } elseif(isset($this->operations[$operation])){
4195
+ return true;
4196
+ }
4197
+ return false;
4198
+ }
4199
+
4200
+ /**
4201
+ * processes SOAP message received from client
4202
+ *
4203
+ * @param array $headers The HTTP headers
4204
+ * @param string $data unprocessed request data from client
4205
+ * @return mixed value of the message, decoded into a PHP type
4206
+ * @access private
4207
+ */
4208
+ function parseRequest($headers, $data) {
4209
+ $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
4210
+ if (!strstr($headers['content-type'], 'text/xml')) {
4211
+ $this->setError('Request not of type text/xml');
4212
+ return false;
4213
+ }
4214
+ if (strpos($headers['content-type'], '=')) {
4215
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
4216
+ $this->debug('Got response encoding: ' . $enc);
4217
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
4218
+ $this->xml_encoding = strtoupper($enc);
4219
+ } else {
4220
+ $this->xml_encoding = 'US-ASCII';
4221
+ }
4222
+ } else {
4223
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
4224
+ $this->xml_encoding = 'ISO-8859-1';
4225
+ }
4226
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
4227
+ // parse response, get soap parser obj
4228
+ $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8);
4229
+ // parser debug
4230
+ $this->debug("parser debug: \n".$parser->getDebug());
4231
+ // if fault occurred during message parsing
4232
+ if($err = $parser->getError()){
4233
+ $this->result = 'fault: error in msg parsing: '.$err;
4234
+ $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err);
4235
+ // else successfully parsed request into soapval object
4236
+ } else {
4237
+ // get/set methodname
4238
+ $this->methodURI = $parser->root_struct_namespace;
4239
+ $this->methodname = $parser->root_struct_name;
4240
+ $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI);
4241
+ $this->debug('calling parser->get_soapbody()');
4242
+ $this->methodparams = $parser->get_soapbody();
4243
+ // get SOAP headers
4244
+ $this->requestHeaders = $parser->getHeaders();
4245
+ // get SOAP Header
4246
+ $this->requestHeader = $parser->get_soapheader();
4247
+ // add document for doclit support
4248
+ $this->document = $parser->document;
4249
+ }
4250
+ }
4251
+
4252
+ /**
4253
+ * gets the HTTP body for the current response.
4254
+ *
4255
+ * @param string $soapmsg The SOAP payload
4256
+ * @return string The HTTP body, which includes the SOAP payload
4257
+ * @access private
4258
+ */
4259
+ function getHTTPBody($soapmsg) {
4260
+ return $soapmsg;
4261
+ }
4262
+
4263
+ /**
4264
+ * gets the HTTP content type for the current response.
4265
+ *
4266
+ * Note: getHTTPBody must be called before this.
4267
+ *
4268
+ * @return string the HTTP content type for the current response.
4269
+ * @access private
4270
+ */
4271
+ function getHTTPContentType() {
4272
+ return 'text/xml';
4273
+ }
4274
+
4275
+ /**
4276
+ * gets the HTTP content type charset for the current response.
4277
+ * returns false for non-text content types.
4278
+ *
4279
+ * Note: getHTTPBody must be called before this.
4280
+ *
4281
+ * @return string the HTTP content type charset for the current response.
4282
+ * @access private
4283
+ */
4284
+ function getHTTPContentTypeCharset() {
4285
+ return $this->soap_defencoding;
4286
+ }
4287
+
4288
+ /**
4289
+ * add a method to the dispatch map (this has been replaced by the register method)
4290
+ *
4291
+ * @param string $methodname
4292
+ * @param string $in array of input values
4293
+ * @param string $out array of output values
4294
+ * @access public
4295
+ * @deprecated
4296
+ */
4297
+ function add_to_map($methodname,$in,$out){
4298
+ $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out);
4299
+ }
4300
+
4301
+ /**
4302
+ * register a service function with the server
4303
+ *
4304
+ * @param string $name the name of the PHP function, class.method or class..method
4305
+ * @param array $in assoc array of input values: key = param name, value = param type
4306
+ * @param array $out assoc array of output values: key = param name, value = param type
4307
+ * @param mixed $namespace the element namespace for the method or false
4308
+ * @param mixed $soapaction the soapaction for the method or false
4309
+ * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
4310
+ * @param mixed $use optional (encoded|literal) or false
4311
+ * @param string $documentation optional Description to include in WSDL
4312
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
4313
+ * @access public
4314
+ */
4315
+ function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){
4316
+ global $HTTP_SERVER_VARS;
4317
+
4318
+ if($this->externalWSDLURL){
4319
+ die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
4320
+ }
4321
+ if (! $name) {
4322
+ die('You must specify a name when you register an operation');
4323
+ }
4324
+ if (!is_array($in)) {
4325
+ die('You must provide an array for operation inputs');
4326
+ }
4327
+ if (!is_array($out)) {
4328
+ die('You must provide an array for operation outputs');
4329
+ }
4330
+ if(false == $namespace) {
4331
+ }
4332
+ if(false == $soapaction) {
4333
+ if (isset($_SERVER)) {
4334
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4335
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4336
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4337
+ } elseif (isset($HTTP_SERVER_VARS)) {
4338
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4339
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4340
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4341
+ } else {
4342
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4343
+ }
4344
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4345
+ $SCHEME = 'https';
4346
+ } else {
4347
+ $SCHEME = 'http';
4348
+ }
4349
+ $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
4350
+ }
4351
+ if(false == $style) {
4352
+ $style = "rpc";
4353
+ }
4354
+ if(false == $use) {
4355
+ $use = "encoded";
4356
+ }
4357
+ if ($use == 'encoded' && $encodingStyle = '') {
4358
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
4359
+ }
4360
+
4361
+ $this->operations[$name] = array(
4362
+ 'name' => $name,
4363
+ 'in' => $in,
4364
+ 'out' => $out,
4365
+ 'namespace' => $namespace,
4366
+ 'soapaction' => $soapaction,
4367
+ 'style' => $style);
4368
+ if($this->wsdl){
4369
+ $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle);
4370
+ }
4371
+ return true;
4372
+ }
4373
+
4374
+ /**
4375
+ * Specify a fault to be returned to the client.
4376
+ * This also acts as a flag to the server that a fault has occured.
4377
+ *
4378
+ * @param string $faultcode
4379
+ * @param string $faultstring
4380
+ * @param string $faultactor
4381
+ * @param string $faultdetail
4382
+ * @access public
4383
+ */
4384
+ function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){
4385
+ if ($faultdetail == '' && $this->debug_flag) {
4386
+ $faultdetail = $this->getDebug();
4387
+ }
4388
+ $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail);
4389
+ $this->fault->soap_defencoding = $this->soap_defencoding;
4390
+ }
4391
+
4392
+ /**
4393
+ * Sets up wsdl object.
4394
+ * Acts as a flag to enable internal WSDL generation
4395
+ *
4396
+ * @param string $serviceName, name of the service
4397
+ * @param mixed $namespace optional 'tns' service namespace or false
4398
+ * @param mixed $endpoint optional URL of service endpoint or false
4399
+ * @param string $style optional (rpc|document) WSDL style (also specified by operation)
4400
+ * @param string $transport optional SOAP transport
4401
+ * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
4402
+ */
4403
+ function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
4404
+ {
4405
+ global $HTTP_SERVER_VARS;
4406
+
4407
+ if (isset($_SERVER)) {
4408
+ $SERVER_NAME = $_SERVER['SERVER_NAME'];
4409
+ $SERVER_PORT = $_SERVER['SERVER_PORT'];
4410
+ $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
4411
+ $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
4412
+ } elseif (isset($HTTP_SERVER_VARS)) {
4413
+ $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
4414
+ $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
4415
+ $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
4416
+ $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
4417
+ } else {
4418
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
4419
+ }
4420
+ // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
4421
+ $colon = strpos($SERVER_NAME,":");
4422
+ if ($colon) {
4423
+ $SERVER_NAME = substr($SERVER_NAME, 0, $colon);
4424
+ }
4425
+ if ($SERVER_PORT == 80) {
4426
+ $SERVER_PORT = '';
4427
+ } else {
4428
+ $SERVER_PORT = ':' . $SERVER_PORT;
4429
+ }
4430
+ if(false == $namespace) {
4431
+ $namespace = "http://$SERVER_NAME/soap/$serviceName";
4432
+ }
4433
+
4434
+ if(false == $endpoint) {
4435
+ if ($HTTPS == '1' || $HTTPS == 'on') {
4436
+ $SCHEME = 'https';
4437
+ } else {
4438
+ $SCHEME = 'http';
4439
+ }
4440
+ $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
4441
+ }
4442
+
4443
+ if(false == $schemaTargetNamespace) {
4444
+ $schemaTargetNamespace = $namespace;
4445
+ }
4446
+
4447
+ $this->wsdl = new wsdl;
4448
+ $this->wsdl->serviceName = $serviceName;
4449
+ $this->wsdl->endpoint = $endpoint;
4450
+ $this->wsdl->namespaces['tns'] = $namespace;
4451
+ $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
4452
+ $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
4453
+ if ($schemaTargetNamespace != $namespace) {
4454
+ $this->wsdl->namespaces['types'] = $schemaTargetNamespace;
4455
+ }
4456
+ $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
4457
+ if ($style == 'document') {
4458
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
4459
+ }
4460
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
4461
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
4462
+ $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
4463
+ $this->wsdl->bindings[$serviceName.'Binding'] = array(
4464
+ 'name'=>$serviceName.'Binding',
4465
+ 'style'=>$style,
4466
+ 'transport'=>$transport,
4467
+ 'portType'=>$serviceName.'PortType');
4468
+ $this->wsdl->ports[$serviceName.'Port'] = array(
4469
+ 'binding'=>$serviceName.'Binding',
4470
+ 'location'=>$endpoint,
4471
+ 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/');
4472
+ }
4473
+ }
4474
+
4475
+ /**
4476
+ * Backward compatibility
4477
+ */
4478
+ class soap_server extends nusoap_server {
4479
+ }
4480
+
4481
+ ?><?php
4482
+
4483
+
4484
+
4485
+ /**
4486
+ * parses a WSDL file, allows access to it's data, other utility methods.
4487
+ * also builds WSDL structures programmatically.
4488
+ *
4489
+ * @author Dietrich Ayala <dietrich@ganx4.com>
4490
+ * @author Scott Nichol <snichol@users.sourceforge.net>
4491
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
4492
+ * @access public
4493
+ */
4494
+ class wsdl extends nusoap_base {
4495
+ // URL or filename of the root of this WSDL
4496
+ var $wsdl;
4497
+ // define internal arrays of bindings, ports, operations, messages, etc.
4498
+ var $schemas = array();
4499
+ var $currentSchema;
4500
+ var $message = array();
4501
+ var $complexTypes = array();
4502
+ var $messages = array();
4503
+ var $currentMessage;
4504
+ var $currentOperation;
4505
+ var $portTypes = array();
4506
+ var $currentPortType;
4507
+ var $bindings = array();
4508
+ var $currentBinding;
4509
+ var $ports = array();
4510
+ var $currentPort;
4511
+ var $opData = array();
4512
+ var $status = '';
4513
+ var $documentation = false;
4514
+ var $endpoint = '';
4515
+ // array of wsdl docs to import
4516
+ var $import = array();
4517
+ // parser vars
4518
+ var $parser;
4519
+ var $position = 0;
4520
+ var $depth = 0;
4521
+ var $depth_array = array();
4522
+ // for getting wsdl
4523
+ var $proxyhost = '';
4524
+ var $proxyport = '';
4525
+ var $proxyusername = '';
4526
+ var $proxypassword = '';
4527
+ var $timeout = 0;
4528
+ var $response_timeout = 30;
4529
+ var $curl_options = array(); // User-specified cURL options
4530
+ var $use_curl = false; // whether to always try to use cURL
4531
+ // for HTTP authentication
4532
+ var $username = ''; // Username for HTTP authentication
4533
+ var $password = ''; // Password for HTTP authentication
4534
+ var $authtype = ''; // Type of HTTP authentication
4535
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
4536
+
4537
+ /**
4538
+ * constructor
4539
+ *
4540
+ * @param string $wsdl WSDL document URL
4541
+ * @param string $proxyhost
4542
+ * @param string $proxyport
4543
+ * @param string $proxyusername
4544
+ * @param string $proxypassword
4545
+ * @param integer $timeout set the connection timeout
4546
+ * @param integer $response_timeout set the response timeout
4547
+ * @param array $curl_options user-specified cURL options
4548
+ * @param boolean $use_curl try to use cURL
4549
+ * @access public
4550
+ */
4551
+ function wsdl($wsdl = '',$proxyhost=false,$proxyport=false,$proxyusername=false,$proxypassword=false,$timeout=0,$response_timeout=30,$curl_options=null,$use_curl=false){
4552
+ parent::nusoap_base();
4553
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
4554
+ $this->proxyhost = $proxyhost;
4555
+ $this->proxyport = $proxyport;
4556
+ $this->proxyusername = $proxyusername;
4557
+ $this->proxypassword = $proxypassword;
4558
+ $this->timeout = $timeout;
4559
+ $this->response_timeout = $response_timeout;
4560
+ if (is_array($curl_options))
4561
+ $this->curl_options = $curl_options;
4562
+ $this->use_curl = $use_curl;
4563
+ $this->fetchWSDL($wsdl);
4564
+ }
4565
+
4566
+ /**
4567
+ * fetches the WSDL document and parses it
4568
+ *
4569
+ * @access public
4570
+ */
4571
+ function fetchWSDL($wsdl) {
4572
+ $this->debug("parse and process WSDL path=$wsdl");
4573
+ $this->wsdl = $wsdl;
4574
+ // parse wsdl file
4575
+ if ($this->wsdl != "") {
4576
+ $this->parseWSDL($this->wsdl);
4577
+ }
4578
+ // imports
4579
+ // TODO: handle imports more properly, grabbing them in-line and nesting them
4580
+ $imported_urls = array();
4581
+ $imported = 1;
4582
+ while ($imported > 0) {
4583
+ $imported = 0;
4584
+ // Schema imports
4585
+ foreach ($this->schemas as $ns => $list) {
4586
+ foreach ($list as $xs) {
4587
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4588
+ foreach ($xs->imports as $ns2 => $list2) {
4589
+ for ($ii = 0; $ii < count($list2); $ii++) {
4590
+ if (! $list2[$ii]['loaded']) {
4591
+ $this->schemas[$ns]->imports[$ns2][$ii]['loaded'] = true;
4592
+ $url = $list2[$ii]['location'];
4593
+ if ($url != '') {
4594
+ $urlparts = parse_url($url);
4595
+ if (!isset($urlparts['host'])) {
4596
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' .$wsdlparts['port'] : '') .
4597
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4598
+ }
4599
+ if (! in_array($url, $imported_urls)) {
4600
+ $this->parseWSDL($url);
4601
+ $imported++;
4602
+ $imported_urls[] = $url;
4603
+ }
4604
+ } else {
4605
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4606
+ }
4607
+ }
4608
+ }
4609
+ }
4610
+ }
4611
+ }
4612
+ // WSDL imports
4613
+ $wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
4614
+ foreach ($this->import as $ns => $list) {
4615
+ for ($ii = 0; $ii < count($list); $ii++) {
4616
+ if (! $list[$ii]['loaded']) {
4617
+ $this->import[$ns][$ii]['loaded'] = true;
4618
+ $url = $list[$ii]['location'];
4619
+ if ($url != '') {
4620
+ $urlparts = parse_url($url);
4621
+ if (!isset($urlparts['host'])) {
4622
+ $url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
4623
+ substr($wsdlparts['path'],0,strrpos($wsdlparts['path'],'/') + 1) .$urlparts['path'];
4624
+ }
4625
+ if (! in_array($url, $imported_urls)) {
4626
+ $this->parseWSDL($url);
4627
+ $imported++;
4628
+ $imported_urls[] = $url;
4629
+ }
4630
+ } else {
4631
+ $this->debug("Unexpected scenario: empty URL for unloaded import");
4632
+ }
4633
+ }
4634
+ }
4635
+ }
4636
+ }
4637
+ // add new data to operation data
4638
+ foreach($this->bindings as $binding => $bindingData) {
4639
+ if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
4640
+ foreach($bindingData['operations'] as $operation => $data) {
4641
+ $this->debug('post-parse data gathering for ' . $operation);
4642
+ $this->bindings[$binding]['operations'][$operation]['input'] =
4643
+ isset($this->bindings[$binding]['operations'][$operation]['input']) ?
4644
+ array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[ $bindingData['portType'] ][$operation]['input']) :
4645
+ $this->portTypes[ $bindingData['portType'] ][$operation]['input'];
4646
+ $this->bindings[$binding]['operations'][$operation]['output'] =
4647
+ isset($this->bindings[$binding]['operations'][$operation]['output']) ?
4648
+ array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[ $bindingData['portType'] ][$operation]['output']) :
4649
+ $this->portTypes[ $bindingData['portType'] ][$operation]['output'];
4650
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ])){
4651
+ $this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['input']['message'] ];
4652
+ }
4653
+ if(isset($this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ])){
4654
+ $this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[ $this->bindings[$binding]['operations'][$operation]['output']['message'] ];
4655
+ }
4656
+ // Set operation style if necessary, but do not override one already provided
4657
+ if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
4658
+ $this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
4659
+ }
4660
+ $this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
4661
+ $this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[ $bindingData['portType'] ][$operation]['documentation']) ? $this->portTypes[ $bindingData['portType'] ][$operation]['documentation'] : '';
4662
+ $this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
4663
+ }
4664
+ }
4665
+ }
4666
+ }
4667
+
4668
+ /**
4669
+ * parses the wsdl document
4670
+ *
4671
+ * @param string $wsdl path or URL
4672
+ * @access private
4673
+ */
4674
+ function parseWSDL($wsdl = '') {
4675
+ $this->debug("parse WSDL at path=$wsdl");
4676
+
4677
+ if ($wsdl == '') {
4678
+ $this->debug('no wsdl passed to parseWSDL()!!');
4679
+ $this->setError('no wsdl passed to parseWSDL()!!');
4680
+ return false;
4681
+ }
4682
+
4683
+ // parse $wsdl for url format
4684
+ $wsdl_props = parse_url($wsdl);
4685
+
4686
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
4687
+ $this->debug('getting WSDL http(s) URL ' . $wsdl);
4688
+ // get wsdl
4689
+ $tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
4690
+ $tr->request_method = 'GET';
4691
+ $tr->useSOAPAction = false;
4692
+ if($this->proxyhost && $this->proxyport){
4693
+ $tr->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
4694
+ }
4695
+ if ($this->authtype != '') {
4696
+ $tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
4697
+ }
4698
+ $tr->setEncoding('gzip, deflate');
4699
+ $wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
4700
+ //$this->debug("WSDL request\n" . $tr->outgoing_payload);
4701
+ //$this->debug("WSDL response\n" . $tr->incoming_payload);
4702
+ $this->appendDebug($tr->getDebug());
4703
+ // catch errors
4704
+ if($err = $tr->getError() ){
4705
+ $errstr = 'HTTP ERROR: '.$err;
4706
+ $this->debug($errstr);
4707
+ $this->setError($errstr);
4708
+ unset($tr);
4709
+ return false;
4710
+ }
4711
+ unset($tr);
4712
+ $this->debug("got WSDL URL");
4713
+ } else {
4714
+ // $wsdl is not http(s), so treat it as a file URL or plain file path
4715
+ if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
4716
+ $path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
4717
+ } else {
4718
+ $path = $wsdl;
4719
+ }
4720
+ $this->debug('getting WSDL file ' . $path);
4721
+ if ($fp = @fopen($path, 'r')) {
4722
+ $wsdl_string = '';
4723
+ while ($data = fread($fp, 32768)) {
4724
+ $wsdl_string .= $data;
4725
+ }
4726
+ fclose($fp);
4727
+ } else {
4728
+ $errstr = "Bad path to WSDL file $path";
4729
+ $this->debug($errstr);
4730
+ $this->setError($errstr);
4731
+ return false;
4732
+ }
4733
+ }
4734
+ $this->debug('Parse WSDL');
4735
+ // end new code added
4736
+ // Create an XML parser.
4737
+ $this->parser = xml_parser_create();
4738
+ // Set the options for parsing the XML data.
4739
+ // xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
4740
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
4741
+ // Set the object for the parser.
4742
+ xml_set_object($this->parser, $this);
4743
+ // Set the element handlers for the parser.
4744
+ xml_set_element_handler($this->parser, 'start_element', 'end_element');
4745
+ xml_set_character_data_handler($this->parser, 'character_data');
4746
+ // Parse the XML file.
4747
+ if (!xml_parse($this->parser, $wsdl_string, true)) {
4748
+ // Display an error message.
4749
+ $errstr = sprintf(
4750
+ 'XML error parsing WSDL from %s on line %d: %s',
4751
+ $wsdl,
4752
+ xml_get_current_line_number($this->parser),
4753
+ xml_error_string(xml_get_error_code($this->parser))
4754
+ );
4755
+ $this->debug($errstr);
4756
+ $this->debug("XML payload:\n" . $wsdl_string);
4757
+ $this->setError($errstr);
4758
+ return false;
4759
+ }
4760
+ // free the parser
4761
+ xml_parser_free($this->parser);
4762
+ $this->debug('Parsing WSDL done');
4763
+ // catch wsdl parse errors
4764
+ if($this->getError()){
4765
+ return false;
4766
+ }
4767
+ return true;
4768
+ }
4769
+
4770
+ /**
4771
+ * start-element handler
4772
+ *
4773
+ * @param string $parser XML parser object
4774
+ * @param string $name element name
4775
+ * @param string $attrs associative array of attributes
4776
+ * @access private
4777
+ */
4778
+ function start_element($parser, $name, $attrs)
4779
+ {
4780
+ if ($this->status == 'schema') {
4781
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4782
+ $this->appendDebug($this->currentSchema->getDebug());
4783
+ $this->currentSchema->clearDebug();
4784
+ } elseif (ereg('schema$', $name)) {
4785
+ $this->debug('Parsing WSDL schema');
4786
+ // $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
4787
+ $this->status = 'schema';
4788
+ $this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
4789
+ $this->currentSchema->schemaStartElement($parser, $name, $attrs);
4790
+ $this->appendDebug($this->currentSchema->getDebug());
4791
+ $this->currentSchema->clearDebug();
4792
+ } else {
4793
+ // position in the total number of elements, starting from 0
4794
+ $pos = $this->position++;
4795
+ $depth = $this->depth++;
4796
+ // set self as current value for this depth
4797
+ $this->depth_array[$depth] = $pos;
4798
+ $this->message[$pos] = array('cdata' => '');
4799
+ // process attributes
4800
+ if (count($attrs) > 0) {
4801
+ // register namespace declarations
4802
+ foreach($attrs as $k => $v) {
4803
+ if (ereg("^xmlns", $k)) {
4804
+ if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
4805
+ $this->namespaces[$ns_prefix] = $v;
4806
+ } else {
4807
+ $this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
4808
+ }
4809
+ if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
4810
+ $this->XMLSchemaVersion = $v;
4811
+ $this->namespaces['xsi'] = $v . '-instance';
4812
+ }
4813
+ }
4814
+ }
4815
+ // expand each attribute prefix to its namespace
4816
+ foreach($attrs as $k => $v) {
4817
+ $k = strpos($k, ':') ? $this->expandQname($k) : $k;
4818
+ if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
4819
+ $v = strpos($v, ':') ? $this->expandQname($v) : $v;
4820
+ }
4821
+ $eAttrs[$k] = $v;
4822
+ }
4823
+ $attrs = $eAttrs;
4824
+ } else {
4825
+ $attrs = array();
4826
+ }
4827
+ // get element prefix, namespace and name
4828
+ if (ereg(':', $name)) {
4829
+ // get ns prefix
4830
+ $prefix = substr($name, 0, strpos($name, ':'));
4831
+ // get ns
4832
+ $namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
4833
+ // get unqualified name
4834
+ $name = substr(strstr($name, ':'), 1);
4835
+ }
4836
+ // process attributes, expanding any prefixes to namespaces
4837
+ // find status, register data
4838
+ switch ($this->status) {
4839
+ case 'message':
4840
+ if ($name == 'part') {
4841
+ if (isset($attrs['type'])) {
4842
+ $this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
4843
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
4844
+ }
4845
+ if (isset($attrs['element'])) {
4846
+ $this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
4847
+ $this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
4848
+ }
4849
+ }
4850
+ break;
4851
+ case 'portType':
4852
+ switch ($name) {
4853
+ case 'operation':
4854
+ $this->currentPortOperation = $attrs['name'];
4855
+ $this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
4856
+ if (isset($attrs['parameterOrder'])) {
4857
+ $this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
4858
+ }
4859
+ break;
4860
+ case 'documentation':
4861
+ $this->documentation = true;
4862
+ break;
4863
+ // merge input/output data
4864
+ default:
4865
+ $m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
4866
+ $this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
4867
+ break;
4868
+ }
4869
+ break;
4870
+ case 'binding':
4871
+ switch ($name) {
4872
+ case 'binding':
4873
+ // get ns prefix
4874
+ if (isset($attrs['style'])) {
4875
+ $this->bindings[$this->currentBinding]['prefix'] = $prefix;
4876
+ }
4877
+ $this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
4878
+ break;
4879
+ case 'header':
4880
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
4881
+ break;
4882
+ case 'operation':
4883
+ if (isset($attrs['soapAction'])) {
4884
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
4885
+ }
4886
+ if (isset($attrs['style'])) {
4887
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
4888
+ }
4889
+ if (isset($attrs['name'])) {
4890
+ $this->currentOperation = $attrs['name'];
4891
+ $this->debug("current binding operation: $this->currentOperation");
4892
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
4893
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
4894
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
4895
+ }
4896
+ break;
4897
+ case 'input':
4898
+ $this->opStatus = 'input';
4899
+ break;
4900
+ case 'output':
4901
+ $this->opStatus = 'output';
4902
+ break;
4903
+ case 'body':
4904
+ if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
4905
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
4906
+ } else {
4907
+ $this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
4908
+ }
4909
+ break;
4910
+ }
4911
+ break;
4912
+ case 'service':
4913
+ switch ($name) {
4914
+ case 'port':
4915
+ $this->currentPort = $attrs['name'];
4916
+ $this->debug('current port: ' . $this->currentPort);
4917
+ $this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
4918
+
4919
+ break;
4920
+ case 'address':
4921
+ $this->ports[$this->currentPort]['location'] = $attrs['location'];
4922
+ $this->ports[$this->currentPort]['bindingType'] = $namespace;
4923
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['bindingType'] = $namespace;
4924
+ $this->bindings[ $this->ports[$this->currentPort]['binding'] ]['endpoint'] = $attrs['location'];
4925
+ break;
4926
+ }
4927
+ break;
4928
+ }
4929
+ // set status
4930
+ switch ($name) {
4931
+ case 'import':
4932
+ if (isset($attrs['location'])) {
4933
+ $this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
4934
+ $this->debug('parsing import ' . $attrs['namespace']. ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]).')');
4935
+ } else {
4936
+ $this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
4937
+ if (! $this->getPrefixFromNamespace($attrs['namespace'])) {
4938
+ $this->namespaces['ns'.(count($this->namespaces)+1)] = $attrs['namespace'];
4939
+ }
4940
+ $this->debug('parsing import ' . $attrs['namespace']. ' - [no location] (' . count($this->import[$attrs['namespace']]).')');
4941
+ }
4942
+ break;
4943
+ //wait for schema
4944
+ //case 'types':
4945
+ // $this->status = 'schema';
4946
+ // break;
4947
+ case 'message':
4948
+ $this->status = 'message';
4949
+ $this->messages[$attrs['name']] = array();
4950
+ $this->currentMessage = $attrs['name'];
4951
+ break;
4952
+ case 'portType':
4953
+ $this->status = 'portType';
4954
+ $this->portTypes[$attrs['name']] = array();
4955
+ $this->currentPortType = $attrs['name'];
4956
+ break;
4957
+ case "binding":
4958
+ if (isset($attrs['name'])) {
4959
+ // get binding name
4960
+ if (strpos($attrs['name'], ':')) {
4961
+ $this->currentBinding = $this->getLocalPart($attrs['name']);
4962
+ } else {
4963
+ $this->currentBinding = $attrs['name'];
4964
+ }
4965
+ $this->status = 'binding';
4966
+ $this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
4967
+ $this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
4968
+ }
4969
+ break;
4970
+ case 'service':
4971
+ $this->serviceName = $attrs['name'];
4972
+ $this->status = 'service';
4973
+ $this->debug('current service: ' . $this->serviceName);
4974
+ break;
4975
+ case 'definitions':
4976
+ foreach ($attrs as $name => $value) {
4977
+ $this->wsdl_info[$name] = $value;
4978
+ }
4979
+ break;
4980
+ }
4981
+ }
4982
+ }
4983
+
4984
+ /**
4985
+ * end-element handler
4986
+ *
4987
+ * @param string $parser XML parser object
4988
+ * @param string $name element name
4989
+ * @access private
4990
+ */
4991
+ function end_element($parser, $name){
4992
+ // unset schema status
4993
+ if (/*ereg('types$', $name) ||*/ ereg('schema$', $name)) {
4994
+ $this->status = "";
4995
+ $this->appendDebug($this->currentSchema->getDebug());
4996
+ $this->currentSchema->clearDebug();
4997
+ $this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
4998
+ $this->debug('Parsing WSDL schema done');
4999
+ }
5000
+ if ($this->status == 'schema') {
5001
+ $this->currentSchema->schemaEndElement($parser, $name);
5002
+ } else {
5003
+ // bring depth down a notch
5004
+ $this->depth--;
5005
+ }
5006
+ // end documentation
5007
+ if ($this->documentation) {
5008
+ //TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
5009
+ //$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
5010
+ $this->documentation = false;
5011
+ }
5012
+ }
5013
+
5014
+ /**
5015
+ * element content handler
5016
+ *
5017
+ * @param string $parser XML parser object
5018
+ * @param string $data element content
5019
+ * @access private
5020
+ */
5021
+ function character_data($parser, $data)
5022
+ {
5023
+ $pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
5024
+ if (isset($this->message[$pos]['cdata'])) {
5025
+ $this->message[$pos]['cdata'] .= $data;
5026
+ }
5027
+ if ($this->documentation) {
5028
+ $this->documentation .= $data;
5029
+ }
5030
+ }
5031
+
5032
+ /**
5033
+ * if authenticating, set user credentials here
5034
+ *
5035
+ * @param string $username
5036
+ * @param string $password
5037
+ * @param string $authtype (basic|digest|certificate|ntlm)
5038
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
5039
+ * @access public
5040
+ */
5041
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
5042
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
5043
+ $this->appendDebug($this->varDump($certRequest));
5044
+ $this->username = $username;
5045
+ $this->password = $password;
5046
+ $this->authtype = $authtype;
5047
+ $this->certRequest = $certRequest;
5048
+ }
5049
+
5050
+ function getBindingData($binding)
5051
+ {
5052
+ if (is_array($this->bindings[$binding])) {
5053
+ return $this->bindings[$binding];
5054
+ }
5055
+ }
5056
+
5057
+ /**
5058
+ * returns an assoc array of operation names => operation data
5059
+ *
5060
+ * @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
5061
+ * @return array
5062
+ * @access public
5063
+ */
5064
+ function getOperations($bindingType = 'soap') {
5065
+ $ops = array();
5066
+ if ($bindingType == 'soap') {
5067
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5068
+ } elseif ($bindingType == 'soap12') {
5069
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5070
+ }
5071
+ // loop thru ports
5072
+ foreach($this->ports as $port => $portData) {
5073
+ // binding type of port matches parameter
5074
+ if ($portData['bindingType'] == $bindingType) {
5075
+ //$this->debug("getOperations for port $port");
5076
+ //$this->debug("port data: " . $this->varDump($portData));
5077
+ //$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
5078
+ // merge bindings
5079
+ if (isset($this->bindings[ $portData['binding'] ]['operations'])) {
5080
+ $ops = array_merge ($ops, $this->bindings[ $portData['binding'] ]['operations']);
5081
+ }
5082
+ }
5083
+ }
5084
+ return $ops;
5085
+ }
5086
+
5087
+ /**
5088
+ * returns an associative array of data necessary for calling an operation
5089
+ *
5090
+ * @param string $operation name of operation
5091
+ * @param string $bindingType type of binding eg: soap, soap12
5092
+ * @return array
5093
+ * @access public
5094
+ */
5095
+ function getOperationData($operation, $bindingType = 'soap')
5096
+ {
5097
+ if ($bindingType == 'soap') {
5098
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5099
+ } elseif ($bindingType == 'soap12') {
5100
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5101
+ }
5102
+ // loop thru ports
5103
+ foreach($this->ports as $port => $portData) {
5104
+ // binding type of port matches parameter
5105
+ if ($portData['bindingType'] == $bindingType) {
5106
+ // get binding
5107
+ //foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5108
+ foreach(array_keys($this->bindings[ $portData['binding'] ]['operations']) as $bOperation) {
5109
+ // note that we could/should also check the namespace here
5110
+ if ($operation == $bOperation) {
5111
+ $opData = $this->bindings[ $portData['binding'] ]['operations'][$operation];
5112
+ return $opData;
5113
+ }
5114
+ }
5115
+ }
5116
+ }
5117
+ }
5118
+
5119
+ /**
5120
+ * returns an associative array of data necessary for calling an operation
5121
+ *
5122
+ * @param string $soapAction soapAction for operation
5123
+ * @param string $bindingType type of binding eg: soap, soap12
5124
+ * @return array
5125
+ * @access public
5126
+ */
5127
+ function getOperationDataForSoapAction($soapAction, $bindingType = 'soap') {
5128
+ if ($bindingType == 'soap') {
5129
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
5130
+ } elseif ($bindingType == 'soap12') {
5131
+ $bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
5132
+ }
5133
+ // loop thru ports
5134
+ foreach($this->ports as $port => $portData) {
5135
+ // binding type of port matches parameter
5136
+ if ($portData['bindingType'] == $bindingType) {
5137
+ // loop through operations for the binding
5138
+ foreach ($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
5139
+ if ($opData['soapAction'] == $soapAction) {
5140
+ return $opData;
5141
+ }
5142
+ }
5143
+ }
5144
+ }
5145
+ }
5146
+
5147
+ /**
5148
+ * returns an array of information about a given type
5149
+ * returns false if no type exists by the given name
5150
+ *
5151
+ * typeDef = array(
5152
+ * 'elements' => array(), // refs to elements array
5153
+ * 'restrictionBase' => '',
5154
+ * 'phpType' => '',
5155
+ * 'order' => '(sequence|all)',
5156
+ * 'attrs' => array() // refs to attributes array
5157
+ * )
5158
+ *
5159
+ * @param string $type the type
5160
+ * @param string $ns namespace (not prefix) of the type
5161
+ * @return mixed
5162
+ * @access public
5163
+ * @see nusoap_xmlschema
5164
+ */
5165
+ function getTypeDef($type, $ns) {
5166
+ $this->debug("in getTypeDef: type=$type, ns=$ns");
5167
+ if ((! $ns) && isset($this->namespaces['tns'])) {
5168
+ $ns = $this->namespaces['tns'];
5169
+ $this->debug("in getTypeDef: type namespace forced to $ns");
5170
+ }
5171
+ if (!isset($this->schemas[$ns])) {
5172
+ foreach ($this->schemas as $ns0 => $schema0) {
5173
+ if (strcasecmp($ns, $ns0) == 0) {
5174
+ $this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
5175
+ $ns = $ns0;
5176
+ break;
5177
+ }
5178
+ }
5179
+ }
5180
+ if (isset($this->schemas[$ns])) {
5181
+ $this->debug("in getTypeDef: have schema for namespace $ns");
5182
+ for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
5183
+ $xs = &$this->schemas[$ns][$i];
5184
+ $t = $xs->getTypeDef($type);
5185
+ //$this->appendDebug($xs->getDebug());
5186
+ //$xs->clearDebug();
5187
+ if ($t) {
5188
+ if (!isset($t['phpType'])) {
5189
+ // get info for type to tack onto the element
5190
+ $uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
5191
+ $ns = substr($t['type'], 0, strrpos($t['type'], ':'));
5192
+ $etype = $this->getTypeDef($uqType, $ns);
5193
+ if ($etype) {
5194
+ $this->debug("found type for [element] $type:");
5195
+ $this->debug($this->varDump($etype));
5196
+ if (isset($etype['phpType'])) {
5197
+ $t['phpType'] = $etype['phpType'];
5198
+ }
5199
+ if (isset($etype['elements'])) {
5200
+ $t['elements'] = $etype['elements'];
5201
+ }
5202
+ if (isset($etype['attrs'])) {
5203
+ $t['attrs'] = $etype['attrs'];
5204
+ }
5205
+ }
5206
+ }
5207
+ return $t;
5208
+ }
5209
+ }
5210
+ } else {
5211
+ $this->debug("in getTypeDef: do not have schema for namespace $ns");
5212
+ }
5213
+ return false;
5214
+ }
5215
+
5216
+ /**
5217
+ * prints html description of services
5218
+ *
5219
+ * @access private
5220
+ */
5221
+ function webDescription(){
5222
+ global $HTTP_SERVER_VARS;
5223
+
5224
+ if (isset($_SERVER)) {
5225
+ $PHP_SELF = $_SERVER['PHP_SELF'];
5226
+ } elseif (isset($HTTP_SERVER_VARS)) {
5227
+ $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
5228
+ } else {
5229
+ $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
5230
+ }
5231
+
5232
+ $b = '
5233
+ <html><head><title>NuSOAP: '.$this->serviceName.'</title>
5234
+ <style type="text/css">
5235
+ body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
5236
+ p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
5237
+ pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
5238
+ ul { margin-top: 10px; margin-left: 20px; }
5239
+ li { list-style-type: none; margin-top: 10px; color: #000000; }
5240
+ .content{
5241
+ margin-left: 0px; padding-bottom: 2em; }
5242
+ .nav {
5243
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
5244
+ margin-top: 10px; margin-left: 0px; color: #000000;
5245
+ background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
5246
+ .title {
5247
+ font-family: arial; font-size: 26px; color: #ffffff;
5248
+ background-color: #999999; width: 105%; margin-left: 0px;
5249
+ padding-top: 10px; padding-bottom: 10px; padding-left: 15px;}
5250
+ .hidden {
5251
+ position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
5252
+ font-family: arial; overflow: hidden; width: 600;
5253
+ padding: 20px; font-size: 10px; background-color: #999999;
5254
+ layer-background-color:#FFFFFF; }
5255
+ a,a:active { color: charcoal; font-weight: bold; }
5256
+ a:visited { color: #666666; font-weight: bold; }
5257
+ a:hover { color: cc3300; font-weight: bold; }
5258
+ </style>
5259
+ <script language="JavaScript" type="text/javascript">
5260
+ <!--
5261
+ // POP-UP CAPTIONS...
5262
+ function lib_bwcheck(){ //Browsercheck (needed)
5263
+ this.ver=navigator.appVersion
5264
+ this.agent=navigator.userAgent
5265
+ this.dom=document.getElementById?1:0
5266
+ this.opera5=this.agent.indexOf("Opera 5")>-1
5267
+ this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
5268
+ this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
5269
+ this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
5270
+ this.ie=this.ie4||this.ie5||this.ie6
5271
+ this.mac=this.agent.indexOf("Mac")>-1
5272
+ this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
5273
+ this.ns4=(document.layers && !this.dom)?1:0;
5274
+ this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
5275
+ return this
5276
+ }
5277
+ var bw = new lib_bwcheck()
5278
+ //Makes crossbrowser object.
5279
+ function makeObj(obj){
5280
+ this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
5281
+ if(!this.evnt) return false
5282
+ this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
5283
+ this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
5284
+ this.writeIt=b_writeIt;
5285
+ return this
5286
+ }
5287
+ // A unit of measure that will be added when setting the position of a layer.
5288
+ //var px = bw.ns4||window.opera?"":"px";
5289
+ function b_writeIt(text){
5290
+ if (bw.ns4){this.wref.write(text);this.wref.close()}
5291
+ else this.wref.innerHTML = text
5292
+ }
5293
+ //Shows the messages
5294
+ var oDesc;
5295
+ function popup(divid){
5296
+ if(oDesc = new makeObj(divid)){
5297
+ oDesc.css.visibility = "visible"
5298
+ }
5299
+ }
5300
+ function popout(){ // Hides message
5301
+ if(oDesc) oDesc.css.visibility = "hidden"
5302
+ }
5303
+ //-->
5304
+ </script>
5305
+ </head>
5306
+ <body>
5307
+ <div class=content>
5308
+ <br><br>
5309
+ <div class=title>'.$this->serviceName.'</div>
5310
+ <div class=nav>
5311
+ <p>View the <a href="'.$PHP_SELF.'?wsdl">WSDL</a> for the service.
5312
+ Click on an operation name to view it&apos;s details.</p>
5313
+ <ul>';
5314
+ foreach($this->getOperations() as $op => $data){
5315
+ $b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
5316
+ // create hidden div
5317
+ $b .= "<div id='$op' class='hidden'>
5318
+ <a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
5319
+ foreach($data as $donnie => $marie){ // loop through opdata
5320
+ if($donnie == 'input' || $donnie == 'output'){ // show input/output data
5321
+ $b .= "<font color='white'>".ucfirst($donnie).':</font><br>';
5322
+ foreach($marie as $captain => $tenille){ // loop through data
5323
+ if($captain == 'parts'){ // loop thru parts
5324
+ $b .= "&nbsp;&nbsp;$captain:<br>";
5325
+ //if(is_array($tenille)){
5326
+ foreach($tenille as $joanie => $chachi){
5327
+ $b .= "&nbsp;&nbsp;&nbsp;&nbsp;$joanie: $chachi<br>";
5328
+ }
5329
+ //}
5330
+ } else {
5331
+ $b .= "&nbsp;&nbsp;$captain: $tenille<br>";
5332
+ }
5333
+ }
5334
+ } else {
5335
+ $b .= "<font color='white'>".ucfirst($donnie).":</font> $marie<br>";
5336
+ }
5337
+ }
5338
+ $b .= '</div>';
5339
+ }
5340
+ $b .= '
5341
+ <ul>
5342
+ </div>
5343
+ </div></body></html>';
5344
+ return $b;
5345
+ }
5346
+
5347
+ /**
5348
+ * serialize the parsed wsdl
5349
+ *
5350
+ * @param mixed $debug whether to put debug=1 in endpoint URL
5351
+ * @return string serialization of WSDL
5352
+ * @access public
5353
+ */
5354
+ function serialize($debug = 0)
5355
+ {
5356
+ $xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
5357
+ $xml .= "\n<definitions";
5358
+ foreach($this->namespaces as $k => $v) {
5359
+ $xml .= " xmlns:$k=\"$v\"";
5360
+ }
5361
+ // 10.9.02 - add poulter fix for wsdl and tns declarations
5362
+ if (isset($this->namespaces['wsdl'])) {
5363
+ $xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
5364
+ }
5365
+ if (isset($this->namespaces['tns'])) {
5366
+ $xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
5367
+ }
5368
+ $xml .= '>';
5369
+ // imports
5370
+ if (sizeof($this->import) > 0) {
5371
+ foreach($this->import as $ns => $list) {
5372
+ foreach ($list as $ii) {
5373
+ if ($ii['location'] != '') {
5374
+ $xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
5375
+ } else {
5376
+ $xml .= '<import namespace="' . $ns . '" />';
5377
+ }
5378
+ }
5379
+ }
5380
+ }
5381
+ // types
5382
+ if (count($this->schemas)>=1) {
5383
+ $xml .= "\n<types>\n";
5384
+ foreach ($this->schemas as $ns => $list) {
5385
+ foreach ($list as $xs) {
5386
+ $xml .= $xs->serializeSchema();
5387
+ }
5388
+ }
5389
+ $xml .= '</types>';
5390
+ }
5391
+ // messages
5392
+ if (count($this->messages) >= 1) {
5393
+ foreach($this->messages as $msgName => $msgParts) {
5394
+ $xml .= "\n<message name=\"" . $msgName . '">';
5395
+ if(is_array($msgParts)){
5396
+ foreach($msgParts as $partName => $partType) {
5397
+ // print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
5398
+ if (strpos($partType, ':')) {
5399
+ $typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
5400
+ } elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
5401
+ // print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
5402
+ $typePrefix = 'xsd';
5403
+ } else {
5404
+ foreach($this->typemap as $ns => $types) {
5405
+ if (isset($types[$partType])) {
5406
+ $typePrefix = $this->getPrefixFromNamespace($ns);
5407
+ }
5408
+ }
5409
+ if (!isset($typePrefix)) {
5410
+ die("$partType has no namespace!");
5411
+ }
5412
+ }
5413
+ $ns = $this->getNamespaceFromPrefix($typePrefix);
5414
+ $localPart = $this->getLocalPart($partType);
5415
+ $typeDef = $this->getTypeDef($localPart, $ns);
5416
+ if ($typeDef['typeClass'] == 'element') {
5417
+ $elementortype = 'element';
5418
+ if (substr($localPart, -1) == '^') {
5419
+ $localPart = substr($localPart, 0, -1);
5420
+ }
5421
+ } else {
5422
+ $elementortype = 'type';
5423
+ }
5424
+ $xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
5425
+ }
5426
+ }
5427
+ $xml .= '</message>';
5428
+ }
5429
+ }
5430
+ // bindings & porttypes
5431
+ if (count($this->bindings) >= 1) {
5432
+ $binding_xml = '';
5433
+ $portType_xml = '';
5434
+ foreach($this->bindings as $bindingName => $attrs) {
5435
+ $binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
5436
+ $binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
5437
+ $portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
5438
+ foreach($attrs['operations'] as $opName => $opParts) {
5439
+ $binding_xml .= "\n" . ' <operation name="' . $opName . '">';
5440
+ $binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="'. $opParts['style'] . '"/>';
5441
+ if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
5442
+ $enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
5443
+ } else {
5444
+ $enc_style = '';
5445
+ }
5446
+ $binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
5447
+ if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
5448
+ $enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
5449
+ } else {
5450
+ $enc_style = '';
5451
+ }
5452
+ $binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
5453
+ $binding_xml .= "\n" . ' </operation>';
5454
+ $portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
5455
+ if (isset($opParts['parameterOrder'])) {
5456
+ $portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
5457
+ }
5458
+ $portType_xml .= '>';
5459
+ if(isset($opParts['documentation']) && $opParts['documentation'] != '') {
5460
+ $portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
5461
+ }
5462
+ $portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
5463
+ $portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
5464
+ $portType_xml .= "\n" . ' </operation>';
5465
+ }
5466
+ $portType_xml .= "\n" . '</portType>';
5467
+ $binding_xml .= "\n" . '</binding>';
5468
+ }
5469
+ $xml .= $portType_xml . $binding_xml;
5470
+ }
5471
+ // services
5472
+ $xml .= "\n<service name=\"" . $this->serviceName . '">';
5473
+ if (count($this->ports) >= 1) {
5474
+ foreach($this->ports as $pName => $attrs) {
5475
+ $xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
5476
+ $xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
5477
+ $xml .= "\n" . ' </port>';
5478
+ }
5479
+ }
5480
+ $xml .= "\n" . '</service>';
5481
+ return $xml . "\n</definitions>";
5482
+ }
5483
+
5484
+ /**
5485
+ * determine whether a set of parameters are unwrapped
5486
+ * when they are expect to be wrapped, Microsoft-style.
5487
+ *
5488
+ * @param string $type the type (element name) of the wrapper
5489
+ * @param array $parameters the parameter values for the SOAP call
5490
+ * @return boolean whether they parameters are unwrapped (and should be wrapped)
5491
+ * @access private
5492
+ */
5493
+ function parametersMatchWrapped($type, &$parameters) {
5494
+ $this->debug("in parametersMatchWrapped type=$type, parameters=");
5495
+ $this->appendDebug($this->varDump($parameters));
5496
+
5497
+ // split type into namespace:unqualified-type
5498
+ if (strpos($type, ':')) {
5499
+ $uqType = substr($type, strrpos($type, ':') + 1);
5500
+ $ns = substr($type, 0, strrpos($type, ':'));
5501
+ $this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
5502
+ if ($this->getNamespaceFromPrefix($ns)) {
5503
+ $ns = $this->getNamespaceFromPrefix($ns);
5504
+ $this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
5505
+ }
5506
+ } else {
5507
+ // TODO: should the type be compared to types in XSD, and the namespace
5508
+ // set to XSD if the type matches?
5509
+ $this->debug("in parametersMatchWrapped: No namespace for type $type");
5510
+ $ns = '';
5511
+ $uqType = $type;
5512
+ }
5513
+
5514
+ // get the type information
5515
+ if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
5516
+ $this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
5517
+ return false;
5518
+ }
5519
+ $this->debug("in parametersMatchWrapped: found typeDef=");
5520
+ $this->appendDebug($this->varDump($typeDef));
5521
+ if (substr($uqType, -1) == '^') {
5522
+ $uqType = substr($uqType, 0, -1);
5523
+ }
5524
+ $phpType = $typeDef['phpType'];
5525
+ $arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
5526
+ $this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
5527
+
5528
+ // we expect a complexType or element of complexType
5529
+ if ($phpType != 'struct') {
5530
+ $this->debug("in parametersMatchWrapped: not a struct");
5531
+ return false;
5532
+ }
5533
+
5534
+ // see whether the parameter names match the elements
5535
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
5536
+ $elements = 0;
5537
+ $matches = 0;
5538
+ $change = false;
5539
+ if ($this->isArraySimpleOrStruct($parameters) == 'arraySimple' && count($parameters) == count($typeDef['elements'])) {
5540
+ $this->debug("in parametersMatchWrapped: (wrapped return value kludge) correct number of elements in simple array, so change array and wrap");
5541
+ $change = true;
5542
+ }
5543
+ foreach ($typeDef['elements'] as $name => $attrs) {
5544
+ if ($change) {
5545
+ $this->debug("in parametersMatchWrapped: change parameter $element to name $name");
5546
+ $parameters[$name] = $parameters[$elements];
5547
+ unset($parameters[$elements]);
5548
+ $matches++;
5549
+ } elseif (isset($parameters[$name])) {
5550
+ $this->debug("in parametersMatchWrapped: have parameter named $name");
5551
+ $matches++;
5552
+ } else {
5553
+ $this->debug("in parametersMatchWrapped: do not have parameter named $name");
5554
+ }
5555
+ $elements++;
5556
+ }
5557
+
5558
+ $this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
5559
+ if ($matches == 0) {
5560
+ return false;
5561
+ }
5562
+ return true;
5563
+ }
5564
+
5565
+ // since there are no elements for the type, if the user passed no
5566
+ // parameters, the parameters match wrapped.
5567
+ $this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
5568
+ return count($parameters) == 0;
5569
+ }
5570
+
5571
+ /**
5572
+ * serialize PHP values according to a WSDL message definition
5573
+ * contrary to the method name, this is not limited to RPC
5574
+ *
5575
+ * TODO
5576
+ * - multi-ref serialization
5577
+ * - validate PHP values against type definitions, return errors if invalid
5578
+ *
5579
+ * @param string $operation operation name
5580
+ * @param string $direction (input|output)
5581
+ * @param mixed $parameters parameter value(s)
5582
+ * @param string $bindingType (soap|soap12)
5583
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5584
+ * @access public
5585
+ */
5586
+ function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap') {
5587
+ $this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
5588
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5589
+
5590
+ if ($direction != 'input' && $direction != 'output') {
5591
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5592
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5593
+ return false;
5594
+ }
5595
+ if (!$opData = $this->getOperationData($operation, $bindingType)) {
5596
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5597
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
5598
+ return false;
5599
+ }
5600
+ $this->debug('in serializeRPCParameters: opData:');
5601
+ $this->appendDebug($this->varDump($opData));
5602
+
5603
+ // Get encoding style for output and set to current
5604
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5605
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5606
+ $encodingStyle = $opData['output']['encodingStyle'];
5607
+ $enc_style = $encodingStyle;
5608
+ }
5609
+
5610
+ // set input params
5611
+ $xml = '';
5612
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5613
+ $parts = &$opData[$direction]['parts'];
5614
+ $part_count = sizeof($parts);
5615
+ $style = $opData['style'];
5616
+ $use = $opData[$direction]['use'];
5617
+ $this->debug("have $part_count part(s) to serialize using $style/$use");
5618
+ if (is_array($parameters)) {
5619
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5620
+ $parameter_count = count($parameters);
5621
+ $this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
5622
+ // check for Microsoft-style wrapped parameters
5623
+ if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
5624
+ $this->debug('check whether the caller has wrapped the parameters');
5625
+ if ((($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) || ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1)) {
5626
+ $this->debug('check whether caller\'s parameters match the wrapped ones');
5627
+ if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
5628
+ $this->debug('wrap the parameters for the caller');
5629
+ $parameters = array('parameters' => $parameters);
5630
+ $parameter_count = 1;
5631
+ }
5632
+ }
5633
+ }
5634
+ foreach ($parts as $name => $type) {
5635
+ $this->debug("serializing part $name of type $type");
5636
+ // Track encoding style
5637
+ if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5638
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5639
+ $enc_style = $encodingStyle;
5640
+ } else {
5641
+ $enc_style = false;
5642
+ }
5643
+ // NOTE: add error handling here
5644
+ // if serializeType returns false, then catch global error and fault
5645
+ if ($parametersArrayType == 'arraySimple') {
5646
+ $p = array_shift($parameters);
5647
+ $this->debug('calling serializeType w/indexed param');
5648
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5649
+ } elseif (isset($parameters[$name])) {
5650
+ $this->debug('calling serializeType w/named param');
5651
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5652
+ } else {
5653
+ // TODO: only send nillable
5654
+ $this->debug('calling serializeType w/null param');
5655
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5656
+ }
5657
+ }
5658
+ } else {
5659
+ $this->debug('no parameters passed.');
5660
+ }
5661
+ }
5662
+ $this->debug("serializeRPCParameters returning: $xml");
5663
+ return $xml;
5664
+ }
5665
+
5666
+ /**
5667
+ * serialize a PHP value according to a WSDL message definition
5668
+ *
5669
+ * TODO
5670
+ * - multi-ref serialization
5671
+ * - validate PHP values against type definitions, return errors if invalid
5672
+ *
5673
+ * @param string $operation operation name
5674
+ * @param string $direction (input|output)
5675
+ * @param mixed $parameters parameter value(s)
5676
+ * @return mixed parameters serialized as XML or false on error (e.g. operation not found)
5677
+ * @access public
5678
+ * @deprecated
5679
+ */
5680
+ function serializeParameters($operation, $direction, $parameters)
5681
+ {
5682
+ $this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
5683
+ $this->appendDebug('parameters=' . $this->varDump($parameters));
5684
+
5685
+ if ($direction != 'input' && $direction != 'output') {
5686
+ $this->debug('The value of the \$direction argument needs to be either "input" or "output"');
5687
+ $this->setError('The value of the \$direction argument needs to be either "input" or "output"');
5688
+ return false;
5689
+ }
5690
+ if (!$opData = $this->getOperationData($operation)) {
5691
+ $this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
5692
+ $this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
5693
+ return false;
5694
+ }
5695
+ $this->debug('opData:');
5696
+ $this->appendDebug($this->varDump($opData));
5697
+
5698
+ // Get encoding style for output and set to current
5699
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
5700
+ if(($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
5701
+ $encodingStyle = $opData['output']['encodingStyle'];
5702
+ $enc_style = $encodingStyle;
5703
+ }
5704
+
5705
+ // set input params
5706
+ $xml = '';
5707
+ if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
5708
+
5709
+ $use = $opData[$direction]['use'];
5710
+ $this->debug("use=$use");
5711
+ $this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
5712
+ if (is_array($parameters)) {
5713
+ $parametersArrayType = $this->isArraySimpleOrStruct($parameters);
5714
+ $this->debug('have ' . $parametersArrayType . ' parameters');
5715
+ foreach($opData[$direction]['parts'] as $name => $type) {
5716
+ $this->debug('serializing part "'.$name.'" of type "'.$type.'"');
5717
+ // Track encoding style
5718
+ if(isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
5719
+ $encodingStyle = $opData[$direction]['encodingStyle'];
5720
+ $enc_style = $encodingStyle;
5721
+ } else {
5722
+ $enc_style = false;
5723
+ }
5724
+ // NOTE: add error handling here
5725
+ // if serializeType returns false, then catch global error and fault
5726
+ if ($parametersArrayType == 'arraySimple') {
5727
+ $p = array_shift($parameters);
5728
+ $this->debug('calling serializeType w/indexed param');
5729
+ $xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
5730
+ } elseif (isset($parameters[$name])) {
5731
+ $this->debug('calling serializeType w/named param');
5732
+ $xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
5733
+ } else {
5734
+ // TODO: only send nillable
5735
+ $this->debug('calling serializeType w/null param');
5736
+ $xml .= $this->serializeType($name, $type, null, $use, $enc_style);
5737
+ }
5738
+ }
5739
+ } else {
5740
+ $this->debug('no parameters passed.');
5741
+ }
5742
+ }
5743
+ $this->debug("serializeParameters returning: $xml");
5744
+ return $xml;
5745
+ }
5746
+
5747
+ /**
5748
+ * serializes a PHP value according a given type definition
5749
+ *
5750
+ * @param string $name name of value (part or element)
5751
+ * @param string $type XML schema type of value (type or element)
5752
+ * @param mixed $value a native PHP value (parameter value)
5753
+ * @param string $use use for part (encoded|literal)
5754
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
5755
+ * @param boolean $unqualified a kludge for what should be XML namespace form handling
5756
+ * @return string value serialized as an XML string
5757
+ * @access private
5758
+ */
5759
+ function serializeType($name, $type, $value, $use='encoded', $encodingStyle=false, $unqualified=false)
5760
+ {
5761
+ $this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
5762
+ $this->appendDebug("value=" . $this->varDump($value));
5763
+ if($use == 'encoded' && $encodingStyle) {
5764
+ $encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
5765
+ }
5766
+
5767
+ // if a soapval has been supplied, let its type override the WSDL
5768
+ if (is_object($value) && get_class($value) == 'soapval') {
5769
+ if ($value->type_ns) {
5770
+ $type = $value->type_ns . ':' . $value->type;
5771
+ $forceType = true;
5772
+ $this->debug("in serializeType: soapval overrides type to $type");
5773
+ } elseif ($value->type) {
5774
+ $type = $value->type;
5775
+ $forceType = true;
5776
+ $this->debug("in serializeType: soapval overrides type to $type");
5777
+ } else {
5778
+ $forceType = false;
5779
+ $this->debug("in serializeType: soapval does not override type");
5780
+ }
5781
+ $attrs = $value->attributes;
5782
+ $value = $value->value;
5783
+ $this->debug("in serializeType: soapval overrides value to $value");
5784
+ if ($attrs) {
5785
+ if (!is_array($value)) {
5786
+ $value['!'] = $value;
5787
+ }
5788
+ foreach ($attrs as $n => $v) {
5789
+ $value['!' . $n] = $v;
5790
+ }
5791
+ $this->debug("in serializeType: soapval provides attributes");
5792
+ }
5793
+ } else {
5794
+ $forceType = false;
5795
+ }
5796
+
5797
+ $xml = '';
5798
+ if (strpos($type, ':')) {
5799
+ $uqType = substr($type, strrpos($type, ':') + 1);
5800
+ $ns = substr($type, 0, strrpos($type, ':'));
5801
+ $this->debug("in serializeType: got a prefixed type: $uqType, $ns");
5802
+ if ($this->getNamespaceFromPrefix($ns)) {
5803
+ $ns = $this->getNamespaceFromPrefix($ns);
5804
+ $this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
5805
+ }
5806
+
5807
+ if($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/'){
5808
+ $this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
5809
+ if ($unqualified && $use == 'literal') {
5810
+ $elementNS = " xmlns=\"\"";
5811
+ } else {
5812
+ $elementNS = '';
5813
+ }
5814
+ if (is_null($value)) {
5815
+ if ($use == 'literal') {
5816
+ // TODO: depends on minOccurs
5817
+ $xml = "<$name$elementNS/>";
5818
+ } else {
5819
+ // TODO: depends on nillable, which should be checked before calling this method
5820
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5821
+ }
5822
+ $this->debug("in serializeType: returning: $xml");
5823
+ return $xml;
5824
+ }
5825
+ if ($uqType == 'Array') {
5826
+ // JBoss/Axis does this sometimes
5827
+ return $this->serialize_val($value, $name, false, false, false, false, $use);
5828
+ }
5829
+ if ($uqType == 'boolean') {
5830
+ if ((is_string($value) && $value == 'false') || (! $value)) {
5831
+ $value = 'false';
5832
+ } else {
5833
+ $value = 'true';
5834
+ }
5835
+ }
5836
+ if ($uqType == 'string' && gettype($value) == 'string') {
5837
+ $value = $this->expandEntities($value);
5838
+ }
5839
+ if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
5840
+ $value = sprintf("%.0lf", $value);
5841
+ }
5842
+ // it's a scalar
5843
+ // TODO: what about null/nil values?
5844
+ // check type isn't a custom type extending xmlschema namespace
5845
+ if (!$this->getTypeDef($uqType, $ns)) {
5846
+ if ($use == 'literal') {
5847
+ if ($forceType) {
5848
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
5849
+ } else {
5850
+ $xml = "<$name$elementNS>$value</$name>";
5851
+ }
5852
+ } else {
5853
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
5854
+ }
5855
+ $this->debug("in serializeType: returning: $xml");
5856
+ return $xml;
5857
+ }
5858
+ $this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
5859
+ } else if ($ns == 'http://xml.apache.org/xml-soap') {
5860
+ $this->debug('in serializeType: appears to be Apache SOAP type');
5861
+ if ($uqType == 'Map') {
5862
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5863
+ if (! $tt_prefix) {
5864
+ $this->debug('in serializeType: Add namespace for Apache SOAP type');
5865
+ $tt_prefix = 'ns' . rand(1000, 9999);
5866
+ $this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
5867
+ // force this to be added to usedNamespaces
5868
+ $tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
5869
+ }
5870
+ $contents = '';
5871
+ foreach($value as $k => $v) {
5872
+ $this->debug("serializing map element: key $k, value $v");
5873
+ $contents .= '<item>';
5874
+ $contents .= $this->serialize_val($k,'key',false,false,false,false,$use);
5875
+ $contents .= $this->serialize_val($v,'value',false,false,false,false,$use);
5876
+ $contents .= '</item>';
5877
+ }
5878
+ if ($use == 'literal') {
5879
+ if ($forceType) {
5880
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
5881
+ } else {
5882
+ $xml = "<$name>$contents</$name>";
5883
+ }
5884
+ } else {
5885
+ $xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
5886
+ }
5887
+ $this->debug("in serializeType: returning: $xml");
5888
+ return $xml;
5889
+ }
5890
+ $this->debug('in serializeType: Apache SOAP type, but only support Map');
5891
+ }
5892
+ } else {
5893
+ // TODO: should the type be compared to types in XSD, and the namespace
5894
+ // set to XSD if the type matches?
5895
+ $this->debug("in serializeType: No namespace for type $type");
5896
+ $ns = '';
5897
+ $uqType = $type;
5898
+ }
5899
+ if(!$typeDef = $this->getTypeDef($uqType, $ns)){
5900
+ $this->setError("$type ($uqType) is not a supported type.");
5901
+ $this->debug("in serializeType: $type ($uqType) is not a supported type.");
5902
+ return false;
5903
+ } else {
5904
+ $this->debug("in serializeType: found typeDef");
5905
+ $this->appendDebug('typeDef=' . $this->varDump($typeDef));
5906
+ if (substr($uqType, -1) == '^') {
5907
+ $uqType = substr($uqType, 0, -1);
5908
+ }
5909
+ }
5910
+ $phpType = $typeDef['phpType'];
5911
+ $this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '') );
5912
+ // if php type == struct, map value to the <all> element names
5913
+ if ($phpType == 'struct') {
5914
+ if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
5915
+ $elementName = $uqType;
5916
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5917
+ $elementNS = " xmlns=\"$ns\"";
5918
+ } else {
5919
+ $elementNS = " xmlns=\"\"";
5920
+ }
5921
+ } else {
5922
+ $elementName = $name;
5923
+ if ($unqualified) {
5924
+ $elementNS = " xmlns=\"\"";
5925
+ } else {
5926
+ $elementNS = '';
5927
+ }
5928
+ }
5929
+ if (is_null($value)) {
5930
+ if ($use == 'literal') {
5931
+ // TODO: depends on minOccurs
5932
+ $xml = "<$elementName$elementNS/>";
5933
+ } else {
5934
+ $xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
5935
+ }
5936
+ $this->debug("in serializeType: returning: $xml");
5937
+ return $xml;
5938
+ }
5939
+ if (is_object($value)) {
5940
+ $value = get_object_vars($value);
5941
+ }
5942
+ if (is_array($value)) {
5943
+ $elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
5944
+ if ($use == 'literal') {
5945
+ if ($forceType) {
5946
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
5947
+ } else {
5948
+ $xml = "<$elementName$elementNS$elementAttrs>";
5949
+ }
5950
+ } else {
5951
+ $xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
5952
+ }
5953
+
5954
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
5955
+ $xml .= "</$elementName>";
5956
+ } else {
5957
+ $this->debug("in serializeType: phpType is struct, but value is not an array");
5958
+ $this->setError("phpType is struct, but value is not an array: see debug output for details");
5959
+ $xml = '';
5960
+ }
5961
+ } elseif ($phpType == 'array') {
5962
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
5963
+ $elementNS = " xmlns=\"$ns\"";
5964
+ } else {
5965
+ if ($unqualified) {
5966
+ $elementNS = " xmlns=\"\"";
5967
+ } else {
5968
+ $elementNS = '';
5969
+ }
5970
+ }
5971
+ if (is_null($value)) {
5972
+ if ($use == 'literal') {
5973
+ // TODO: depends on minOccurs
5974
+ $xml = "<$name$elementNS/>";
5975
+ } else {
5976
+ $xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
5977
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
5978
+ ":Array\" " .
5979
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
5980
+ ':arrayType="' .
5981
+ $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
5982
+ ':' .
5983
+ $this->getLocalPart($typeDef['arrayType'])."[0]\"/>";
5984
+ }
5985
+ $this->debug("in serializeType: returning: $xml");
5986
+ return $xml;
5987
+ }
5988
+ if (isset($typeDef['multidimensional'])) {
5989
+ $nv = array();
5990
+ foreach($value as $v) {
5991
+ $cols = ',' . sizeof($v);
5992
+ $nv = array_merge($nv, $v);
5993
+ }
5994
+ $value = $nv;
5995
+ } else {
5996
+ $cols = '';
5997
+ }
5998
+ if (is_array($value) && sizeof($value) >= 1) {
5999
+ $rows = sizeof($value);
6000
+ $contents = '';
6001
+ foreach($value as $k => $v) {
6002
+ $this->debug("serializing array element: $k, $v of type: $typeDef[arrayType]");
6003
+ //if (strpos($typeDef['arrayType'], ':') ) {
6004
+ if (!in_array($typeDef['arrayType'],$this->typemap['http://www.w3.org/2001/XMLSchema'])) {
6005
+ $contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
6006
+ } else {
6007
+ $contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
6008
+ }
6009
+ }
6010
+ } else {
6011
+ $rows = 0;
6012
+ $contents = null;
6013
+ }
6014
+ // TODO: for now, an empty value will be serialized as a zero element
6015
+ // array. Revisit this when coding the handling of null/nil values.
6016
+ if ($use == 'literal') {
6017
+ $xml = "<$name$elementNS>"
6018
+ .$contents
6019
+ ."</$name>";
6020
+ } else {
6021
+ $xml = "<$name$elementNS xsi:type=\"".$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/').':Array" '.
6022
+ $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
6023
+ .':arrayType="'
6024
+ .$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
6025
+ .":".$this->getLocalPart($typeDef['arrayType'])."[$rows$cols]\">"
6026
+ .$contents
6027
+ ."</$name>";
6028
+ }
6029
+ } elseif ($phpType == 'scalar') {
6030
+ if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
6031
+ $elementNS = " xmlns=\"$ns\"";
6032
+ } else {
6033
+ if ($unqualified) {
6034
+ $elementNS = " xmlns=\"\"";
6035
+ } else {
6036
+ $elementNS = '';
6037
+ }
6038
+ }
6039
+ if ($use == 'literal') {
6040
+ if ($forceType) {
6041
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
6042
+ } else {
6043
+ $xml = "<$name$elementNS>$value</$name>";
6044
+ }
6045
+ } else {
6046
+ $xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
6047
+ }
6048
+ }
6049
+ $this->debug("in serializeType: returning: $xml");
6050
+ return $xml;
6051
+ }
6052
+
6053
+ /**
6054
+ * serializes the attributes for a complexType
6055
+ *
6056
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6057
+ * @param mixed $value a native PHP value (parameter value)
6058
+ * @param string $ns the namespace of the type
6059
+ * @param string $uqType the local part of the type
6060
+ * @return string value serialized as an XML string
6061
+ * @access private
6062
+ */
6063
+ function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType) {
6064
+ $xml = '';
6065
+ if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
6066
+ $this->debug("serialize attributes for XML Schema type $ns:$uqType");
6067
+ if (is_array($value)) {
6068
+ $xvalue = $value;
6069
+ } elseif (is_object($value)) {
6070
+ $xvalue = get_object_vars($value);
6071
+ } else {
6072
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6073
+ $xvalue = array();
6074
+ }
6075
+ foreach ($typeDef['attrs'] as $aName => $attrs) {
6076
+ if (isset($xvalue['!' . $aName])) {
6077
+ $xname = '!' . $aName;
6078
+ $this->debug("value provided for attribute $aName with key $xname");
6079
+ } elseif (isset($xvalue[$aName])) {
6080
+ $xname = $aName;
6081
+ $this->debug("value provided for attribute $aName with key $xname");
6082
+ } elseif (isset($attrs['default'])) {
6083
+ $xname = '!' . $aName;
6084
+ $xvalue[$xname] = $attrs['default'];
6085
+ $this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
6086
+ } else {
6087
+ $xname = '';
6088
+ $this->debug("no value provided for attribute $aName");
6089
+ }
6090
+ if ($xname) {
6091
+ $xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
6092
+ }
6093
+ }
6094
+ } else {
6095
+ $this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
6096
+ }
6097
+ if (isset($typeDef['extensionBase'])) {
6098
+ $ns = $this->getPrefix($typeDef['extensionBase']);
6099
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
6100
+ if ($this->getNamespaceFromPrefix($ns)) {
6101
+ $ns = $this->getNamespaceFromPrefix($ns);
6102
+ }
6103
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6104
+ $this->debug("serialize attributes for extension base $ns:$uqType");
6105
+ $xml .= $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
6106
+ } else {
6107
+ $this->debug("extension base $ns:$uqType is not a supported type");
6108
+ }
6109
+ }
6110
+ return $xml;
6111
+ }
6112
+
6113
+ /**
6114
+ * serializes the elements for a complexType
6115
+ *
6116
+ * @param array $typeDef our internal representation of an XML schema type (or element)
6117
+ * @param mixed $value a native PHP value (parameter value)
6118
+ * @param string $ns the namespace of the type
6119
+ * @param string $uqType the local part of the type
6120
+ * @param string $use use for part (encoded|literal)
6121
+ * @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
6122
+ * @return string value serialized as an XML string
6123
+ * @access private
6124
+ */
6125
+ function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use='encoded', $encodingStyle=false) {
6126
+ $xml = '';
6127
+ if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
6128
+ $this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
6129
+ if (is_array($value)) {
6130
+ $xvalue = $value;
6131
+ } elseif (is_object($value)) {
6132
+ $xvalue = get_object_vars($value);
6133
+ } else {
6134
+ $this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
6135
+ $xvalue = array();
6136
+ }
6137
+ // toggle whether all elements are present - ideally should validate against schema
6138
+ if (count($typeDef['elements']) != count($xvalue)){
6139
+ $optionals = true;
6140
+ }
6141
+ foreach ($typeDef['elements'] as $eName => $attrs) {
6142
+ if (!isset($xvalue[$eName])) {
6143
+ if (isset($attrs['default'])) {
6144
+ $xvalue[$eName] = $attrs['default'];
6145
+ $this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
6146
+ }
6147
+ }
6148
+ // if user took advantage of a minOccurs=0, then only serialize named parameters
6149
+ if (isset($optionals)
6150
+ && (!isset($xvalue[$eName]))
6151
+ && ( (!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
6152
+ ){
6153
+ if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
6154
+ $this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
6155
+ }
6156
+ // do nothing
6157
+ $this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
6158
+ } else {
6159
+ // get value
6160
+ if (isset($xvalue[$eName])) {
6161
+ $v = $xvalue[$eName];
6162
+ } else {
6163
+ $v = null;
6164
+ }
6165
+ if (isset($attrs['form'])) {
6166
+ $unqualified = ($attrs['form'] == 'unqualified');
6167
+ } else {
6168
+ $unqualified = false;
6169
+ }
6170
+ if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
6171
+ $vv = $v;
6172
+ foreach ($vv as $k => $v) {
6173
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6174
+ // serialize schema-defined type
6175
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6176
+ } else {
6177
+ // serialize generic type (can this ever really happen?)
6178
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6179
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6180
+ }
6181
+ }
6182
+ } else {
6183
+ if (isset($attrs['type']) || isset($attrs['ref'])) {
6184
+ // serialize schema-defined type
6185
+ $xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
6186
+ } else {
6187
+ // serialize generic type (can this ever really happen?)
6188
+ $this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
6189
+ $xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
6190
+ }
6191
+ }
6192
+ }
6193
+ }
6194
+ } else {
6195
+ $this->debug("no elements to serialize for XML Schema type $ns:$uqType");
6196
+ }
6197
+ if (isset($typeDef['extensionBase'])) {
6198
+ $ns = $this->getPrefix($typeDef['extensionBase']);
6199
+ $uqType = $this->getLocalPart($typeDef['extensionBase']);
6200
+ if ($this->getNamespaceFromPrefix($ns)) {
6201
+ $ns = $this->getNamespaceFromPrefix($ns);
6202
+ }
6203
+ if ($typeDef = $this->getTypeDef($uqType, $ns)) {
6204
+ $this->debug("serialize elements for extension base $ns:$uqType");
6205
+ $xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
6206
+ } else {
6207
+ $this->debug("extension base $ns:$uqType is not a supported type");
6208
+ }
6209
+ }
6210
+ return $xml;
6211
+ }
6212
+
6213
+ /**
6214
+ * adds an XML Schema complex type to the WSDL types
6215
+ *
6216
+ * @param string $name
6217
+ * @param string $typeClass (complexType|simpleType|attribute)
6218
+ * @param string $phpType currently supported are array and struct (php assoc array)
6219
+ * @param string $compositor (all|sequence|choice)
6220
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6221
+ * @param array $elements e.g. array ( name => array(name=>'',type=>'') )
6222
+ * @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
6223
+ * @param string $arrayType as namespace:name (xsd:string)
6224
+ * @see nusoap_xmlschema
6225
+ * @access public
6226
+ */
6227
+ function addComplexType($name,$typeClass='complexType',$phpType='array',$compositor='',$restrictionBase='',$elements=array(),$attrs=array(),$arrayType='') {
6228
+ if (count($elements) > 0) {
6229
+ $eElements = array();
6230
+ foreach($elements as $n => $e){
6231
+ // expand each element
6232
+ $ee = array();
6233
+ foreach ($e as $k => $v) {
6234
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6235
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6236
+ $ee[$k] = $v;
6237
+ }
6238
+ $eElements[$n] = $ee;
6239
+ }
6240
+ $elements = $eElements;
6241
+ }
6242
+
6243
+ if (count($attrs) > 0) {
6244
+ foreach($attrs as $n => $a){
6245
+ // expand each attribute
6246
+ foreach ($a as $k => $v) {
6247
+ $k = strpos($k,':') ? $this->expandQname($k) : $k;
6248
+ $v = strpos($v,':') ? $this->expandQname($v) : $v;
6249
+ $aa[$k] = $v;
6250
+ }
6251
+ $eAttrs[$n] = $aa;
6252
+ }
6253
+ $attrs = $eAttrs;
6254
+ }
6255
+
6256
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6257
+ $arrayType = strpos($arrayType,':') ? $this->expandQname($arrayType) : $arrayType;
6258
+
6259
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6260
+ $this->schemas[$typens][0]->addComplexType($name,$typeClass,$phpType,$compositor,$restrictionBase,$elements,$attrs,$arrayType);
6261
+ }
6262
+
6263
+ /**
6264
+ * adds an XML Schema simple type to the WSDL types
6265
+ *
6266
+ * @param string $name
6267
+ * @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
6268
+ * @param string $typeClass (should always be simpleType)
6269
+ * @param string $phpType (should always be scalar)
6270
+ * @param array $enumeration array of values
6271
+ * @see nusoap_xmlschema
6272
+ * @access public
6273
+ */
6274
+ function addSimpleType($name, $restrictionBase='', $typeClass='simpleType', $phpType='scalar', $enumeration=array()) {
6275
+ $restrictionBase = strpos($restrictionBase,':') ? $this->expandQname($restrictionBase) : $restrictionBase;
6276
+
6277
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6278
+ $this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
6279
+ }
6280
+
6281
+ /**
6282
+ * adds an element to the WSDL types
6283
+ *
6284
+ * @param array $attrs attributes that must include name and type
6285
+ * @see nusoap_xmlschema
6286
+ * @access public
6287
+ */
6288
+ function addElement($attrs) {
6289
+ $typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
6290
+ $this->schemas[$typens][0]->addElement($attrs);
6291
+ }
6292
+
6293
+ /**
6294
+ * register an operation with the server
6295
+ *
6296
+ * @param string $name operation (method) name
6297
+ * @param array $in assoc array of input values: key = param name, value = param type
6298
+ * @param array $out assoc array of output values: key = param name, value = param type
6299
+ * @param string $namespace optional The namespace for the operation
6300
+ * @param string $soapaction optional The soapaction for the operation
6301
+ * @param string $style (rpc|document) optional The style for the operation Note: when 'document' is specified, parameter and return wrappers are created for you automatically
6302
+ * @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
6303
+ * @param string $documentation optional The description to include in the WSDL
6304
+ * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
6305
+ * @access public
6306
+ */
6307
+ function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = ''){
6308
+ if ($use == 'encoded' && $encodingStyle == '') {
6309
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
6310
+ }
6311
+
6312
+ if ($style == 'document') {
6313
+ $elements = array();
6314
+ foreach ($in as $n => $t) {
6315
+ $elements[$n] = array('name' => $n, 'type' => $t);
6316
+ }
6317
+ $this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
6318
+ $this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
6319
+ $in = array('parameters' => 'tns:' . $name . '^');
6320
+
6321
+ $elements = array();
6322
+ foreach ($out as $n => $t) {
6323
+ $elements[$n] = array('name' => $n, 'type' => $t);
6324
+ }
6325
+ $this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
6326
+ $this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
6327
+ $out = array('parameters' => 'tns:' . $name . 'Response' . '^');
6328
+ }
6329
+
6330
+ // get binding
6331
+ $this->bindings[ $this->serviceName . 'Binding' ]['operations'][$name] =
6332
+ array(
6333
+ 'name' => $name,
6334
+ 'binding' => $this->serviceName . 'Binding',
6335
+ 'endpoint' => $this->endpoint,
6336
+ 'soapAction' => $soapaction,
6337
+ 'style' => $style,
6338
+ 'input' => array(
6339
+ 'use' => $use,
6340
+ 'namespace' => $namespace,
6341
+ 'encodingStyle' => $encodingStyle,
6342
+ 'message' => $name . 'Request',
6343
+ 'parts' => $in),
6344
+ 'output' => array(
6345
+ 'use' => $use,
6346
+ 'namespace' => $namespace,
6347
+ 'encodingStyle' => $encodingStyle,
6348
+ 'message' => $name . 'Response',
6349
+ 'parts' => $out),
6350
+ 'namespace' => $namespace,
6351
+ 'transport' => 'http://schemas.xmlsoap.org/soap/http',
6352
+ 'documentation' => $documentation);
6353
+ // add portTypes
6354
+ // add messages
6355
+ if($in)
6356
+ {
6357
+ foreach($in as $pName => $pType)
6358
+ {
6359
+ if(strpos($pType,':')) {
6360
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6361
+ }
6362
+ $this->messages[$name.'Request'][$pName] = $pType;
6363
+ }
6364
+ } else {
6365
+ $this->messages[$name.'Request']= '0';
6366
+ }
6367
+ if($out)
6368
+ {
6369
+ foreach($out as $pName => $pType)
6370
+ {
6371
+ if(strpos($pType,':')) {
6372
+ $pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)).":".$this->getLocalPart($pType);
6373
+ }
6374
+ $this->messages[$name.'Response'][$pName] = $pType;
6375
+ }
6376
+ } else {
6377
+ $this->messages[$name.'Response']= '0';
6378
+ }
6379
+ return true;
6380
+ }
6381
+ }
6382
+ ?><?php
6383
+
6384
+
6385
+
6386
+ /**
6387
+ *
6388
+ * nusoap_parser class parses SOAP XML messages into native PHP values
6389
+ *
6390
+ * @author Dietrich Ayala <dietrich@ganx4.com>
6391
+ * @author Scott Nichol <snichol@users.sourceforge.net>
6392
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
6393
+ * @access public
6394
+ */
6395
+ class nusoap_parser extends nusoap_base {
6396
+
6397
+ var $xml = '';
6398
+ var $xml_encoding = '';
6399
+ var $method = '';
6400
+ var $root_struct = '';
6401
+ var $root_struct_name = '';
6402
+ var $root_struct_namespace = '';
6403
+ var $root_header = '';
6404
+ var $document = ''; // incoming SOAP body (text)
6405
+ // determines where in the message we are (envelope,header,body,method)
6406
+ var $status = '';
6407
+ var $position = 0;
6408
+ var $depth = 0;
6409
+ var $default_namespace = '';
6410
+ var $namespaces = array();
6411
+ var $message = array();
6412
+ var $parent = '';
6413
+ var $fault = false;
6414
+ var $fault_code = '';
6415
+ var $fault_str = '';
6416
+ var $fault_detail = '';
6417
+ var $depth_array = array();
6418
+ var $debug_flag = true;
6419
+ var $soapresponse = NULL; // parsed SOAP Body
6420
+ var $soapheader = NULL; // parsed SOAP Header
6421
+ var $responseHeaders = ''; // incoming SOAP headers (text)
6422
+ var $body_position = 0;
6423
+ // for multiref parsing:
6424
+ // array of id => pos
6425
+ var $ids = array();
6426
+ // array of id => hrefs => pos
6427
+ var $multirefs = array();
6428
+ // toggle for auto-decoding element content
6429
+ var $decode_utf8 = true;
6430
+
6431
+ /**
6432
+ * constructor that actually does the parsing
6433
+ *
6434
+ * @param string $xml SOAP message
6435
+ * @param string $encoding character encoding scheme of message
6436
+ * @param string $method method for which XML is parsed (unused?)
6437
+ * @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
6438
+ * @access public
6439
+ */
6440
+ function nusoap_parser($xml,$encoding='UTF-8',$method='',$decode_utf8=true){
6441
+ parent::nusoap_base();
6442
+ $this->xml = $xml;
6443
+ $this->xml_encoding = $encoding;
6444
+ $this->method = $method;
6445
+ $this->decode_utf8 = $decode_utf8;
6446
+
6447
+ // Check whether content has been read.
6448
+ if(!empty($xml)){
6449
+ // Check XML encoding
6450
+ $pos_xml = strpos($xml, '<?xml');
6451
+ if ($pos_xml !== FALSE) {
6452
+ $xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
6453
+ if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
6454
+ $xml_encoding = $res[1];
6455
+ if (strtoupper($xml_encoding) != $encoding) {
6456
+ $err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
6457
+ $this->debug($err);
6458
+ if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
6459
+ $this->setError($err);
6460
+ return;
6461
+ }
6462
+ // when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
6463
+ } else {
6464
+ $this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
6465
+ }
6466
+ } else {
6467
+ $this->debug('No encoding specified in XML declaration');
6468
+ }
6469
+ } else {
6470
+ $this->debug('No XML declaration');
6471
+ }
6472
+ $this->debug('Entering nusoap_parser(), length='.strlen($xml).', encoding='.$encoding);
6473
+ // Create an XML parser - why not xml_parser_create_ns?
6474
+ $this->parser = xml_parser_create($this->xml_encoding);
6475
+ // Set the options for parsing the XML data.
6476
+ //xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
6477
+ xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
6478
+ xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
6479
+ // Set the object for the parser.
6480
+ xml_set_object($this->parser, $this);
6481
+ // Set the element handlers for the parser.
6482
+ xml_set_element_handler($this->parser, 'start_element','end_element');
6483
+ xml_set_character_data_handler($this->parser,'character_data');
6484
+
6485
+ // Parse the XML file.
6486
+ if(!xml_parse($this->parser,$xml,true)){
6487
+ // Display an error message.
6488
+ $err = sprintf('XML error parsing SOAP payload on line %d: %s',
6489
+ xml_get_current_line_number($this->parser),
6490
+ xml_error_string(xml_get_error_code($this->parser)));
6491
+ $this->debug($err);
6492
+ $this->debug("XML payload:\n" . $xml);
6493
+ $this->setError($err);
6494
+ } else {
6495
+ $this->debug('parsed successfully, found root struct: '.$this->root_struct.' of name '.$this->root_struct_name);
6496
+ // get final value
6497
+ $this->soapresponse = $this->message[$this->root_struct]['result'];
6498
+ // get header value
6499
+ if($this->root_header != '' && isset($this->message[$this->root_header]['result'])){
6500
+ $this->soapheader = $this->message[$this->root_header]['result'];
6501
+ }
6502
+ // resolve hrefs/ids
6503
+ if(sizeof($this->multirefs) > 0){
6504
+ foreach($this->multirefs as $id => $hrefs){
6505
+ $this->debug('resolving multirefs for id: '.$id);
6506
+ $idVal = $this->buildVal($this->ids[$id]);
6507
+ if (is_array($idVal) && isset($idVal['!id'])) {
6508
+ unset($idVal['!id']);
6509
+ }
6510
+ foreach($hrefs as $refPos => $ref){
6511
+ $this->debug('resolving href at pos '.$refPos);
6512
+ $this->multirefs[$id][$refPos] = $idVal;
6513
+ }
6514
+ }
6515
+ }
6516
+ }
6517
+ xml_parser_free($this->parser);
6518
+ } else {
6519
+ $this->debug('xml was empty, didn\'t parse!');
6520
+ $this->setError('xml was empty, didn\'t parse!');
6521
+ }
6522
+ }
6523
+
6524
+ /**
6525
+ * start-element handler
6526
+ *
6527
+ * @param resource $parser XML parser object
6528
+ * @param string $name element name
6529
+ * @param array $attrs associative array of attributes
6530
+ * @access private
6531
+ */
6532
+ function start_element($parser, $name, $attrs) {
6533
+ // position in a total number of elements, starting from 0
6534
+ // update class level pos
6535
+ $pos = $this->position++;
6536
+ // and set mine
6537
+ $this->message[$pos] = array('pos' => $pos,'children'=>'','cdata'=>'');
6538
+ // depth = how many levels removed from root?
6539
+ // set mine as current global depth and increment global depth value
6540
+ $this->message[$pos]['depth'] = $this->depth++;
6541
+
6542
+ // else add self as child to whoever the current parent is
6543
+ if($pos != 0){
6544
+ $this->message[$this->parent]['children'] .= '|'.$pos;
6545
+ }
6546
+ // set my parent
6547
+ $this->message[$pos]['parent'] = $this->parent;
6548
+ // set self as current parent
6549
+ $this->parent = $pos;
6550
+ // set self as current value for this depth
6551
+ $this->depth_array[$this->depth] = $pos;
6552
+ // get element prefix
6553
+ if(strpos($name,':')){
6554
+ // get ns prefix
6555
+ $prefix = substr($name,0,strpos($name,':'));
6556
+ // get unqualified name
6557
+ $name = substr(strstr($name,':'),1);
6558
+ }
6559
+ // set status
6560
+ if($name == 'Envelope'){
6561
+ $this->status = 'envelope';
6562
+ } elseif($name == 'Header' && $this->status = 'envelope'){
6563
+ $this->root_header = $pos;
6564
+ $this->status = 'header';
6565
+ } elseif($name == 'Body' && $this->status = 'envelope'){
6566
+ $this->status = 'body';
6567
+ $this->body_position = $pos;
6568
+ // set method
6569
+ } elseif($this->status == 'body' && $pos == ($this->body_position+1)){
6570
+ $this->status = 'method';
6571
+ $this->root_struct_name = $name;
6572
+ $this->root_struct = $pos;
6573
+ $this->message[$pos]['type'] = 'struct';
6574
+ $this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
6575
+ }
6576
+ // set my status
6577
+ $this->message[$pos]['status'] = $this->status;
6578
+ // set name
6579
+ $this->message[$pos]['name'] = htmlspecialchars($name);
6580
+ // set attrs
6581
+ $this->message[$pos]['attrs'] = $attrs;
6582
+
6583
+ // loop through atts, logging ns and type declarations
6584
+ $attstr = '';
6585
+ foreach($attrs as $key => $value){
6586
+ $key_prefix = $this->getPrefix($key);
6587
+ $key_localpart = $this->getLocalPart($key);
6588
+ // if ns declarations, add to class level array of valid namespaces
6589
+ if($key_prefix == 'xmlns'){
6590
+ if(ereg('^http://www.w3.org/[0-9]{4}/XMLSchema$',$value)){
6591
+ $this->XMLSchemaVersion = $value;
6592
+ $this->namespaces['xsd'] = $this->XMLSchemaVersion;
6593
+ $this->namespaces['xsi'] = $this->XMLSchemaVersion.'-instance';
6594
+ }
6595
+ $this->namespaces[$key_localpart] = $value;
6596
+ // set method namespace
6597
+ if($name == $this->root_struct_name){
6598
+ $this->methodNamespace = $value;
6599
+ }
6600
+ // if it's a type declaration, set type
6601
+ } elseif($key_localpart == 'type'){
6602
+ if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
6603
+ // do nothing: already processed arrayType
6604
+ } else {
6605
+ $value_prefix = $this->getPrefix($value);
6606
+ $value_localpart = $this->getLocalPart($value);
6607
+ $this->message[$pos]['type'] = $value_localpart;
6608
+ $this->message[$pos]['typePrefix'] = $value_prefix;
6609
+ if(isset($this->namespaces[$value_prefix])){
6610
+ $this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
6611
+ } else if(isset($attrs['xmlns:'.$value_prefix])) {
6612
+ $this->message[$pos]['type_namespace'] = $attrs['xmlns:'.$value_prefix];
6613
+ }
6614
+ // should do something here with the namespace of specified type?
6615
+ }
6616
+ } elseif($key_localpart == 'arrayType'){
6617
+ $this->message[$pos]['type'] = 'array';
6618
+ /* do arrayType ereg here
6619
+ [1] arrayTypeValue ::= atype asize
6620
+ [2] atype ::= QName rank*
6621
+ [3] rank ::= '[' (',')* ']'
6622
+ [4] asize ::= '[' length~ ']'
6623
+ [5] length ::= nextDimension* Digit+
6624
+ [6] nextDimension ::= Digit+ ','
6625
+ */
6626
+ $expr = '([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]';
6627
+ if(ereg($expr,$value,$regs)){
6628
+ $this->message[$pos]['typePrefix'] = $regs[1];
6629
+ $this->message[$pos]['arrayTypePrefix'] = $regs[1];
6630
+ if (isset($this->namespaces[$regs[1]])) {
6631
+ $this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
6632
+ } else if (isset($attrs['xmlns:'.$regs[1]])) {
6633
+ $this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:'.$regs[1]];
6634
+ }
6635
+ $this->message[$pos]['arrayType'] = $regs[2];
6636
+ $this->message[$pos]['arraySize'] = $regs[3];
6637
+ $this->message[$pos]['arrayCols'] = $regs[4];
6638
+ }
6639
+ // specifies nil value (or not)
6640
+ } elseif ($key_localpart == 'nil'){
6641
+ $this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
6642
+ // some other attribute
6643
+ } elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
6644
+ $this->message[$pos]['xattrs']['!' . $key] = $value;
6645
+ }
6646
+
6647
+ if ($key == 'xmlns') {
6648
+ $this->default_namespace = $value;
6649
+ }
6650
+ // log id
6651
+ if($key == 'id'){
6652
+ $this->ids[$value] = $pos;
6653
+ }
6654
+ // root
6655
+ if($key_localpart == 'root' && $value == 1){
6656
+ $this->status = 'method';
6657
+ $this->root_struct_name = $name;
6658
+ $this->root_struct = $pos;
6659
+ $this->debug("found root struct $this->root_struct_name, pos $pos");
6660
+ }
6661
+ // for doclit
6662
+ $attstr .= " $key=\"$value\"";
6663
+ }
6664
+ // get namespace - must be done after namespace atts are processed
6665
+ if(isset($prefix)){
6666
+ $this->message[$pos]['namespace'] = $this->namespaces[$prefix];
6667
+ $this->default_namespace = $this->namespaces[$prefix];
6668
+ } else {
6669
+ $this->message[$pos]['namespace'] = $this->default_namespace;
6670
+ }
6671
+ if($this->status == 'header'){
6672
+ if ($this->root_header != $pos) {
6673
+ $this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6674
+ }
6675
+ } elseif($this->root_struct_name != ''){
6676
+ $this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
6677
+ }
6678
+ }
6679
+
6680
+ /**
6681
+ * end-element handler
6682
+ *
6683
+ * @param resource $parser XML parser object
6684
+ * @param string $name element name
6685
+ * @access private
6686
+ */
6687
+ function end_element($parser, $name) {
6688
+ // position of current element is equal to the last value left in depth_array for my depth
6689
+ $pos = $this->depth_array[$this->depth--];
6690
+
6691
+ // get element prefix
6692
+ if(strpos($name,':')){
6693
+ // get ns prefix
6694
+ $prefix = substr($name,0,strpos($name,':'));
6695
+ // get unqualified name
6696
+ $name = substr(strstr($name,':'),1);
6697
+ }
6698
+
6699
+ // build to native type
6700
+ if(isset($this->body_position) && $pos > $this->body_position){
6701
+ // deal w/ multirefs
6702
+ if(isset($this->message[$pos]['attrs']['href'])){
6703
+ // get id
6704
+ $id = substr($this->message[$pos]['attrs']['href'],1);
6705
+ // add placeholder to href array
6706
+ $this->multirefs[$id][$pos] = 'placeholder';
6707
+ // add set a reference to it as the result value
6708
+ $this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
6709
+ // build complexType values
6710
+ } elseif($this->message[$pos]['children'] != ''){
6711
+ // if result has already been generated (struct/array)
6712
+ if(!isset($this->message[$pos]['result'])){
6713
+ $this->message[$pos]['result'] = $this->buildVal($pos);
6714
+ }
6715
+ // build complexType values of attributes and possibly simpleContent
6716
+ } elseif (isset($this->message[$pos]['xattrs'])) {
6717
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6718
+ $this->message[$pos]['xattrs']['!'] = null;
6719
+ } elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6720
+ if (isset($this->message[$pos]['type'])) {
6721
+ $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'] : '');
6722
+ } else {
6723
+ $parent = $this->message[$pos]['parent'];
6724
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6725
+ $this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6726
+ } else {
6727
+ $this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
6728
+ }
6729
+ }
6730
+ }
6731
+ $this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
6732
+ // set value of simpleType (or nil complexType)
6733
+ } else {
6734
+ //$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
6735
+ if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
6736
+ $this->message[$pos]['xattrs']['!'] = null;
6737
+ } elseif (isset($this->message[$pos]['type'])) {
6738
+ $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'] : '');
6739
+ } else {
6740
+ $parent = $this->message[$pos]['parent'];
6741
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6742
+ $this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6743
+ } else {
6744
+ $this->message[$pos]['result'] = $this->message[$pos]['cdata'];
6745
+ }
6746
+ }
6747
+
6748
+ /* add value to parent's result, if parent is struct/array
6749
+ $parent = $this->message[$pos]['parent'];
6750
+ if($this->message[$parent]['type'] != 'map'){
6751
+ if(strtolower($this->message[$parent]['type']) == 'array'){
6752
+ $this->message[$parent]['result'][] = $this->message[$pos]['result'];
6753
+ } else {
6754
+ $this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
6755
+ }
6756
+ }
6757
+ */
6758
+ }
6759
+ }
6760
+
6761
+ // for doclit
6762
+ if($this->status == 'header'){
6763
+ if ($this->root_header != $pos) {
6764
+ $this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6765
+ }
6766
+ } elseif($pos >= $this->root_struct){
6767
+ $this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
6768
+ }
6769
+ // switch status
6770
+ if($pos == $this->root_struct){
6771
+ $this->status = 'body';
6772
+ $this->root_struct_namespace = $this->message[$pos]['namespace'];
6773
+ } elseif($name == 'Body'){
6774
+ $this->status = 'envelope';
6775
+ } elseif($name == 'Header'){
6776
+ $this->status = 'envelope';
6777
+ } elseif($name == 'Envelope'){
6778
+ //
6779
+ }
6780
+ // set parent back to my parent
6781
+ $this->parent = $this->message[$pos]['parent'];
6782
+ }
6783
+
6784
+ /**
6785
+ * element content handler
6786
+ *
6787
+ * @param resource $parser XML parser object
6788
+ * @param string $data element content
6789
+ * @access private
6790
+ */
6791
+ function character_data($parser, $data){
6792
+ $pos = $this->depth_array[$this->depth];
6793
+ if ($this->xml_encoding=='UTF-8'){
6794
+ // TODO: add an option to disable this for folks who want
6795
+ // raw UTF-8 that, e.g., might not map to iso-8859-1
6796
+ // TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
6797
+ if($this->decode_utf8){
6798
+ $data = utf8_decode($data);
6799
+ }
6800
+ }
6801
+ $this->message[$pos]['cdata'] .= $data;
6802
+ // for doclit
6803
+ if($this->status == 'header'){
6804
+ $this->responseHeaders .= $data;
6805
+ } else {
6806
+ $this->document .= $data;
6807
+ }
6808
+ }
6809
+
6810
+ /**
6811
+ * get the parsed message (SOAP Body)
6812
+ *
6813
+ * @return mixed
6814
+ * @access public
6815
+ * @deprecated use get_soapbody instead
6816
+ */
6817
+ function get_response(){
6818
+ return $this->soapresponse;
6819
+ }
6820
+
6821
+ /**
6822
+ * get the parsed SOAP Body (NULL if there was none)
6823
+ *
6824
+ * @return mixed
6825
+ * @access public
6826
+ */
6827
+ function get_soapbody(){
6828
+ return $this->soapresponse;
6829
+ }
6830
+
6831
+ /**
6832
+ * get the parsed SOAP Header (NULL if there was none)
6833
+ *
6834
+ * @return mixed
6835
+ * @access public
6836
+ */
6837
+ function get_soapheader(){
6838
+ return $this->soapheader;
6839
+ }
6840
+
6841
+ /**
6842
+ * get the unparsed SOAP Header
6843
+ *
6844
+ * @return string XML or empty if no Header
6845
+ * @access public
6846
+ */
6847
+ function getHeaders(){
6848
+ return $this->responseHeaders;
6849
+ }
6850
+
6851
+ /**
6852
+ * decodes simple types into PHP variables
6853
+ *
6854
+ * @param string $value value to decode
6855
+ * @param string $type XML type to decode
6856
+ * @param string $typens XML type namespace to decode
6857
+ * @return mixed PHP value
6858
+ * @access private
6859
+ */
6860
+ function decodeSimple($value, $type, $typens) {
6861
+ // TODO: use the namespace!
6862
+ if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
6863
+ return (string) $value;
6864
+ }
6865
+ if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
6866
+ return (int) $value;
6867
+ }
6868
+ if ($type == 'float' || $type == 'double' || $type == 'decimal') {
6869
+ return (double) $value;
6870
+ }
6871
+ if ($type == 'boolean') {
6872
+ if (strtolower($value) == 'false' || strtolower($value) == 'f') {
6873
+ return false;
6874
+ }
6875
+ return (boolean) $value;
6876
+ }
6877
+ if ($type == 'base64' || $type == 'base64Binary') {
6878
+ $this->debug('Decode base64 value');
6879
+ return base64_decode($value);
6880
+ }
6881
+ // obscure numeric types
6882
+ if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
6883
+ || $type == 'nonNegativeInteger' || $type == 'positiveInteger'
6884
+ || $type == 'unsignedInt'
6885
+ || $type == 'unsignedShort' || $type == 'unsignedByte') {
6886
+ return (int) $value;
6887
+ }
6888
+ // bogus: parser treats array with no elements as a simple type
6889
+ if ($type == 'array') {
6890
+ return array();
6891
+ }
6892
+ // everything else
6893
+ return (string) $value;
6894
+ }
6895
+
6896
+ /**
6897
+ * builds response structures for compound values (arrays/structs)
6898
+ * and scalars
6899
+ *
6900
+ * @param integer $pos position in node tree
6901
+ * @return mixed PHP value
6902
+ * @access private
6903
+ */
6904
+ function buildVal($pos){
6905
+ if(!isset($this->message[$pos]['type'])){
6906
+ $this->message[$pos]['type'] = '';
6907
+ }
6908
+ $this->debug('in buildVal() for '.$this->message[$pos]['name']."(pos $pos) of type ".$this->message[$pos]['type']);
6909
+ // if there are children...
6910
+ if($this->message[$pos]['children'] != ''){
6911
+ $this->debug('in buildVal, there are children');
6912
+ $children = explode('|',$this->message[$pos]['children']);
6913
+ array_shift($children); // knock off empty
6914
+ // md array
6915
+ if(isset($this->message[$pos]['arrayCols']) && $this->message[$pos]['arrayCols'] != ''){
6916
+ $r=0; // rowcount
6917
+ $c=0; // colcount
6918
+ foreach($children as $child_pos){
6919
+ $this->debug("in buildVal, got an MD array element: $r, $c");
6920
+ $params[$r][] = $this->message[$child_pos]['result'];
6921
+ $c++;
6922
+ if($c == $this->message[$pos]['arrayCols']){
6923
+ $c = 0;
6924
+ $r++;
6925
+ }
6926
+ }
6927
+ // array
6928
+ } elseif($this->message[$pos]['type'] == 'array' || $this->message[$pos]['type'] == 'Array'){
6929
+ $this->debug('in buildVal, adding array '.$this->message[$pos]['name']);
6930
+ foreach($children as $child_pos){
6931
+ $params[] = &$this->message[$child_pos]['result'];
6932
+ }
6933
+ // apache Map type: java hashtable
6934
+ } elseif($this->message[$pos]['type'] == 'Map' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap'){
6935
+ $this->debug('in buildVal, Java Map '.$this->message[$pos]['name']);
6936
+ foreach($children as $child_pos){
6937
+ $kv = explode("|",$this->message[$child_pos]['children']);
6938
+ $params[$this->message[$kv[1]]['result']] = &$this->message[$kv[2]]['result'];
6939
+ }
6940
+ // generic compound type
6941
+ //} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
6942
+ } else {
6943
+ // Apache Vector type: treat as an array
6944
+ $this->debug('in buildVal, adding Java Vector or generic compound type '.$this->message[$pos]['name']);
6945
+ if ($this->message[$pos]['type'] == 'Vector' && $this->message[$pos]['type_namespace'] == 'http://xml.apache.org/xml-soap') {
6946
+ $notstruct = 1;
6947
+ } else {
6948
+ $notstruct = 0;
6949
+ }
6950
+ //
6951
+ foreach($children as $child_pos){
6952
+ if($notstruct){
6953
+ $params[] = &$this->message[$child_pos]['result'];
6954
+ } else {
6955
+ if (isset($params[$this->message[$child_pos]['name']])) {
6956
+ // de-serialize repeated element name into an array
6957
+ if ((!is_array($params[$this->message[$child_pos]['name']])) || (!isset($params[$this->message[$child_pos]['name']][0]))) {
6958
+ $params[$this->message[$child_pos]['name']] = array($params[$this->message[$child_pos]['name']]);
6959
+ }
6960
+ $params[$this->message[$child_pos]['name']][] = &$this->message[$child_pos]['result'];
6961
+ } else {
6962
+ $params[$this->message[$child_pos]['name']] = &$this->message[$child_pos]['result'];
6963
+ }
6964
+ }
6965
+ }
6966
+ }
6967
+ if (isset($this->message[$pos]['xattrs'])) {
6968
+ $this->debug('in buildVal, handling attributes');
6969
+ foreach ($this->message[$pos]['xattrs'] as $n => $v) {
6970
+ $params[$n] = $v;
6971
+ }
6972
+ }
6973
+ // handle simpleContent
6974
+ if (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
6975
+ $this->debug('in buildVal, handling simpleContent');
6976
+ if (isset($this->message[$pos]['type'])) {
6977
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6978
+ } else {
6979
+ $parent = $this->message[$pos]['parent'];
6980
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
6981
+ $params['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
6982
+ } else {
6983
+ $params['!'] = $this->message[$pos]['cdata'];
6984
+ }
6985
+ }
6986
+ }
6987
+ $ret = is_array($params) ? $params : array();
6988
+ $this->debug('in buildVal, return:');
6989
+ $this->appendDebug($this->varDump($ret));
6990
+ return $ret;
6991
+ } else {
6992
+ $this->debug('in buildVal, no children, building scalar');
6993
+ $cdata = isset($this->message[$pos]['cdata']) ? $this->message[$pos]['cdata'] : '';
6994
+ if (isset($this->message[$pos]['type'])) {
6995
+ $ret = $this->decodeSimple($cdata, $this->message[$pos]['type'], isset($this->message[$pos]['type_namespace']) ? $this->message[$pos]['type_namespace'] : '');
6996
+ $this->debug("in buildVal, return: $ret");
6997
+ return $ret;
6998
+ }
6999
+ $parent = $this->message[$pos]['parent'];
7000
+ if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
7001
+ $ret = $this->decodeSimple($cdata, $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
7002
+ $this->debug("in buildVal, return: $ret");
7003
+ return $ret;
7004
+ }
7005
+ $ret = $this->message[$pos]['cdata'];
7006
+ $this->debug("in buildVal, return: $ret");
7007
+ return $ret;
7008
+ }
7009
+ }
7010
+ }
7011
+
7012
+ /**
7013
+ * Backward compatibility
7014
+ */
7015
+ class soap_parser extends nusoap_parser {
7016
+ }
7017
+
7018
+ ?><?php
7019
+
7020
+
7021
+
7022
+ /**
7023
+ *
7024
+ * [nu]soapclient higher level class for easy usage.
7025
+ *
7026
+ * usage:
7027
+ *
7028
+ * // instantiate client with server info
7029
+ * $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
7030
+ *
7031
+ * // call method, get results
7032
+ * echo $soapclient->call( string methodname [ ,array parameters] );
7033
+ *
7034
+ * // bye bye client
7035
+ * unset($soapclient);
7036
+ *
7037
+ * @author Dietrich Ayala <dietrich@ganx4.com>
7038
+ * @author Scott Nichol <snichol@users.sourceforge.net>
7039
+ * @version $Id: nusoap.php,v 1.114 2007/11/06 15:17:46 snichol Exp $
7040
+ * @access public
7041
+ */
7042
+ class nusoap_client extends nusoap_base {
7043
+
7044
+ var $username = ''; // Username for HTTP authentication
7045
+ var $password = ''; // Password for HTTP authentication
7046
+ var $authtype = ''; // Type of HTTP authentication
7047
+ var $certRequest = array(); // Certificate for HTTP SSL authentication
7048
+ var $requestHeaders = false; // SOAP headers in request (text)
7049
+ var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
7050
+ var $responseHeader = NULL; // SOAP Header from response (parsed)
7051
+ var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
7052
+ var $endpoint;
7053
+ var $forceEndpoint = ''; // overrides WSDL endpoint
7054
+ var $proxyhost = '';
7055
+ var $proxyport = '';
7056
+ var $proxyusername = '';
7057
+ var $proxypassword = '';
7058
+ var $xml_encoding = ''; // character set encoding of incoming (response) messages
7059
+ var $http_encoding = false;
7060
+ var $timeout = 0; // HTTP connection timeout
7061
+ var $response_timeout = 30; // HTTP response timeout
7062
+ var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
7063
+ var $persistentConnection = false;
7064
+ var $defaultRpcParams = false; // This is no longer used
7065
+ var $request = ''; // HTTP request
7066
+ var $response = ''; // HTTP response
7067
+ var $responseData = ''; // SOAP payload of response
7068
+ var $cookies = array(); // Cookies from response or for request
7069
+ var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
7070
+ var $operations = array(); // WSDL operations, empty for WSDL initialization error
7071
+ var $curl_options = array(); // User-specified cURL options
7072
+ var $bindingType = ''; // WSDL operation binding type
7073
+ var $use_curl = false; // whether to always try to use cURL
7074
+
7075
+ /*
7076
+ * fault related variables
7077
+ */
7078
+ /**
7079
+ * @var fault
7080
+ * @access public
7081
+ */
7082
+ var $fault;
7083
+ /**
7084
+ * @var faultcode
7085
+ * @access public
7086
+ */
7087
+ var $faultcode;
7088
+ /**
7089
+ * @var faultstring
7090
+ * @access public
7091
+ */
7092
+ var $faultstring;
7093
+ /**
7094
+ * @var faultdetail
7095
+ * @access public
7096
+ */
7097
+ var $faultdetail;
7098
+
7099
+ /**
7100
+ * constructor
7101
+ *
7102
+ * @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
7103
+ * @param bool $wsdl optional, set to true if using WSDL
7104
+ * @param int $portName optional portName in WSDL document
7105
+ * @param string $proxyhost
7106
+ * @param string $proxyport
7107
+ * @param string $proxyusername
7108
+ * @param string $proxypassword
7109
+ * @param integer $timeout set the connection timeout
7110
+ * @param integer $response_timeout set the response timeout
7111
+ * @access public
7112
+ */
7113
+ function nusoap_client($endpoint,$wsdl = false,$proxyhost = false,$proxyport = false,$proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30){
7114
+ parent::nusoap_base();
7115
+ $this->endpoint = $endpoint;
7116
+ $this->proxyhost = $proxyhost;
7117
+ $this->proxyport = $proxyport;
7118
+ $this->proxyusername = $proxyusername;
7119
+ $this->proxypassword = $proxypassword;
7120
+ $this->timeout = $timeout;
7121
+ $this->response_timeout = $response_timeout;
7122
+
7123
+ $this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
7124
+ $this->appendDebug('endpoint=' . $this->varDump($endpoint));
7125
+
7126
+ // make values
7127
+ if($wsdl){
7128
+ if (is_object($endpoint) && (get_class($endpoint) == 'wsdl')) {
7129
+ $this->wsdl = $endpoint;
7130
+ $this->endpoint = $this->wsdl->wsdl;
7131
+ $this->wsdlFile = $this->endpoint;
7132
+ $this->debug('existing wsdl instance created from ' . $this->endpoint);
7133
+ $this->checkWSDL();
7134
+ } else {
7135
+ $this->wsdlFile = $this->endpoint;
7136
+ $this->wsdl = null;
7137
+ $this->debug('will use lazy evaluation of wsdl from ' . $this->endpoint);
7138
+ }
7139
+ $this->endpointType = 'wsdl';
7140
+ } else {
7141
+ $this->debug("instantiate SOAP with endpoint at $endpoint");
7142
+ $this->endpointType = 'soap';
7143
+ }
7144
+ }
7145
+
7146
+ /**
7147
+ * calls method, returns PHP native type
7148
+ *
7149
+ * @param string $operation SOAP server URL or path
7150
+ * @param mixed $params An array, associative or simple, of the parameters
7151
+ * for the method call, or a string that is the XML
7152
+ * for the call. For rpc style, this call will
7153
+ * wrap the XML in a tag named after the method, as
7154
+ * well as the SOAP Envelope and Body. For document
7155
+ * style, this will only wrap with the Envelope and Body.
7156
+ * IMPORTANT: when using an array with document style,
7157
+ * in which case there
7158
+ * is really one parameter, the root of the fragment
7159
+ * used in the call, which encloses what programmers
7160
+ * normally think of parameters. A parameter array
7161
+ * *must* include the wrapper.
7162
+ * @param string $namespace optional method namespace (WSDL can override)
7163
+ * @param string $soapAction optional SOAPAction value (WSDL can override)
7164
+ * @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
7165
+ * @param boolean $rpcParams optional (no longer used)
7166
+ * @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
7167
+ * @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
7168
+ * @return mixed response from SOAP call
7169
+ * @access public
7170
+ */
7171
+ function call($operation,$params=array(),$namespace='http://tempuri.org',$soapAction='',$headers=false,$rpcParams=null,$style='rpc',$use='encoded'){
7172
+ $this->operation = $operation;
7173
+ $this->fault = false;
7174
+ $this->setError('');
7175
+ $this->request = '';
7176
+ $this->response = '';
7177
+ $this->responseData = '';
7178
+ $this->faultstring = '';
7179
+ $this->faultcode = '';
7180
+ $this->opData = array();
7181
+
7182
+ $this->debug("call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType");
7183
+ $this->appendDebug('params=' . $this->varDump($params));
7184
+ $this->appendDebug('headers=' . $this->varDump($headers));
7185
+ if ($headers) {
7186
+ $this->requestHeaders = $headers;
7187
+ }
7188
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7189
+ $this->loadWSDL();
7190
+ if ($this->getError())
7191
+ return false;
7192
+ }
7193
+ // serialize parameters
7194
+ if($this->endpointType == 'wsdl' && $opData = $this->getOperationData($operation)){
7195
+ // use WSDL for operation
7196
+ $this->opData = $opData;
7197
+ $this->debug("found operation");
7198
+ $this->appendDebug('opData=' . $this->varDump($opData));
7199
+ if (isset($opData['soapAction'])) {
7200
+ $soapAction = $opData['soapAction'];
7201
+ }
7202
+ if (! $this->forceEndpoint) {
7203
+ $this->endpoint = $opData['endpoint'];
7204
+ } else {
7205
+ $this->endpoint = $this->forceEndpoint;
7206
+ }
7207
+ $namespace = isset($opData['input']['namespace']) ? $opData['input']['namespace'] : $namespace;
7208
+ $style = $opData['style'];
7209
+ $use = $opData['input']['use'];
7210
+ // add ns to ns array
7211
+ if($namespace != '' && !isset($this->wsdl->namespaces[$namespace])){
7212
+ $nsPrefix = 'ns' . rand(1000, 9999);
7213
+ $this->wsdl->namespaces[$nsPrefix] = $namespace;
7214
+ }
7215
+ $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace);
7216
+ // serialize payload
7217
+ if (is_string($params)) {
7218
+ $this->debug("serializing param string for WSDL operation $operation");
7219
+ $payload = $params;
7220
+ } elseif (is_array($params)) {
7221
+ $this->debug("serializing param array for WSDL operation $operation");
7222
+ $payload = $this->wsdl->serializeRPCParameters($operation,'input',$params,$this->bindingType);
7223
+ } else {
7224
+ $this->debug('params must be array or string');
7225
+ $this->setError('params must be array or string');
7226
+ return false;
7227
+ }
7228
+ $usedNamespaces = $this->wsdl->usedNamespaces;
7229
+ if (isset($opData['input']['encodingStyle'])) {
7230
+ $encodingStyle = $opData['input']['encodingStyle'];
7231
+ } else {
7232
+ $encodingStyle = '';
7233
+ }
7234
+ $this->appendDebug($this->wsdl->getDebug());
7235
+ $this->wsdl->clearDebug();
7236
+ if ($errstr = $this->wsdl->getError()) {
7237
+ $this->debug('got wsdl error: '.$errstr);
7238
+ $this->setError('wsdl error: '.$errstr);
7239
+ return false;
7240
+ }
7241
+ } elseif($this->endpointType == 'wsdl') {
7242
+ // operation not in WSDL
7243
+ $this->appendDebug($this->wsdl->getDebug());
7244
+ $this->wsdl->clearDebug();
7245
+ $this->setError( 'operation '.$operation.' not present.');
7246
+ $this->debug("operation '$operation' not present.");
7247
+ return false;
7248
+ } else {
7249
+ // no WSDL
7250
+ //$this->namespaces['ns1'] = $namespace;
7251
+ $nsPrefix = 'ns' . rand(1000, 9999);
7252
+ // serialize
7253
+ $payload = '';
7254
+ if (is_string($params)) {
7255
+ $this->debug("serializing param string for operation $operation");
7256
+ $payload = $params;
7257
+ } elseif (is_array($params)) {
7258
+ $this->debug("serializing param array for operation $operation");
7259
+ foreach($params as $k => $v){
7260
+ $payload .= $this->serialize_val($v,$k,false,false,false,false,$use);
7261
+ }
7262
+ } else {
7263
+ $this->debug('params must be array or string');
7264
+ $this->setError('params must be array or string');
7265
+ return false;
7266
+ }
7267
+ $usedNamespaces = array();
7268
+ if ($use == 'encoded') {
7269
+ $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
7270
+ } else {
7271
+ $encodingStyle = '';
7272
+ }
7273
+ }
7274
+ // wrap RPC calls with method element
7275
+ if ($style == 'rpc') {
7276
+ if ($use == 'literal') {
7277
+ $this->debug("wrapping RPC request with literal method element");
7278
+ if ($namespace) {
7279
+ // 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
7280
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7281
+ $payload .
7282
+ "</$nsPrefix:$operation>";
7283
+ } else {
7284
+ $payload = "<$operation>" . $payload . "</$operation>";
7285
+ }
7286
+ } else {
7287
+ $this->debug("wrapping RPC request with encoded method element");
7288
+ if ($namespace) {
7289
+ $payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
7290
+ $payload .
7291
+ "</$nsPrefix:$operation>";
7292
+ } else {
7293
+ $payload = "<$operation>" .
7294
+ $payload .
7295
+ "</$operation>";
7296
+ }
7297
+ }
7298
+ }
7299
+ // serialize envelope
7300
+ $soapmsg = $this->serializeEnvelope($payload,$this->requestHeaders,$usedNamespaces,$style,$use,$encodingStyle);
7301
+ $this->debug("endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle");
7302
+ $this->debug('SOAP message length=' . strlen($soapmsg) . ' contents (max 1000 bytes)=' . substr($soapmsg, 0, 1000));
7303
+ // send
7304
+ $return = $this->send($this->getHTTPBody($soapmsg),$soapAction,$this->timeout,$this->response_timeout);
7305
+ if($errstr = $this->getError()){
7306
+ $this->debug('Error: '.$errstr);
7307
+ return false;
7308
+ } else {
7309
+ $this->return = $return;
7310
+ $this->debug('sent message successfully and got a(n) '.gettype($return));
7311
+ $this->appendDebug('return=' . $this->varDump($return));
7312
+
7313
+ // fault?
7314
+ if(is_array($return) && isset($return['faultcode'])){
7315
+ $this->debug('got fault');
7316
+ $this->setError($return['faultcode'].': '.$return['faultstring']);
7317
+ $this->fault = true;
7318
+ foreach($return as $k => $v){
7319
+ $this->$k = $v;
7320
+ $this->debug("$k = $v<br>");
7321
+ }
7322
+ return $return;
7323
+ } elseif ($style == 'document') {
7324
+ // NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
7325
+ // we are only going to return the first part here...sorry about that
7326
+ return $return;
7327
+ } else {
7328
+ // array of return values
7329
+ if(is_array($return)){
7330
+ // multiple 'out' parameters, which we return wrapped up
7331
+ // in the array
7332
+ if(sizeof($return) > 1){
7333
+ return $return;
7334
+ }
7335
+ // single 'out' parameter (normally the return value)
7336
+ $return = array_shift($return);
7337
+ $this->debug('return shifted value: ');
7338
+ $this->appendDebug($this->varDump($return));
7339
+ return $return;
7340
+ // nothing returned (ie, echoVoid)
7341
+ } else {
7342
+ return "";
7343
+ }
7344
+ }
7345
+ }
7346
+ }
7347
+
7348
+ /**
7349
+ * check WSDL passed as an instance or pulled from an endpoint
7350
+ *
7351
+ * @access private
7352
+ */
7353
+ function checkWSDL() {
7354
+ $this->appendDebug($this->wsdl->getDebug());
7355
+ $this->wsdl->clearDebug();
7356
+ $this->debug('checkWSDL');
7357
+ // catch errors
7358
+ if ($errstr = $this->wsdl->getError()) {
7359
+ $this->debug('got wsdl error: '.$errstr);
7360
+ $this->setError('wsdl error: '.$errstr);
7361
+ } elseif ($this->operations = $this->wsdl->getOperations('soap')) {
7362
+ $this->bindingType = 'soap';
7363
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7364
+ } elseif ($this->operations = $this->wsdl->getOperations('soap12')) {
7365
+ $this->bindingType = 'soap12';
7366
+ $this->debug('got '.count($this->operations).' operations from wsdl '.$this->wsdlFile.' for binding type '.$this->bindingType);
7367
+ $this->debug('**************** WARNING: SOAP 1.2 BINDING *****************');
7368
+ } else {
7369
+ $this->debug('getOperations returned false');
7370
+ $this->setError('no operations defined in the WSDL document!');
7371
+ }
7372
+ }
7373
+
7374
+ /**
7375
+ * instantiate wsdl object and parse wsdl file
7376
+ *
7377
+ * @access public
7378
+ */
7379
+ function loadWSDL() {
7380
+ $this->debug('instantiating wsdl class with doc: '.$this->wsdlFile);
7381
+ $this->wsdl =& new wsdl('',$this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword,$this->timeout,$this->response_timeout,$this->curl_options,$this->use_curl);
7382
+ $this->wsdl->setCredentials($this->username, $this->password, $this->authtype, $this->certRequest);
7383
+ $this->wsdl->fetchWSDL($this->wsdlFile);
7384
+ $this->checkWSDL();
7385
+ }
7386
+
7387
+ /**
7388
+ * get available data pertaining to an operation
7389
+ *
7390
+ * @param string $operation operation name
7391
+ * @return array array of data pertaining to the operation
7392
+ * @access public
7393
+ */
7394
+ function getOperationData($operation){
7395
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7396
+ $this->loadWSDL();
7397
+ if ($this->getError())
7398
+ return false;
7399
+ }
7400
+ if(isset($this->operations[$operation])){
7401
+ return $this->operations[$operation];
7402
+ }
7403
+ $this->debug("No data for operation: $operation");
7404
+ }
7405
+
7406
+ /**
7407
+ * send the SOAP message
7408
+ *
7409
+ * Note: if the operation has multiple return values
7410
+ * the return value of this method will be an array
7411
+ * of those values.
7412
+ *
7413
+ * @param string $msg a SOAPx4 soapmsg object
7414
+ * @param string $soapaction SOAPAction value
7415
+ * @param integer $timeout set connection timeout in seconds
7416
+ * @param integer $response_timeout set response timeout in seconds
7417
+ * @return mixed native PHP types.
7418
+ * @access private
7419
+ */
7420
+ function send($msg, $soapaction = '', $timeout=0, $response_timeout=30) {
7421
+ $this->checkCookies();
7422
+ // detect transport
7423
+ switch(true){
7424
+ // http(s)
7425
+ case ereg('^http',$this->endpoint):
7426
+ $this->debug('transporting via HTTP');
7427
+ if($this->persistentConnection == true && is_object($this->persistentConnection)){
7428
+ $http =& $this->persistentConnection;
7429
+ } else {
7430
+ $http = new soap_transport_http($this->endpoint, $this->curl_options, $this->use_curl);
7431
+ if ($this->persistentConnection) {
7432
+ $http->usePersistentConnection();
7433
+ }
7434
+ }
7435
+ $http->setContentType($this->getHTTPContentType(), $this->getHTTPContentTypeCharset());
7436
+ $http->setSOAPAction($soapaction);
7437
+ if($this->proxyhost && $this->proxyport){
7438
+ $http->setProxy($this->proxyhost,$this->proxyport,$this->proxyusername,$this->proxypassword);
7439
+ }
7440
+ if($this->authtype != '') {
7441
+ $http->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
7442
+ }
7443
+ if($this->http_encoding != ''){
7444
+ $http->setEncoding($this->http_encoding);
7445
+ }
7446
+ $this->debug('sending message, length='.strlen($msg));
7447
+ if(ereg('^http:',$this->endpoint)){
7448
+ //if(strpos($this->endpoint,'http:')){
7449
+ $this->responseData = $http->send($msg,$timeout,$response_timeout,$this->cookies);
7450
+ } elseif(ereg('^https',$this->endpoint)){
7451
+ //} elseif(strpos($this->endpoint,'https:')){
7452
+ //if(phpversion() == '4.3.0-dev'){
7453
+ //$response = $http->send($msg,$timeout,$response_timeout);
7454
+ //$this->request = $http->outgoing_payload;
7455
+ //$this->response = $http->incoming_payload;
7456
+ //} else
7457
+ $this->responseData = $http->sendHTTPS($msg,$timeout,$response_timeout,$this->cookies);
7458
+ } else {
7459
+ $this->setError('no http/s in endpoint url');
7460
+ }
7461
+ $this->request = $http->outgoing_payload;
7462
+ $this->response = $http->incoming_payload;
7463
+ $this->appendDebug($http->getDebug());
7464
+ $this->UpdateCookies($http->incoming_cookies);
7465
+
7466
+ // save transport object if using persistent connections
7467
+ if ($this->persistentConnection) {
7468
+ $http->clearDebug();
7469
+ if (!is_object($this->persistentConnection)) {
7470
+ $this->persistentConnection = $http;
7471
+ }
7472
+ }
7473
+
7474
+ if($err = $http->getError()){
7475
+ $this->setError('HTTP Error: '.$err);
7476
+ return false;
7477
+ } elseif($this->getError()){
7478
+ return false;
7479
+ } else {
7480
+ $this->debug('got response, length='. strlen($this->responseData).' type='.$http->incoming_headers['content-type']);
7481
+ return $this->parseResponse($http->incoming_headers, $this->responseData);
7482
+ }
7483
+ break;
7484
+ default:
7485
+ $this->setError('no transport found, or selected transport is not yet supported!');
7486
+ return false;
7487
+ break;
7488
+ }
7489
+ }
7490
+
7491
+ /**
7492
+ * processes SOAP message returned from server
7493
+ *
7494
+ * @param array $headers The HTTP headers
7495
+ * @param string $data unprocessed response data from server
7496
+ * @return mixed value of the message, decoded into a PHP type
7497
+ * @access private
7498
+ */
7499
+ function parseResponse($headers, $data) {
7500
+ $this->debug('Entering parseResponse() for data of length ' . strlen($data) . ' headers:');
7501
+ $this->appendDebug($this->varDump($headers));
7502
+ if (!strstr($headers['content-type'], 'text/xml')) {
7503
+ $this->setError('Response not of type text/xml: ' . $headers['content-type']);
7504
+ return false;
7505
+ }
7506
+ if (strpos($headers['content-type'], '=')) {
7507
+ $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
7508
+ $this->debug('Got response encoding: ' . $enc);
7509
+ if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){
7510
+ $this->xml_encoding = strtoupper($enc);
7511
+ } else {
7512
+ $this->xml_encoding = 'US-ASCII';
7513
+ }
7514
+ } else {
7515
+ // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
7516
+ $this->xml_encoding = 'ISO-8859-1';
7517
+ }
7518
+ $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
7519
+ $parser = new nusoap_parser($data,$this->xml_encoding,$this->operation,$this->decode_utf8);
7520
+ // add parser debug data to our debug
7521
+ $this->appendDebug($parser->getDebug());
7522
+ // if parse errors
7523
+ if($errstr = $parser->getError()){
7524
+ $this->setError( $errstr);
7525
+ // destroy the parser object
7526
+ unset($parser);
7527
+ return false;
7528
+ } else {
7529
+ // get SOAP headers
7530
+ $this->responseHeaders = $parser->getHeaders();
7531
+ // get SOAP headers
7532
+ $this->responseHeader = $parser->get_soapheader();
7533
+ // get decoded message
7534
+ $return = $parser->get_soapbody();
7535
+ // add document for doclit support
7536
+ $this->document = $parser->document;
7537
+ // destroy the parser object
7538
+ unset($parser);
7539
+ // return decode message
7540
+ return $return;
7541
+ }
7542
+ }
7543
+
7544
+ /**
7545
+ * sets user-specified cURL options
7546
+ *
7547
+ * @param mixed $option The cURL option (always integer?)
7548
+ * @param mixed $value The cURL option value
7549
+ * @access public
7550
+ */
7551
+ function setCurlOption($option, $value) {
7552
+ $this->debug("setCurlOption option=$option, value=");
7553
+ $this->appendDebug($this->varDump($value));
7554
+ $this->curl_options[$option] = $value;
7555
+ }
7556
+
7557
+ /**
7558
+ * sets the SOAP endpoint, which can override WSDL
7559
+ *
7560
+ * @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
7561
+ * @access public
7562
+ */
7563
+ function setEndpoint($endpoint) {
7564
+ $this->debug("setEndpoint(\"$endpoint\")");
7565
+ $this->forceEndpoint = $endpoint;
7566
+ }
7567
+
7568
+ /**
7569
+ * set the SOAP headers
7570
+ *
7571
+ * @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
7572
+ * @access public
7573
+ */
7574
+ function setHeaders($headers){
7575
+ $this->debug("setHeaders headers=");
7576
+ $this->appendDebug($this->varDump($headers));
7577
+ $this->requestHeaders = $headers;
7578
+ }
7579
+
7580
+ /**
7581
+ * get the SOAP response headers (namespace resolution incomplete)
7582
+ *
7583
+ * @return string
7584
+ * @access public
7585
+ */
7586
+ function getHeaders(){
7587
+ return $this->responseHeaders;
7588
+ }
7589
+
7590
+ /**
7591
+ * get the SOAP response Header (parsed)
7592
+ *
7593
+ * @return mixed
7594
+ * @access public
7595
+ */
7596
+ function getHeader(){
7597
+ return $this->responseHeader;
7598
+ }
7599
+
7600
+ /**
7601
+ * set proxy info here
7602
+ *
7603
+ * @param string $proxyhost
7604
+ * @param string $proxyport
7605
+ * @param string $proxyusername
7606
+ * @param string $proxypassword
7607
+ * @access public
7608
+ */
7609
+ function setHTTPProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '') {
7610
+ $this->proxyhost = $proxyhost;
7611
+ $this->proxyport = $proxyport;
7612
+ $this->proxyusername = $proxyusername;
7613
+ $this->proxypassword = $proxypassword;
7614
+ }
7615
+
7616
+ /**
7617
+ * if authenticating, set user credentials here
7618
+ *
7619
+ * @param string $username
7620
+ * @param string $password
7621
+ * @param string $authtype (basic|digest|certificate|ntlm)
7622
+ * @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
7623
+ * @access public
7624
+ */
7625
+ function setCredentials($username, $password, $authtype = 'basic', $certRequest = array()) {
7626
+ $this->debug("setCredentials username=$username authtype=$authtype certRequest=");
7627
+ $this->appendDebug($this->varDump($certRequest));
7628
+ $this->username = $username;
7629
+ $this->password = $password;
7630
+ $this->authtype = $authtype;
7631
+ $this->certRequest = $certRequest;
7632
+ }
7633
+
7634
+ /**
7635
+ * use HTTP encoding
7636
+ *
7637
+ * @param string $enc HTTP encoding
7638
+ * @access public
7639
+ */
7640
+ function setHTTPEncoding($enc='gzip, deflate'){
7641
+ $this->debug("setHTTPEncoding(\"$enc\")");
7642
+ $this->http_encoding = $enc;
7643
+ }
7644
+
7645
+ /**
7646
+ * Set whether to try to use cURL connections if possible
7647
+ *
7648
+ * @param boolean $use Whether to try to use cURL
7649
+ * @access public
7650
+ */
7651
+ function setUseCURL($use) {
7652
+ $this->debug("setUseCURL($use)");
7653
+ $this->use_curl = $use;
7654
+ }
7655
+
7656
+ /**
7657
+ * use HTTP persistent connections if possible
7658
+ *
7659
+ * @access public
7660
+ */
7661
+ function useHTTPPersistentConnection(){
7662
+ $this->debug("useHTTPPersistentConnection");
7663
+ $this->persistentConnection = true;
7664
+ }
7665
+
7666
+ /**
7667
+ * gets the default RPC parameter setting.
7668
+ * If true, default is that call params are like RPC even for document style.
7669
+ * Each call() can override this value.
7670
+ *
7671
+ * This is no longer used.
7672
+ *
7673
+ * @return boolean
7674
+ * @access public
7675
+ * @deprecated
7676
+ */
7677
+ function getDefaultRpcParams() {
7678
+ return $this->defaultRpcParams;
7679
+ }
7680
+
7681
+ /**
7682
+ * sets the default RPC parameter setting.
7683
+ * If true, default is that call params are like RPC even for document style
7684
+ * Each call() can override this value.
7685
+ *
7686
+ * This is no longer used.
7687
+ *
7688
+ * @param boolean $rpcParams
7689
+ * @access public
7690
+ * @deprecated
7691
+ */
7692
+ function setDefaultRpcParams($rpcParams) {
7693
+ $this->defaultRpcParams = $rpcParams;
7694
+ }
7695
+
7696
+ /**
7697
+ * dynamically creates an instance of a proxy class,
7698
+ * allowing user to directly call methods from wsdl
7699
+ *
7700
+ * @return object soap_proxy object
7701
+ * @access public
7702
+ */
7703
+ function getProxy() {
7704
+ $r = rand();
7705
+ $evalStr = $this->_getProxyClassCode($r);
7706
+ //$this->debug("proxy class: $evalStr");
7707
+ if ($this->getError()) {
7708
+ $this->debug("Error from _getProxyClassCode, so return NULL");
7709
+ return null;
7710
+ }
7711
+ // eval the class
7712
+ eval($evalStr);
7713
+ // instantiate proxy object
7714
+ eval("\$proxy = new nusoap_proxy_$r('');");
7715
+ // transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
7716
+ $proxy->endpointType = 'wsdl';
7717
+ $proxy->wsdlFile = $this->wsdlFile;
7718
+ $proxy->wsdl = $this->wsdl;
7719
+ $proxy->operations = $this->operations;
7720
+ $proxy->defaultRpcParams = $this->defaultRpcParams;
7721
+ // transfer other state
7722
+ $proxy->soap_defencoding = $this->soap_defencoding;
7723
+ $proxy->username = $this->username;
7724
+ $proxy->password = $this->password;
7725
+ $proxy->authtype = $this->authtype;
7726
+ $proxy->certRequest = $this->certRequest;
7727
+ $proxy->requestHeaders = $this->requestHeaders;
7728
+ $proxy->endpoint = $this->endpoint;
7729
+ $proxy->forceEndpoint = $this->forceEndpoint;
7730
+ $proxy->proxyhost = $this->proxyhost;
7731
+ $proxy->proxyport = $this->proxyport;
7732
+ $proxy->proxyusername = $this->proxyusername;
7733
+ $proxy->proxypassword = $this->proxypassword;
7734
+ $proxy->http_encoding = $this->http_encoding;
7735
+ $proxy->timeout = $this->timeout;
7736
+ $proxy->response_timeout = $this->response_timeout;
7737
+ $proxy->persistentConnection = &$this->persistentConnection;
7738
+ $proxy->decode_utf8 = $this->decode_utf8;
7739
+ $proxy->curl_options = $this->curl_options;
7740
+ $proxy->bindingType = $this->bindingType;
7741
+ $proxy->use_curl = $this->use_curl;
7742
+ return $proxy;
7743
+ }
7744
+
7745
+ /**
7746
+ * dynamically creates proxy class code
7747
+ *
7748
+ * @return string PHP/NuSOAP code for the proxy class
7749
+ * @access private
7750
+ */
7751
+ function _getProxyClassCode($r) {
7752
+ $this->debug("in getProxy endpointType=$this->endpointType");
7753
+ $this->appendDebug("wsdl=" . $this->varDump($this->wsdl));
7754
+ if ($this->endpointType != 'wsdl') {
7755
+ $evalStr = 'A proxy can only be created for a WSDL client';
7756
+ $this->setError($evalStr);
7757
+ $evalStr = "echo \"$evalStr\";";
7758
+ return $evalStr;
7759
+ }
7760
+ if ($this->endpointType == 'wsdl' && is_null($this->wsdl)) {
7761
+ $this->loadWSDL();
7762
+ if ($this->getError()) {
7763
+ return "echo \"" . $this->getError() . "\";";
7764
+ }
7765
+ }
7766
+ $evalStr = '';
7767
+ foreach ($this->operations as $operation => $opData) {
7768
+ if ($operation != '') {
7769
+ // create param string and param comment string
7770
+ if (sizeof($opData['input']['parts']) > 0) {
7771
+ $paramStr = '';
7772
+ $paramArrayStr = '';
7773
+ $paramCommentStr = '';
7774
+ foreach ($opData['input']['parts'] as $name => $type) {
7775
+ $paramStr .= "\$$name, ";
7776
+ $paramArrayStr .= "'$name' => \$$name, ";
7777
+ $paramCommentStr .= "$type \$$name, ";
7778
+ }
7779
+ $paramStr = substr($paramStr, 0, strlen($paramStr)-2);
7780
+ $paramArrayStr = substr($paramArrayStr, 0, strlen($paramArrayStr)-2);
7781
+ $paramCommentStr = substr($paramCommentStr, 0, strlen($paramCommentStr)-2);
7782
+ } else {
7783
+ $paramStr = '';
7784
+ $paramArrayStr = '';
7785
+ $paramCommentStr = 'void';
7786
+ }
7787
+ $opData['namespace'] = !isset($opData['namespace']) ? 'http://testuri.com' : $opData['namespace'];
7788
+ $evalStr .= "// $paramCommentStr
7789
+ function " . str_replace('.', '__', $operation) . "($paramStr) {
7790
+ \$params = array($paramArrayStr);
7791
+ return \$this->call('$operation', \$params, '".$opData['namespace']."', '".(isset($opData['soapAction']) ? $opData['soapAction'] : '')."');
7792
+ }
7793
+ ";
7794
+ unset($paramStr);
7795
+ unset($paramCommentStr);
7796
+ }
7797
+ }
7798
+ $evalStr = 'class nusoap_proxy_'.$r.' extends nusoap_client {
7799
+ '.$evalStr.'
7800
+ }';
7801
+ return $evalStr;
7802
+ }
7803
+
7804
+ /**
7805
+ * dynamically creates proxy class code
7806
+ *
7807
+ * @return string PHP/NuSOAP code for the proxy class
7808
+ * @access public
7809
+ */
7810
+ function getProxyClassCode() {
7811
+ $r = rand();
7812
+ return $this->_getProxyClassCode($r);
7813
+ }
7814
+
7815
+ /**
7816
+ * gets the HTTP body for the current request.
7817
+ *
7818
+ * @param string $soapmsg The SOAP payload
7819
+ * @return string The HTTP body, which includes the SOAP payload
7820
+ * @access private
7821
+ */
7822
+ function getHTTPBody($soapmsg) {
7823
+ return $soapmsg;
7824
+ }
7825
+
7826
+ /**
7827
+ * gets the HTTP content type for the current request.
7828
+ *
7829
+ * Note: getHTTPBody must be called before this.
7830
+ *
7831
+ * @return string the HTTP content type for the current request.
7832
+ * @access private
7833
+ */
7834
+ function getHTTPContentType() {
7835
+ return 'text/xml';
7836
+ }
7837
+
7838
+ /**
7839
+ * gets the HTTP content type charset for the current request.
7840
+ * returns false for non-text content types.
7841
+ *
7842
+ * Note: getHTTPBody must be called before this.
7843
+ *
7844
+ * @return string the HTTP content type charset for the current request.
7845
+ * @access private
7846
+ */
7847
+ function getHTTPContentTypeCharset() {
7848
+ return $this->soap_defencoding;
7849
+ }
7850
+
7851
+ /*
7852
+ * whether or not parser should decode utf8 element content
7853
+ *
7854
+ * @return always returns true
7855
+ * @access public
7856
+ */
7857
+ function decodeUTF8($bool){
7858
+ $this->decode_utf8 = $bool;
7859
+ return true;
7860
+ }
7861
+
7862
+ /**
7863
+ * adds a new Cookie into $this->cookies array
7864
+ *
7865
+ * @param string $name Cookie Name
7866
+ * @param string $value Cookie Value
7867
+ * @return boolean if cookie-set was successful returns true, else false
7868
+ * @access public
7869
+ */
7870
+ function setCookie($name, $value) {
7871
+ if (strlen($name) == 0) {
7872
+ return false;
7873
+ }
7874
+ $this->cookies[] = array('name' => $name, 'value' => $value);
7875
+ return true;
7876
+ }
7877
+
7878
+ /**
7879
+ * gets all Cookies
7880
+ *
7881
+ * @return array with all internal cookies
7882
+ * @access public
7883
+ */
7884
+ function getCookies() {
7885
+ return $this->cookies;
7886
+ }
7887
+
7888
+ /**
7889
+ * checks all Cookies and delete those which are expired
7890
+ *
7891
+ * @return boolean always return true
7892
+ * @access private
7893
+ */
7894
+ function checkCookies() {
7895
+ if (sizeof($this->cookies) == 0) {
7896
+ return true;
7897
+ }
7898
+ $this->debug('checkCookie: check ' . sizeof($this->cookies) . ' cookies');
7899
+ $curr_cookies = $this->cookies;
7900
+ $this->cookies = array();
7901
+ foreach ($curr_cookies as $cookie) {
7902
+ if (! is_array($cookie)) {
7903
+ $this->debug('Remove cookie that is not an array');
7904
+ continue;
7905
+ }
7906
+ if ((isset($cookie['expires'])) && (! empty($cookie['expires']))) {
7907
+ if (strtotime($cookie['expires']) > time()) {
7908
+ $this->cookies[] = $cookie;
7909
+ } else {
7910
+ $this->debug('Remove expired cookie ' . $cookie['name']);
7911
+ }
7912
+ } else {
7913
+ $this->cookies[] = $cookie;
7914
+ }
7915
+ }
7916
+ $this->debug('checkCookie: '.sizeof($this->cookies).' cookies left in array');
7917
+ return true;
7918
+ }
7919
+
7920
+ /**
7921
+ * updates the current cookies with a new set
7922
+ *
7923
+ * @param array $cookies new cookies with which to update current ones
7924
+ * @return boolean always return true
7925
+ * @access private
7926
+ */
7927
+ function UpdateCookies($cookies) {
7928
+ if (sizeof($this->cookies) == 0) {
7929
+ // no existing cookies: take whatever is new
7930
+ if (sizeof($cookies) > 0) {
7931
+ $this->debug('Setting new cookie(s)');
7932
+ $this->cookies = $cookies;
7933
+ }
7934
+ return true;
7935
+ }
7936
+ if (sizeof($cookies) == 0) {
7937
+ // no new cookies: keep what we've got
7938
+ return true;
7939
+ }
7940
+ // merge
7941
+ foreach ($cookies as $newCookie) {
7942
+ if (!is_array($newCookie)) {
7943
+ continue;
7944
+ }
7945
+ if ((!isset($newCookie['name'])) || (!isset($newCookie['value']))) {
7946
+ continue;
7947
+ }
7948
+ $newName = $newCookie['name'];
7949
+
7950
+ $found = false;
7951
+ for ($i = 0; $i < count($this->cookies); $i++) {
7952
+ $cookie = $this->cookies[$i];
7953
+ if (!is_array($cookie)) {
7954
+ continue;
7955
+ }
7956
+ if (!isset($cookie['name'])) {
7957
+ continue;
7958
+ }
7959
+ if ($newName != $cookie['name']) {
7960
+ continue;
7961
+ }
7962
+ $newDomain = isset($newCookie['domain']) ? $newCookie['domain'] : 'NODOMAIN';
7963
+ $domain = isset($cookie['domain']) ? $cookie['domain'] : 'NODOMAIN';
7964
+ if ($newDomain != $domain) {
7965
+ continue;
7966
+ }
7967
+ $newPath = isset($newCookie['path']) ? $newCookie['path'] : 'NOPATH';
7968
+ $path = isset($cookie['path']) ? $cookie['path'] : 'NOPATH';
7969
+ if ($newPath != $path) {
7970
+ continue;
7971
+ }
7972
+ $this->cookies[$i] = $newCookie;
7973
+ $found = true;
7974
+ $this->debug('Update cookie ' . $newName . '=' . $newCookie['value']);
7975
+ break;
7976
+ }
7977
+ if (! $found) {
7978
+ $this->debug('Add cookie ' . $newName . '=' . $newCookie['value']);
7979
+ $this->cookies[] = $newCookie;
7980
+ }
7981
+ }
7982
+ return true;
7983
+ }
7984
+ }
7985
+
7986
+ /*if (!extension_loaded('soap')) {
7987
+ /**
7988
+ * For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
7989
+ *
7990
+ class soapclient extends nusoap_client {
7991
+ }
7992
+ }*/
7993
+ ?>
app/code/community/Easy/CEM/Model/Soap/nusoapmime.php ADDED
@@ -0,0 +1,501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
4
+
5
+ NuSOAP - Web Services Toolkit for PHP
6
+
7
+ Copyright (c) 2002 NuSphere Corporation
8
+
9
+ This library is free software; you can redistribute it and/or
10
+ modify it under the terms of the GNU Lesser General Public
11
+ License as published by the Free Software Foundation; either
12
+ version 2.1 of the License, or (at your option) any later version.
13
+
14
+ This library is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ Lesser General Public License for more details.
18
+
19
+ You should have received a copy of the GNU Lesser General Public
20
+ License along with this library; if not, write to the Free Software
21
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
+
23
+ The NuSOAP project home is:
24
+ http://sourceforge.net/projects/nusoap/
25
+
26
+ The primary support for NuSOAP is the mailing list:
27
+ nusoap-general@lists.sourceforge.net
28
+
29
+ If you have any questions or comments, please email:
30
+
31
+ Dietrich Ayala
32
+ dietrich@ganx4.com
33
+ http://dietrich.ganx4.com/nusoap
34
+
35
+ NuSphere Corporation
36
+ http://www.nusphere.com
37
+
38
+ */
39
+
40
+ /*require_once('nusoap.php');*/
41
+ /* PEAR Mail_MIME library */
42
+ require_once('Mail/mimeDecode.php');
43
+ require_once('Mail/mimePart.php');
44
+
45
+ /**
46
+ * nusoap_client_mime client supporting MIME attachments defined at
47
+ * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
48
+ *
49
+ * @author Scott Nichol <snichol@users.sourceforge.net>
50
+ * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
51
+ * @version $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
52
+ * @access public
53
+ */
54
+ class nusoap_client_mime extends nusoap_client {
55
+ /**
56
+ * @var array Each array element in the return is an associative array with keys
57
+ * data, filename, contenttype, cid
58
+ * @access private
59
+ */
60
+ var $requestAttachments = array();
61
+ /**
62
+ * @var array Each array element in the return is an associative array with keys
63
+ * data, filename, contenttype, cid
64
+ * @access private
65
+ */
66
+ var $responseAttachments;
67
+ /**
68
+ * @var string
69
+ * @access private
70
+ */
71
+ var $mimeContentType;
72
+
73
+ /**
74
+ * adds a MIME attachment to the current request.
75
+ *
76
+ * If the $data parameter contains an empty string, this method will read
77
+ * the contents of the file named by the $filename parameter.
78
+ *
79
+ * If the $cid parameter is false, this method will generate the cid.
80
+ *
81
+ * @param string $data The data of the attachment
82
+ * @param string $filename The filename of the attachment (default is empty string)
83
+ * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
84
+ * @param string $cid The content-id (cid) of the attachment (default is false)
85
+ * @return string The content-id (cid) of the attachment
86
+ * @access public
87
+ */
88
+ function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
89
+ if (! $cid) {
90
+ $cid = md5(uniqid(time()));
91
+ }
92
+
93
+ $info['data'] = $data;
94
+ $info['filename'] = $filename;
95
+ $info['contenttype'] = $contenttype;
96
+ $info['cid'] = $cid;
97
+
98
+ $this->requestAttachments[] = $info;
99
+
100
+ return $cid;
101
+ }
102
+
103
+ /**
104
+ * clears the MIME attachments for the current request.
105
+ *
106
+ * @access public
107
+ */
108
+ function clearAttachments() {
109
+ $this->requestAttachments = array();
110
+ }
111
+
112
+ /**
113
+ * gets the MIME attachments from the current response.
114
+ *
115
+ * Each array element in the return is an associative array with keys
116
+ * data, filename, contenttype, cid. These keys correspond to the parameters
117
+ * for addAttachment.
118
+ *
119
+ * @return array The attachments.
120
+ * @access public
121
+ */
122
+ function getAttachments() {
123
+ return $this->responseAttachments;
124
+ }
125
+
126
+ /**
127
+ * gets the HTTP body for the current request.
128
+ *
129
+ * @param string $soapmsg The SOAP payload
130
+ * @return string The HTTP body, which includes the SOAP payload
131
+ * @access private
132
+ */
133
+ function getHTTPBody($soapmsg) {
134
+ if (count($this->requestAttachments) > 0) {
135
+ $params['content_type'] = 'multipart/related; type="text/xml"';
136
+ $mimeMessage =& new Mail_mimePart('', $params);
137
+ unset($params);
138
+
139
+ $params['content_type'] = 'text/xml';
140
+ $params['encoding'] = '8bit';
141
+ $params['charset'] = $this->soap_defencoding;
142
+ $mimeMessage->addSubpart($soapmsg, $params);
143
+
144
+ foreach ($this->requestAttachments as $att) {
145
+ unset($params);
146
+
147
+ $params['content_type'] = $att['contenttype'];
148
+ $params['encoding'] = 'base64';
149
+ $params['disposition'] = 'attachment';
150
+ $params['dfilename'] = $att['filename'];
151
+ $params['cid'] = $att['cid'];
152
+
153
+ if ($att['data'] == '' && $att['filename'] <> '') {
154
+ if ($fd = fopen($att['filename'], 'rb')) {
155
+ $data = fread($fd, filesize($att['filename']));
156
+ fclose($fd);
157
+ } else {
158
+ $data = '';
159
+ }
160
+ $mimeMessage->addSubpart($data, $params);
161
+ } else {
162
+ $mimeMessage->addSubpart($att['data'], $params);
163
+ }
164
+ }
165
+
166
+ $output = $mimeMessage->encode();
167
+ $mimeHeaders = $output['headers'];
168
+
169
+ foreach ($mimeHeaders as $k => $v) {
170
+ $this->debug("MIME header $k: $v");
171
+ if (strtolower($k) == 'content-type') {
172
+ // PHP header() seems to strip leading whitespace starting
173
+ // the second line, so force everything to one line
174
+ $this->mimeContentType = str_replace("\r\n", " ", $v);
175
+ }
176
+ }
177
+
178
+ return $output['body'];
179
+ }
180
+
181
+ return parent::getHTTPBody($soapmsg);
182
+ }
183
+
184
+ /**
185
+ * gets the HTTP content type for the current request.
186
+ *
187
+ * Note: getHTTPBody must be called before this.
188
+ *
189
+ * @return string the HTTP content type for the current request.
190
+ * @access private
191
+ */
192
+ function getHTTPContentType() {
193
+ if (count($this->requestAttachments) > 0) {
194
+ return $this->mimeContentType;
195
+ }
196
+ return parent::getHTTPContentType();
197
+ }
198
+
199
+ /**
200
+ * gets the HTTP content type charset for the current request.
201
+ * returns false for non-text content types.
202
+ *
203
+ * Note: getHTTPBody must be called before this.
204
+ *
205
+ * @return string the HTTP content type charset for the current request.
206
+ * @access private
207
+ */
208
+ function getHTTPContentTypeCharset() {
209
+ if (count($this->requestAttachments) > 0) {
210
+ return false;
211
+ }
212
+ return parent::getHTTPContentTypeCharset();
213
+ }
214
+
215
+ /**
216
+ * processes SOAP message returned from server
217
+ *
218
+ * @param array $headers The HTTP headers
219
+ * @param string $data unprocessed response data from server
220
+ * @return mixed value of the message, decoded into a PHP type
221
+ * @access private
222
+ */
223
+ function parseResponse($headers, $data) {
224
+ $this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
225
+ $this->responseAttachments = array();
226
+ if (strstr($headers['content-type'], 'multipart/related')) {
227
+ $this->debug('Decode multipart/related');
228
+ $input = '';
229
+ foreach ($headers as $k => $v) {
230
+ $input .= "$k: $v\r\n";
231
+ }
232
+ $params['input'] = $input . "\r\n" . $data;
233
+ $params['include_bodies'] = true;
234
+ $params['decode_bodies'] = true;
235
+ $params['decode_headers'] = true;
236
+
237
+ $structure = Mail_mimeDecode::decode($params);
238
+
239
+ foreach ($structure->parts as $part) {
240
+ if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
241
+ $this->debug('Have root part of type ' . $part->headers['content-type']);
242
+ $root = $part->body;
243
+ $return = parent::parseResponse($part->headers, $part->body);
244
+ } else {
245
+ $this->debug('Have an attachment of type ' . $part->headers['content-type']);
246
+ $info['data'] = $part->body;
247
+ $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
248
+ $info['contenttype'] = $part->headers['content-type'];
249
+ $info['cid'] = $part->headers['content-id'];
250
+ $this->responseAttachments[] = $info;
251
+ }
252
+ }
253
+
254
+ if (isset($return)) {
255
+ $this->responseData = $root;
256
+ return $return;
257
+ }
258
+
259
+ $this->setError('No root part found in multipart/related content');
260
+ return '';
261
+ }
262
+ $this->debug('Not multipart/related');
263
+ return parent::parseResponse($headers, $data);
264
+ }
265
+ }
266
+
267
+ /*
268
+ * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
269
+ */
270
+ if (!extension_loaded('soap')) {
271
+ class soapclientmime extends nusoap_client_mime {
272
+ }
273
+ }
274
+
275
+ /**
276
+ * nusoap_server_mime server supporting MIME attachments defined at
277
+ * http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
278
+ *
279
+ * @author Scott Nichol <snichol@users.sourceforge.net>
280
+ * @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
281
+ * @version $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
282
+ * @access public
283
+ */
284
+ class nusoap_server_mime extends nusoap_server {
285
+ /**
286
+ * @var array Each array element in the return is an associative array with keys
287
+ * data, filename, contenttype, cid
288
+ * @access private
289
+ */
290
+ var $requestAttachments = array();
291
+ /**
292
+ * @var array Each array element in the return is an associative array with keys
293
+ * data, filename, contenttype, cid
294
+ * @access private
295
+ */
296
+ var $responseAttachments;
297
+ /**
298
+ * @var string
299
+ * @access private
300
+ */
301
+ var $mimeContentType;
302
+
303
+ /**
304
+ * adds a MIME attachment to the current response.
305
+ *
306
+ * If the $data parameter contains an empty string, this method will read
307
+ * the contents of the file named by the $filename parameter.
308
+ *
309
+ * If the $cid parameter is false, this method will generate the cid.
310
+ *
311
+ * @param string $data The data of the attachment
312
+ * @param string $filename The filename of the attachment (default is empty string)
313
+ * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
314
+ * @param string $cid The content-id (cid) of the attachment (default is false)
315
+ * @return string The content-id (cid) of the attachment
316
+ * @access public
317
+ */
318
+ function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
319
+ if (! $cid) {
320
+ $cid = md5(uniqid(time()));
321
+ }
322
+
323
+ $info['data'] = $data;
324
+ $info['filename'] = $filename;
325
+ $info['contenttype'] = $contenttype;
326
+ $info['cid'] = $cid;
327
+
328
+ $this->responseAttachments[] = $info;
329
+
330
+ return $cid;
331
+ }
332
+
333
+ /**
334
+ * clears the MIME attachments for the current response.
335
+ *
336
+ * @access public
337
+ */
338
+ function clearAttachments() {
339
+ $this->responseAttachments = array();
340
+ }
341
+
342
+ /**
343
+ * gets the MIME attachments from the current request.
344
+ *
345
+ * Each array element in the return is an associative array with keys
346
+ * data, filename, contenttype, cid. These keys correspond to the parameters
347
+ * for addAttachment.
348
+ *
349
+ * @return array The attachments.
350
+ * @access public
351
+ */
352
+ function getAttachments() {
353
+ return $this->requestAttachments;
354
+ }
355
+
356
+ /**
357
+ * gets the HTTP body for the current response.
358
+ *
359
+ * @param string $soapmsg The SOAP payload
360
+ * @return string The HTTP body, which includes the SOAP payload
361
+ * @access private
362
+ */
363
+ function getHTTPBody($soapmsg) {
364
+ if (count($this->responseAttachments) > 0) {
365
+ $params['content_type'] = 'multipart/related; type="text/xml"';
366
+ $mimeMessage =& new Mail_mimePart('', $params);
367
+ unset($params);
368
+
369
+ $params['content_type'] = 'text/xml';
370
+ $params['encoding'] = '8bit';
371
+ $params['charset'] = $this->soap_defencoding;
372
+ $mimeMessage->addSubpart($soapmsg, $params);
373
+
374
+ foreach ($this->responseAttachments as $att) {
375
+ unset($params);
376
+
377
+ $params['content_type'] = $att['contenttype'];
378
+ $params['encoding'] = 'base64';
379
+ $params['disposition'] = 'attachment';
380
+ $params['dfilename'] = $att['filename'];
381
+ $params['cid'] = $att['cid'];
382
+
383
+ if ($att['data'] == '' && $att['filename'] <> '') {
384
+ if ($fd = fopen($att['filename'], 'rb')) {
385
+ $data = fread($fd, filesize($att['filename']));
386
+ fclose($fd);
387
+ } else {
388
+ $data = '';
389
+ }
390
+ $mimeMessage->addSubpart($data, $params);
391
+ } else {
392
+ $mimeMessage->addSubpart($att['data'], $params);
393
+ }
394
+ }
395
+
396
+ $output = $mimeMessage->encode();
397
+ $mimeHeaders = $output['headers'];
398
+
399
+ foreach ($mimeHeaders as $k => $v) {
400
+ $this->debug("MIME header $k: $v");
401
+ if (strtolower($k) == 'content-type') {
402
+ // PHP header() seems to strip leading whitespace starting
403
+ // the second line, so force everything to one line
404
+ $this->mimeContentType = str_replace("\r\n", " ", $v);
405
+ }
406
+ }
407
+
408
+ return $output['body'];
409
+ }
410
+
411
+ return parent::getHTTPBody($soapmsg);
412
+ }
413
+
414
+ /**
415
+ * gets the HTTP content type for the current response.
416
+ *
417
+ * Note: getHTTPBody must be called before this.
418
+ *
419
+ * @return string the HTTP content type for the current response.
420
+ * @access private
421
+ */
422
+ function getHTTPContentType() {
423
+ if (count($this->responseAttachments) > 0) {
424
+ return $this->mimeContentType;
425
+ }
426
+ return parent::getHTTPContentType();
427
+ }
428
+
429
+ /**
430
+ * gets the HTTP content type charset for the current response.
431
+ * returns false for non-text content types.
432
+ *
433
+ * Note: getHTTPBody must be called before this.
434
+ *
435
+ * @return string the HTTP content type charset for the current response.
436
+ * @access private
437
+ */
438
+ function getHTTPContentTypeCharset() {
439
+ if (count($this->responseAttachments) > 0) {
440
+ return false;
441
+ }
442
+ return parent::getHTTPContentTypeCharset();
443
+ }
444
+
445
+ /**
446
+ * processes SOAP message received from client
447
+ *
448
+ * @param array $headers The HTTP headers
449
+ * @param string $data unprocessed request data from client
450
+ * @return mixed value of the message, decoded into a PHP type
451
+ * @access private
452
+ */
453
+ function parseRequest($headers, $data) {
454
+ $this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
455
+ $this->requestAttachments = array();
456
+ if (strstr($headers['content-type'], 'multipart/related')) {
457
+ $this->debug('Decode multipart/related');
458
+ $input = '';
459
+ foreach ($headers as $k => $v) {
460
+ $input .= "$k: $v\r\n";
461
+ }
462
+ $params['input'] = $input . "\r\n" . $data;
463
+ $params['include_bodies'] = true;
464
+ $params['decode_bodies'] = true;
465
+ $params['decode_headers'] = true;
466
+
467
+ $structure = Mail_mimeDecode::decode($params);
468
+
469
+ foreach ($structure->parts as $part) {
470
+ if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
471
+ $this->debug('Have root part of type ' . $part->headers['content-type']);
472
+ $return = parent::parseRequest($part->headers, $part->body);
473
+ } else {
474
+ $this->debug('Have an attachment of type ' . $part->headers['content-type']);
475
+ $info['data'] = $part->body;
476
+ $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
477
+ $info['contenttype'] = $part->headers['content-type'];
478
+ $info['cid'] = $part->headers['content-id'];
479
+ $this->requestAttachments[] = $info;
480
+ }
481
+ }
482
+
483
+ if (isset($return)) {
484
+ return $return;
485
+ }
486
+
487
+ $this->setError('No root part found in multipart/related content');
488
+ return;
489
+ }
490
+ $this->debug('Not multipart/related');
491
+ return parent::parseRequest($headers, $data);
492
+ }
493
+ }
494
+
495
+ /*
496
+ * For backwards compatiblity
497
+ */
498
+ class nusoapservermime extends nusoap_server_mime {
499
+ }
500
+
501
+ ?>
app/code/community/Easy/CEM/Model/System/Config/Source/CEM/Frequency.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package Easy_CEM
17
+ * @copyright Copyright (c) 2009 MageParts Crew (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Model_System_Config_Source_CEM_Frequency
22
+ {
23
+ public function toOptionArray()
24
+ {
25
+ return array(
26
+ 1 => Mage::helper('adminhtml')->__('1 Hour'),
27
+ 2 => Mage::helper('adminhtml')->__('2 Hours'),
28
+ 6 => Mage::helper('adminhtml')->__('6 Hours'),
29
+ 12 => Mage::helper('adminhtml')->__('12 Hours'),
30
+ 24 => Mage::helper('adminhtml')->__('24 Hours')
31
+ );
32
+ }
33
+ }
app/code/community/Easy/CEM/controllers/Adminhtml/LicensesController.php ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ /**
22
+ * Error reporting, don't logg any strict errors here it gives us problems with the NuSOAP class
23
+ */
24
+ //error_reporting(E_ALL);
25
+
26
+ class Easy_CEM_Adminhtml_LicensesController extends Mage_Adminhtml_Controller_Action
27
+ {
28
+
29
+ /**
30
+ * Init action
31
+ *
32
+ * Creates breadcrumbs etc.
33
+ */
34
+ public function _initAction()
35
+ {
36
+ $this->loadLayout()
37
+ ->_setActiveMenu('system')
38
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('System'), Mage::helper('adminhtml')->__('System'))
39
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('Magento Connect'), Mage::helper('adminhtml')->__('Magento Connect'))
40
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('Commercial Extension Manager'), Mage::helper('adminhtml')->__('Commercial Extension Manager'));
41
+
42
+ return $this;
43
+ }
44
+
45
+
46
+ /**
47
+ * Index action
48
+ */
49
+ public function indexAction()
50
+ {
51
+ $this->_forward('edit');
52
+ }
53
+
54
+
55
+ /**
56
+ * Redirects a user to the editing area
57
+ */
58
+ public function newAction()
59
+ {
60
+ $this->_forward('edit');
61
+ }
62
+
63
+
64
+ /**
65
+ * Redirects a user to the editing area
66
+ */
67
+ public function editAction()
68
+ {
69
+ // Edit block
70
+ $this->_initAction()
71
+ ->_addBreadcrumb(Mage::helper('cem')->__('License Management'), Mage::helper('cem')->__('License Management'))
72
+ ->_addContent($this->getLayout()->createBlock('cem/adminhtml_licenses_edit'))
73
+ ->_addLeft($this->getLayout()->createBlock('cem/adminhtml_licenses_edit_tabs'))
74
+ ->renderLayout();
75
+ }
76
+
77
+
78
+ /**
79
+ * Request lost CEM key
80
+ */
81
+ public function requestLostCemKeyAction()
82
+ {
83
+ $serviceUrl = $this->getRequest()->getParam('service_url');
84
+
85
+ try {
86
+ if(empty($serviceUrl)) {
87
+ throw new Exception(Mage::helper('cem')->__("Please provide a valid service url"));
88
+ }
89
+
90
+ // Check if url exists
91
+ if(!@fopen($serviceUrl,'r')) {
92
+ throw new Exception(Mage::helper('cem')->__("The provided service url is either invalid or unreachable. Make sure that the service url you provided is correct and try again in a few minutes. If the problem consists we advise you to contact your software retailer for assistance."));
93
+ }
94
+
95
+ // Make SOAP call to recover lost CEM key
96
+ $response = Mage::getModel('cem/soap')->call(
97
+ 'lostCemKey',
98
+ array(
99
+ 'email' => Mage::getStoreConfig('system/cem/email'),
100
+ 'clientHostname' => Mage::getStoreConfig('web/unsecure/base_url')
101
+ ),
102
+ $serviceUrl
103
+ );
104
+
105
+ // Check for soap errors
106
+ if($response->getResults()!==true) {
107
+ if(!$response->getErrorMessage()) {
108
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance."));
109
+ }
110
+ throw new Exception($response->getErrorMessage());
111
+ }
112
+
113
+ // Success
114
+ $this->getResponse()->setBody("SUCCESS");
115
+ return;
116
+ }
117
+ catch (Exception $e) {
118
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
119
+ return;
120
+ }
121
+ }
122
+
123
+
124
+ /**
125
+ * Request lost license key
126
+ */
127
+ public function requestLostLicenseKeyAction()
128
+ {
129
+ $serviceUrl = $this->getRequest()->getParam('service_url');
130
+ $moduleIdentifier = $this->getRequest()->getParam('module_identifier');
131
+
132
+ try {
133
+ // We need these values
134
+ if(empty($serviceUrl) || empty($moduleIdentifier)) {
135
+ throw new Exception(Mage::helper('cem')->__("Please provide a valid service url and module identifier"));
136
+ }
137
+
138
+ // Make sure the service url exists in the database
139
+ if(!$serviceId = Mage::getResourceModel('cem/services')->urlExists($serviceUrl)) {
140
+ throw new Exception(Mage::helper('cem')->__("The provided service url doesn't exists in your database. No matching CEM key was found. You'll have to retrieve your CEM key from the provided service using the 'Lost CEM Key' section before you can retrieve any lost license keys."));
141
+ }
142
+
143
+ // Get CEM key
144
+ if(!$cemKey = Mage::getResourceModel('cem/services')->getCemKey($serviceId)) {
145
+ throw new Exception(Mage::helper('cem')->__("Unable to retrieve any CEM key. Please contact your software retailer for assistance."));
146
+ }
147
+
148
+ // Make SOAP call to recover lost license key
149
+ $response = Mage::getModel('cem/soap')->call(
150
+ 'lostLicenseKey',
151
+ array(
152
+ 'cemKey' => $cemKey,
153
+ 'clientHostname' => Mage::getStoreConfig('web/unsecure/base_url'),
154
+ 'moduleIdentifier' => $moduleIdentifier
155
+ ),
156
+ $serviceUrl
157
+ );
158
+
159
+ // Check for soap errors
160
+ if($response->getResults()!==true) {
161
+ if(!$response->getErrorMessage()) {
162
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance."));
163
+ }
164
+ throw new Exception($response->getErrorMessage());
165
+ }
166
+
167
+ // Success
168
+ $this->getResponse()->setBody("SUCCESS");
169
+ return;
170
+ }
171
+ catch (Exception $e) {
172
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
173
+ return;
174
+ }
175
+ }
176
+
177
+
178
+ /**
179
+ * Request lost CEM key
180
+ */
181
+ public function installCemKeyAction()
182
+ {
183
+ // Gather parameters
184
+ $serviceUrl = $this->getRequest()->getParam('service_url');
185
+ $cemKey = $this->getRequest()->getParam('cem_key');
186
+
187
+ try {
188
+ // We need these values
189
+ if(empty($serviceUrl) || empty($cemKey)) {
190
+ throw new Exception(Mage::helper('cem')->__("Please provide a valid service url and CEM key"));
191
+ }
192
+
193
+ // Get service model / resource model
194
+ $serviceModel = Mage::getModel('cem/services');
195
+ $serviceResourceModel = Mage::getResourceModel('cem/services');
196
+
197
+ // Retrieve existing or create new service id
198
+ $serviceId = 0;
199
+
200
+ if(!$serviceResourceModel->urlExists($serviceUrl)) {
201
+ if(!$serviceModel->setUrl($serviceUrl)->save()) {
202
+ throw new Exception(Mage::helper('cem')->__("Unable to save service information in local database. Please contact your retailer for assistance."));
203
+ }
204
+ $serviceId = $serviceModel->getServiceId();
205
+ }
206
+ else {
207
+ $serviceCollection = $serviceModel->getCollection()
208
+ ->setUrlFilter($serviceUrl)
209
+ ->getFirstItem();
210
+
211
+ if(!$serviceId = $serviceCollection->getServiceId()) {
212
+ throw new Exception(Mage::helper('cem')->__("Unable data recieved from service database. Please contact your software retailer for assistance."));
213
+ }
214
+ }
215
+
216
+ // Check if the CEM key already exists in the database
217
+ $checkCemKeyExists = $serviceResourceModel->getCemKey($serviceId);
218
+
219
+ if(empty($checkCemKeyExists) || !$checkCemKeyExists || $checkCemKeyExists!==$cemKey) {
220
+ // Save CEM key in local database
221
+ if(!$serviceResourceModel->addCemKey(array('service_id' => $serviceId, 'key' => $cemKey))) {
222
+ throw new Exception(Mage::helper('cem')->__("Unable to save CEM key information in local database. Please contact your retailer for assistance."));
223
+ }
224
+ }
225
+
226
+ // Make SOAP call to install CEM key
227
+ $call = Mage::getModel('cem/soap')->call(
228
+ 'gePackagesAndLicensesByCemKey',
229
+ array(
230
+ 'cemKey' => $cemKey,
231
+ 'clientHostname' => Mage::getStoreConfig('web/unsecure/base_url'),
232
+ ),
233
+ $serviceUrl
234
+ );
235
+
236
+ $response = $call->getResults();
237
+
238
+ // Check for soap errors
239
+ if(is_null($response)) {
240
+ if(trim($call->getErrorMessage())=='') {
241
+ throw new Exception(Mage::helper('cem')->__("An unknown SOAP error occurred while install the CEM key. Please contact your retailer for assistance."));
242
+ }
243
+ throw new Exception($call->getErrorMessage());
244
+ }
245
+
246
+ // Install packages
247
+ $failedInstallations = '';
248
+
249
+ if(!is_array($response)) {
250
+ throw new Exception(Mage::helper('cem')->__("No packages could be found that were associated with the provided CEM key. Make sure that the CEM key is valid and try again."));
251
+ }
252
+
253
+ foreach ($response as $package) {
254
+ if(!@Mage::getModel('cem/packages')->install($package['package_identifier'],$package['license_key'],$serviceUrl,1)) {
255
+ $error = Mage::registry('cem_error');
256
+ $error = empty($error) ? 'Unknown error' : $error;
257
+
258
+ $failedInstallations.= "\n\n[ {$package['package_identifier']} ]\n - {$error}";
259
+ }
260
+ }
261
+
262
+ // Success
263
+ $this->getResponse()->setBody("SUCCESS|{$failedInstallations}");
264
+ return;
265
+ }
266
+ catch (Exception $e) {
267
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
268
+ return;
269
+ }
270
+ }
271
+
272
+
273
+ /**
274
+ * Make sure the user can access this controller
275
+ */
276
+ protected function _isAllowed()
277
+ {
278
+ return Mage::getSingleton('admin/session')->isAllowed('system/extensions/cem');
279
+ }
280
+
281
+ }
app/code/community/Easy/CEM/controllers/Adminhtml/PackagesController.php ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_Adminhtml_PackagesController extends Mage_Adminhtml_Controller_Action
22
+ {
23
+
24
+ /**
25
+ * Init action
26
+ *
27
+ * Creates breadcrumbs etc.
28
+ */
29
+ public function _initAction()
30
+ {
31
+ $this->loadLayout()
32
+ ->_setActiveMenu('system')
33
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('System'), Mage::helper('adminhtml')->__('System'))
34
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('Magento Connect'), Mage::helper('adminhtml')->__('Magento Connect'))
35
+ ->_addBreadcrumb(Mage::helper('adminhtml')->__('Commercial Extension Manager'), Mage::helper('adminhtml')->__('Commercial Extension Manager'));
36
+
37
+ return $this;
38
+ }
39
+
40
+
41
+ /**
42
+ * Index action
43
+ */
44
+ public function indexAction()
45
+ {
46
+ $this->_initAction()
47
+ ->_addContent($this->getLayout()->createBlock('cem/adminhtml_packages'))
48
+ ->renderLayout();
49
+ }
50
+
51
+
52
+ /**
53
+ * Redirects a user to the editing area
54
+ */
55
+ public function newAction()
56
+ {
57
+ $this->_forward('edit');
58
+ }
59
+
60
+
61
+ /**
62
+ * Redirects a user to the editing area
63
+ */
64
+ public function editAction()
65
+ {
66
+ $id = $this->getRequest()->getParam('package_id');
67
+ $model = Mage::getModel('cem/packages');
68
+
69
+ // If an ID was givven, load the object
70
+ if($id) {
71
+ $model->load($id);
72
+ if (!$model->getPackageId()) {
73
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('cem')->__('This package no longer exists'));
74
+ $this->_redirect('*/*/');
75
+ return;
76
+ }
77
+ }
78
+
79
+ // Register the current model object
80
+ Mage::register('cem_package', $model);
81
+
82
+ // Edit block
83
+ $this->_initAction()
84
+ ->_addBreadcrumb($id ? Mage::helper('cem')->__('Update Extension') : Mage::helper('cem')->__('Install New Extension'), $id ? Mage::helper('cem')->__('Update Extension') : Mage::helper('cem')->__('Install New Etension'))
85
+ ->_addContent($this->getLayout()->createBlock('cem/adminhtml_packages_edit')->setData('action', $this->getUrl('*/*/install')))
86
+ ->renderLayout();
87
+ }
88
+
89
+
90
+ /**
91
+ * Install action
92
+ */
93
+ public function installAction()
94
+ {
95
+ // License key
96
+ $licenseKey = $this->getRequest()->getPost('license_key');
97
+
98
+ // Auth service
99
+ $service = $this->getRequest()->getPost('service');
100
+
101
+ // Package Identifier
102
+ $packageIdentifier = $this->getRequest()->getPost('package_identifier');
103
+
104
+ // Update package automatically
105
+ $autoUpdate = $this->getRequest()->getPost('auto_update');
106
+
107
+ try {
108
+ // Get package model
109
+ $packageModel = Mage::getModel('cem/packages');
110
+
111
+ // Install extension
112
+ if(!$packageModel->install($packageIdentifier,$licenseKey,$service,$autoUpdate)) {
113
+ $error = Mage::registry('cem_error');
114
+
115
+ if(!empty($error)) {
116
+ throw new Exception($error);
117
+ }
118
+ else {
119
+ throw new Exception(Mage::helper('cem')->__("The installation couldn't be completed due to an unknown error. Please contact your software retailer for assistance."));
120
+ }
121
+ }
122
+
123
+ // Success
124
+ $this->getResponse()->setBody("SUCCESS");
125
+ return;
126
+ }
127
+ catch (Exception $e) {
128
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
129
+ return;
130
+ }
131
+ }
132
+
133
+
134
+ /**
135
+ * Update installed extension(s)
136
+ */
137
+ public function updateAction()
138
+ {
139
+ // Package id
140
+ $packageId = $this->getRequest()->getPost('id');
141
+
142
+ // Ajax call
143
+ $ajax = $this->getRequest()->getPost('ajax');
144
+
145
+ // Get package module
146
+ $packageModel = Mage::getModel('cem/packages');
147
+
148
+ try {
149
+ // Get package collection
150
+ $packages = $packageModel->getCollection()
151
+ ->joinTables()
152
+ ->setIdFilter($packageId);
153
+
154
+ // Check so that there were at least one valid package
155
+ if($packages->getSize()<1) {
156
+ throw new Exception(Mage::helper('cem')->__("Unable to find the extension requested for update."));
157
+ }
158
+
159
+ // Message
160
+ $msg = Mage::helper('cem')->__('No extensions were updated');
161
+
162
+ // Update success
163
+ $update = 0;
164
+
165
+ // Update packages
166
+ if($update = $packageModel->update($packages,true)) {
167
+ $msg = Mage::helper('cem')->__('Extensions was successfully updated');
168
+ }
169
+
170
+ if($ajax) {
171
+ if($packages->getSize()===1 && $update===0) {
172
+ $this->getResponse()->setBody(Mage::helper('cms')->__("The extension is already up-to-date"));
173
+ }
174
+ else {
175
+ $this->getResponse()->setBody("SUCCESS");
176
+ }
177
+ }
178
+ else {
179
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('cms')->__($msg));
180
+ $this->_redirect('*/*/');
181
+ }
182
+ return;
183
+ }
184
+ catch (Exception $e) {
185
+ // display error message
186
+ if($ajax) {
187
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
188
+ }
189
+ else {
190
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
191
+ $this->_redirect('*/*/');
192
+ }
193
+ return;
194
+ }
195
+ }
196
+
197
+
198
+ /**
199
+ * Set the CEM email
200
+ */
201
+ public function setCemEmailAction()
202
+ {
203
+ $email = $this->getRequest()->getParam('email');
204
+
205
+ if(!empty($email)) {
206
+ try {
207
+ if(!Mage::getModel('cem/licenses')->validateEmail($email)) {
208
+ throw new Exception(Mage::helper('cem')->__("The email address you provided is invalid, please make sure that it's correct and try again."));
209
+ }
210
+
211
+ $configEmail = Mage::getStoreConfig('system/cem/email');
212
+
213
+ if(empty($configEmail)) {
214
+ Mage::getConfig()->saveConfig('system/cem/email', $email, 'default', 0);
215
+
216
+ // Clean up the cache
217
+ if(!Mage::app()->cleanCache()) {
218
+ throw new Exception(Mage::helper('cem')->__("Unable to refresh cache, please refresh the cache manually."));
219
+ }
220
+ }
221
+
222
+ // Success
223
+ $this->getResponse()->setBody("SUCCESS");
224
+ return;
225
+ }
226
+ catch (Exception $e) {
227
+ $this->getResponse()->setBody(Mage::helper('cem')->__($e->getMessage()));
228
+ return;
229
+ }
230
+ }
231
+ else {
232
+ $this->getResponse()->setBody(Mage::helper('cem')->__("You need to provide a valid email address"));
233
+ return;
234
+ }
235
+ }
236
+
237
+
238
+ /**
239
+ * Set the CEM email
240
+ */
241
+ public function licenseManagementAction()
242
+ {
243
+ $this->_initAction()
244
+ ->_addBreadcrumb(Mage::helper('cem')->__('License Management'), Mage::helper('cem')->__('License Management'))
245
+ ->_addContent($this->getLayout()->createBlock('cem/adminhtml_licenses_edit'))
246
+ ->_addLeft($this->getLayout()->createBlock('cem/adminhtml_licenses_edit_tabs'))
247
+ ->renderLayout();
248
+ }
249
+
250
+
251
+ /**
252
+ * Make sure the user can access this controller
253
+ */
254
+ protected function _isAllowed()
255
+ {
256
+ return Mage::getSingleton('admin/session')->isAllowed('system/extensions/cem');
257
+ }
258
+
259
+ }
app/code/community/Easy/CEM/controllers/IndexController.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ class Easy_CEM_IndexController extends Mage_Adminhtml_Controller_Action
22
+ {
23
+
24
+ /**
25
+ * Noroute action
26
+ */
27
+ public function norouteAction($coreRoute = null)
28
+ {
29
+ $this->_forward('index','adminhtml_packages','cem');
30
+ }
31
+
32
+
33
+ /**
34
+ * Fixes changeLocale bug
35
+ *
36
+ */
37
+ public function changeLocaleAction()
38
+ {
39
+ $this->_forward('changeLocale', 'index','admin');
40
+ }
41
+
42
+
43
+ /**
44
+ * Check if a user is allowed here
45
+ *
46
+ * @return boolean
47
+ */
48
+ protected function _isAllowed()
49
+ {
50
+ return Mage::getSingleton('admin/session')->isAllowed('system/extensions/cem');
51
+ }
52
+
53
+ }
app/code/community/Easy/CEM/etc/config.xml ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * MageParts
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category MageParts
17
+ * @package Easy_CEM
18
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <Easy_CEM>
25
+ <version>1.0.0</version>
26
+ </Easy_CEM>
27
+ </modules>
28
+
29
+ <global>
30
+ <models>
31
+ <cem>
32
+ <class>Easy_CEM_Model</class>
33
+ <resourceModel>cem_mysql4</resourceModel>
34
+ </cem>
35
+ <cem_mysql4>
36
+ <class>Easy_CEM_Model_Mysql4</class>
37
+ <entities>
38
+ <packages>
39
+ <table>cem_packages</table>
40
+ </packages>
41
+ <services>
42
+ <table>cem_services</table>
43
+ </services>
44
+ <service_keys>
45
+ <table>cem_service_keys</table>
46
+ </service_keys>
47
+ <licenses>
48
+ <table>cem_licenses</table>
49
+ </licenses>
50
+ </entities>
51
+ </cem_mysql4>
52
+ </models>
53
+ <helpers>
54
+ <cem>
55
+ <class>Easy_CEM_Helper</class>
56
+ </cem>
57
+ </helpers>
58
+ <blocks>
59
+ <cem>
60
+ <class>Easy_CEM_Block</class>
61
+ </cem>
62
+ </blocks>
63
+ <resources>
64
+ <cem_setup>
65
+ <setup>
66
+ <module>Easy_CEM</module>
67
+ </setup>
68
+ <connection>
69
+ <use>core_setup</use>
70
+ </connection>
71
+ </cem_setup>
72
+ <cem_write>
73
+ <connection>
74
+ <use>core_write</use>
75
+ </connection>
76
+ </cem_write>
77
+ <cem_read>
78
+ <connection>
79
+ <use>core_read</use>
80
+ </connection>
81
+ </cem_read>
82
+ </resources>
83
+ </global>
84
+
85
+ <adminhtml>
86
+ <translate>
87
+ <modules>
88
+ <Easy_CEM>
89
+ <files>
90
+ <default>Easy_CEM.csv</default>
91
+ </files>
92
+ </Easy_CEM>
93
+ </modules>
94
+ </translate>
95
+
96
+ <menu>
97
+ <system>
98
+ <children>
99
+ <extensions>
100
+ <children>
101
+ <cem module="cem">
102
+ <title>Commercial Extension Manager</title>
103
+ <action>cem/adminhtml_packages</action>
104
+ <sort_order>999</sort_order>
105
+ </cem>
106
+ </children>
107
+ </extensions>
108
+ </children>
109
+ </system>
110
+ </menu>
111
+
112
+ <acl>
113
+ <resources>
114
+ <admin>
115
+ <children>
116
+ <system>
117
+ <children>
118
+ <extensions>
119
+ <children>
120
+ <cem translate="title">
121
+ <title>Commercial Extension Manager</title>
122
+ <sort_order>999</sort_order>
123
+ </cem>
124
+ </children>
125
+ </extensions>
126
+ </children>
127
+ </system>
128
+ </children>
129
+ </admin>
130
+ </resources>
131
+ </acl>
132
+
133
+ <layout>
134
+ <updates>
135
+ <cem>
136
+ <file>cem.xml</file>
137
+ </cem>
138
+ </updates>
139
+ </layout>
140
+ </adminhtml>
141
+
142
+ <admin>
143
+ <routers>
144
+ <cem>
145
+ <use>admin</use>
146
+ <args>
147
+ <module>Easy_CEM</module>
148
+ <frontName>cem</frontName>
149
+ </args>
150
+ </cem>
151
+ </routers>
152
+ </admin>
153
+
154
+ <default>
155
+ <system>
156
+ <cem>
157
+ <frequency>24</frequency>
158
+ <email></email>
159
+ </cem>
160
+ </system>
161
+ </default>
162
+
163
+ <crontab>
164
+ <jobs>
165
+ <cem_auto_update>
166
+ <schedule><cron_expr>* * * * *</cron_expr></schedule>
167
+ <run><model>cem/observer::checkUpdate</model></run>
168
+ </cem_auto_update>
169
+ </jobs>
170
+ </crontab>
171
+ </config>
app/code/community/Easy/CEM/etc/system.xml ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * MageParts
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category MageParts
17
+ * @package Easy_CEM
18
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <sections>
24
+ <system>
25
+ <groups>
26
+ <cem translate="label" module="cem">
27
+ <label>CEM</label>
28
+ <frontend_type>text</frontend_type>
29
+ <sort_order>0</sort_order>
30
+ <show_in_default>1</show_in_default>
31
+ <show_in_website>1</show_in_website>
32
+ <show_in_store>1</show_in_store>
33
+ <fields>
34
+ <frequency>
35
+ <label>Update frequency</label>
36
+ <frontend_type>select</frontend_type>
37
+ <source_model>cem/system_config_source_cEM_frequency</source_model>
38
+ <sort_order>0</sort_order>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>0</show_in_website>
41
+ <show_in_store>0</show_in_store>
42
+ </frequency>
43
+ <email translate="label">
44
+ <label>Email</label>
45
+ <frontend_type>text</frontend_type>
46
+ <sort_order>10</sort_order>
47
+ <show_in_default>1</show_in_default>
48
+ <show_in_website>1</show_in_website>
49
+ <show_in_store>1</show_in_store>
50
+ </email>
51
+ </fields>
52
+ </cem>
53
+ </groups>
54
+ </system>
55
+ </sections>
56
+ </config>
app/code/community/Easy/CEM/sql/cem_setup/mysql4-install-1.0.0.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package MageParts_Adminhtml
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+ $installer = $this;
22
+ /* @var $installer Mage_Core_Model_Resource_Setup */
23
+
24
+ $installer->startSetup();
25
+
26
+ // Create tables
27
+ $installer->run("
28
+
29
+ /*============================== SERVICES ==============================*/
30
+
31
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('cem_services')}` (
32
+ `service_id` int(11) unsigned NOT NULL auto_increment,
33
+ `url` varchar(255) NOT NULL,
34
+ PRIMARY KEY (`service_id`),
35
+ UNIQUE KEY `UK_url` (`url`)
36
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
37
+
38
+
39
+
40
+
41
+ /*============================== LICENSES ==============================*/
42
+
43
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('cem_licenses')}` (
44
+ `license_id` int(11) unsigned NOT NULL auto_increment,
45
+ `license_key` varchar(255) NOT NULL,
46
+ PRIMARY KEY (`license_id`),
47
+ UNIQUE KEY `FK_license_key` (`license_key`)
48
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
49
+
50
+
51
+
52
+
53
+ /*============================== PACKAGES ==============================*/
54
+
55
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('cem_packages')}` (
56
+ `package_id` int(11) unsigned NOT NULL auto_increment,
57
+ `service_id` int(11) unsigned NOT NULL,
58
+ `license_id` int(11) unsigned NOT NULL,
59
+ `module_id` int(11) NOT NULL,
60
+ `identifier` varchar(100) NOT NULL,
61
+ `title` varchar(100) NOT NULL,
62
+ `version` decimal(12,4) NOT NULL,
63
+ `identifier_rollback` varchar(100),
64
+ `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
65
+ `update_available` tinyint(1) DEFAULT '0',
66
+ `auto_update` tinyint(1) NOT NULL DEFAULT '0',
67
+ PRIMARY KEY (`package_id`),
68
+ UNIQUE KEY `UK_identifier` (`identifier`),
69
+ UNIQUE KEY `FK_license_id` (`license_id`),
70
+ KEY `FK_service_id` (`service_id`),
71
+ CONSTRAINT `FK_service_id` FOREIGN KEY (`service_id`) REFERENCES {$this->getTable('cem_services')} (`service_id`) ON DELETE CASCADE ON UPDATE CASCADE,
72
+ CONSTRAINT `FK_license_id` FOREIGN KEY (`license_id`) REFERENCES {$this->getTable('cem_licenses')} (`license_id`) ON DELETE CASCADE ON UPDATE CASCADE
73
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
74
+
75
+
76
+
77
+
78
+ /*============================== CEM KEYS ==============================*/
79
+
80
+ CREATE TABLE IF NOT EXISTS `{$this->getTable('cem_service_keys')}` (
81
+ `key_id` int(11) unsigned NOT NULL auto_increment,
82
+ `service_id` int(11) unsigned NOT NULL,
83
+ `key` varchar(255) NOT NULL,
84
+ PRIMARY KEY (`key_id`),
85
+ UNIQUE KEY `FK_service_id` (`service_id`),
86
+ UNIQUE KEY `UK_key` (`key`),
87
+ CONSTRAINT `FK_service_id2` FOREIGN KEY (`service_id`) REFERENCES {$this->getTable('cem_services')} (`service_id`) ON DELETE CASCADE ON UPDATE CASCADE
88
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
89
+
90
+ ");
91
+
92
+
93
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/cem.xml ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package design_default
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ -->
21
+ <layout>
22
+ <cem_adminhtml_packages_index>
23
+ <reference name="head">
24
+ <action method="addCss"><stylesheet>cem/style.css</stylesheet></action>
25
+ </reference>
26
+ </cem_adminhtml_packages_index>
27
+ <cem_adminhtml_packages_new>
28
+ <reference name="head">
29
+ <action method="addCss"><stylesheet>cem/style.css</stylesheet></action>
30
+ </reference>
31
+ </cem_adminhtml_packages_new>
32
+ <cem_adminhtml_packages_edit>
33
+ <reference name="head">
34
+ <action method="addCss"><stylesheet>cem/style.css</stylesheet></action>
35
+ </reference>
36
+ </cem_adminhtml_packages_edit>
37
+ <cem_adminhtml_packages_licensemanagement>
38
+ <reference name="head">
39
+ <action method="addCss"><stylesheet>cem/style.css</stylesheet></action>
40
+ </reference>
41
+ </cem_adminhtml_packages_licensemanagement>
42
+ </layout>
app/design/adminhtml/default/default/template/cem/licenses/lostcem.phtml ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package design_default
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+
22
+ <style type="text/css">
23
+ #content .content-header {
24
+ display:none;
25
+ }
26
+ </style>
27
+
28
+ <div class="content-header" style="display:block;">
29
+ <table cellspacing="0">
30
+ <tr>
31
+ <td><h3 class="icon-head head-adminhtml-lost-key"><?php echo Mage::helper('cem')->__('Recover Lost CEM Key'); ?></h3></td>
32
+ <td class="form-buttons">
33
+ <?php echo $this->getLostCemKeyButtonHtml(); ?>
34
+ <?php echo $this->getBackButtonHtml(); ?>
35
+ </td>
36
+ </tr>
37
+ </table>
38
+ </div>
39
+
40
+ <div class="entry-edit">
41
+ <div class="entry-edit-head">
42
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('cem')->__('General Information'); ?></h4>
43
+ </div>
44
+
45
+ <div class="fieldset fieldset-wide">
46
+ <table class="form-list">
47
+ <tbody>
48
+ <tr>
49
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Service URL'); ?></label></td>
50
+ <td class="value">
51
+ <input type="text"id="cem_service_url" value="" />
52
+ </td>
53
+ </tr>
54
+ <tr>
55
+ <td class="label"><label><?php echo Mage::helper('cem')->__('CEM Key'); ?></label></td>
56
+ <td class="value">
57
+ <input type="text" id="cem_key" value="" />
58
+ </td>
59
+ </tr>
60
+ </tbody>
61
+ </table>
62
+ </div>
63
+ </div>
64
+
65
+ <script type="text/javascript">
66
+ //<![CDATA[
67
+
68
+ var lostCem = {
69
+
70
+ /**
71
+ * Install package
72
+ */
73
+ install : function()
74
+ {
75
+ var serviceUrl = $('cem_service_url').value;
76
+ var cemKey = $('cem_key').value;
77
+
78
+ if(serviceUrl.blank()) {
79
+ alert("<?php echo Mage::helper('cem')->__("Please provide a valid service url") ?>");
80
+ return;
81
+ }
82
+
83
+ if(cemKey.blank()) {
84
+ new Ajax.Request(
85
+ '<?php echo $this->getUrl('*/adminhtml_licenses/requestLostCemKey'); ?>',
86
+ {
87
+ method : 'POST',
88
+ parameters : '?service_url=' + serviceUrl,
89
+ onSuccess : function(o){
90
+ try {
91
+ if(o.responseText) {
92
+ if(o.responseText==='SUCCESS') {
93
+ alert("<?php echo Mage::helper('cem')->__("The CEM key has been sent to your email inbox (%s). Please insert the CEM key into the 'Cem Key' field and click the 'OK' button once more to install the CEM key and all of its associated software.",Mage::getStoreConfig('system/cem/email')) ?>");
94
+ }
95
+ else {
96
+ alert(o.responseText);
97
+ }
98
+ }
99
+ }
100
+ catch (e2) {
101
+ alert("<?php echo Mage::helper('cem')->__("An unknown error has occurred, the requested action was interrupted") ?>");
102
+ }
103
+ },
104
+ onFailure : function(o) {
105
+ try {
106
+ console.log(o.statusText);
107
+ } catch (e2) {
108
+ alert(o.statusText);
109
+ }
110
+ }
111
+ }
112
+ );
113
+ }
114
+ else {
115
+ new Ajax.Request(
116
+ '<?php echo $this->getUrl('*/adminhtml_licenses/installCemKey'); ?>',
117
+ {
118
+ method : 'POST',
119
+ parameters : '?service_url=' + serviceUrl + '&cem_key=' + cemKey,
120
+ onSuccess : function(o){
121
+ try {
122
+ if(o.responseText) {
123
+ if(o.responseText.substr(0,7)==='SUCCESS') {
124
+ var failedInstallations = o.responseText.substr(8);
125
+ if(!failedInstallations.blank()) {
126
+ alert("<?php echo Mage::helper('cem')->__("The requested CEM key was successfully installed. The following extensions could not be automatically installed on your system:") ?> " + failedInstallations + "\n\n<?php echo Mage::helper('cem')->__("Any unknown errors were most likely caused by insufficient writing permission. The extensions which failed to be installed will have to be installed manually, we appologize for your inconvenience.") ?> ");
127
+ }
128
+ else {
129
+ alert("<?php echo Mage::helper('cem')->__("The requested CEM key was successfully installed along with all associated extensions found on service") ?> " + serviceUrl);
130
+ }
131
+ }
132
+ else {
133
+ alert(o.responseText);
134
+ }
135
+ }
136
+ }
137
+ catch (e2) {
138
+ alert("<?php echo Mage::helper('cem')->__("An unknown error has occurred, the requested action was interrupted") ?>");
139
+ }
140
+ },
141
+ onFailure : function(o) {
142
+ try {
143
+ console.log(o.statusText);
144
+ } catch (e2) {
145
+ alert(o.statusText);
146
+ }
147
+ }
148
+ }
149
+ );
150
+ }
151
+ }
152
+
153
+ }
154
+
155
+ //]]>
156
+ </script>
app/design/adminhtml/default/default/template/cem/licenses/lostlicense.phtml ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package design_default
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+
22
+ <style type="text/css">
23
+ #content .content-header {
24
+ display:none;
25
+ }
26
+ </style>
27
+
28
+ <div class="content-header" style="display:block;">
29
+ <table cellspacing="0">
30
+ <tr>
31
+ <td><h3 class="icon-head head-adminhtml-lost-key"><?php echo Mage::helper('cem')->__('Recover Lost License Key'); ?></h3></td>
32
+ <td class="form-buttons">
33
+ <?php echo $this->getLostLicenseKeyButtonHtml(); ?>
34
+ <?php echo $this->getBackButtonHtml(); ?>
35
+ </td>
36
+ </tr>
37
+ </table>
38
+ </div>
39
+
40
+ <div class="entry-edit">
41
+ <div class="entry-edit-head">
42
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('cem')->__('General Information'); ?></h4>
43
+ </div>
44
+
45
+ <div class="fieldset fieldset-wide">
46
+ <table class="form-list">
47
+ <tbody>
48
+ <tr>
49
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Service URL'); ?></label></td>
50
+ <td class="value">
51
+ <input type="text"id="license_service_url" value="" />
52
+ </td>
53
+ </tr>
54
+ <tr>
55
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Module Identifier'); ?></label></td>
56
+ <td class="value">
57
+ <input type="text" id="module_identifier" value="" />
58
+ </td>
59
+ </tr>
60
+ </tbody>
61
+ </table>
62
+ </div>
63
+ </div>
64
+
65
+ <script type="text/javascript">
66
+ //<![CDATA[
67
+
68
+ var lostLicenses = {
69
+
70
+ /**
71
+ * Install package
72
+ */
73
+ install : function()
74
+ {
75
+ var serviceUrl = $('license_service_url').value;
76
+ var moduleIdentifier = $('module_identifier').value;
77
+
78
+ new Ajax.Request(
79
+ '<?php echo $this->getUrl('*/adminhtml_licenses/requestLostLicenseKey'); ?>',
80
+ {
81
+ method : 'POST',
82
+ parameters : '?service_url=' + serviceUrl + '&module_identifier=' + moduleIdentifier,
83
+ onSuccess : function(o){
84
+ try {
85
+ if(o.responseText) {
86
+ if(o.responseText==='SUCCESS') {
87
+ alert("<?php echo Mage::helper('cem')->__("The license key has been sent to your email inbox (%s).",Mage::getStoreConfig('system/cem/email')) ?>");
88
+ }
89
+ else {
90
+ alert(o.responseText);
91
+ }
92
+ }
93
+ }
94
+ catch (e2) {
95
+ alert("<?php echo Mage::helper('cem')->__("An unknown error has occurred, the requested action was interrupted") ?>");
96
+ }
97
+ },
98
+ onFailure : function(o) {
99
+ try {
100
+ console.log(o.statusText);
101
+ } catch (e2) {
102
+ alert(o.statusText);
103
+ }
104
+ }
105
+ }
106
+ );
107
+ }
108
+
109
+ }
110
+
111
+ //]]>
112
+ </script>
app/design/adminhtml/default/default/template/cem/packages/install.phtml ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package design_default
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+
22
+
23
+ <?php $rollbackIdentifier = $this->getIdentifierRollback() ?>
24
+ <?php $packageIdentifier = $this->getPackageIdentifier() ?>
25
+
26
+ <div class="content-header">
27
+ <table cellspacing="0">
28
+ <tr>
29
+ <td><h3 class="icon-head head-adminhtml-packages-install"><?php echo $this->getHeaderText() ?></h3></td>
30
+ <td class="form-buttons">
31
+ <button class="scalable back" onclick="setLocation('<?php echo $this->getUrl('*/*/index'); ?>');"><span><?php echo Mage::helper('cem')->__('Back') ?></span></button>
32
+
33
+ <?php // ROLLBACK BUTTON ?>
34
+ <?php if(!empty($rollbackIdentifier)) : ?>
35
+ <button class="scalable" onclick="cem.install('<?php echo $this->getIdentifierRollback(); ?>');"><span><?php echo Mage::helper('cem')->__('Rollback') ?></span></button>
36
+ <?php endif; ?>
37
+
38
+ <? // UPDATE BUTTON ?>
39
+ <?php if(!empty($packageIdentifier)) : ?>
40
+ <button class="scalable" onclick="cem.update();"><span><?php echo Mage::helper('cem')->__('Update') ?></span></button>
41
+ <?php endif; ?>
42
+
43
+ <button class="scalable save" onclick="cem.install();"><span><?php echo Mage::helper('cem')->__('Install') ?></span></button>
44
+ </td>
45
+ </tr>
46
+ </table>
47
+ </div>
48
+
49
+
50
+
51
+
52
+ <div class="entry-edit">
53
+ <div class="entry-edit-head">
54
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('cem')->__('General Information'); ?></h4>
55
+ </div>
56
+
57
+ <div class="fieldset fieldset-wide">
58
+ <table class="form-list">
59
+ <tbody>
60
+ <tr>
61
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Service URL'); ?></label></td>
62
+ <td class="value">
63
+ <input type="text" name="address" id="cem_service" value="<?php echo $this->getPackageServiceUrl(); ?>" />
64
+ </td>
65
+ </tr>
66
+ <tr>
67
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Extension Identifier'); ?></label></td>
68
+ <td class="value">
69
+ <input type="text" name="identifier" id="cem_package_identifier" value="<?php echo $this->getPackageIdentifier(); ?>" />
70
+ </td>
71
+ </tr>
72
+ <tr>
73
+ <td class="label"><label><?php echo Mage::helper('cem')->__('License'); ?></label></td>
74
+ <td class="value">
75
+ <input type="text" name="license_key" id="cem_license_key" value="<?php echo $this->getPackageLicenseKey(); ?>" />
76
+ </td>
77
+ </tr>
78
+ <tr>
79
+ <td class="label"><label><?php echo Mage::helper('cem')->__('Update Automatically'); ?></label></td>
80
+ <td class="value">
81
+ <select name="auto_update" id="cem_auto_update">
82
+ <option value="1"><?php echo Mage::helper('cem')->__('Yes'); ?></option>
83
+ <option value="0"<?php if(!$this->getPackageAutoUpdate() && trim($this->getPackageIdentifier()) != '') : ?> selected<?php endif; ?>><?php echo Mage::helper('cem')->__('No'); ?></option>
84
+ </select>
85
+ </td>
86
+ </tr>
87
+ </tbody>
88
+ </table>
89
+ </div>
90
+ </div>
91
+
92
+ <script type="text/javascript">
93
+ //<![CDATA[
94
+
95
+ var cem = {
96
+
97
+ /**
98
+ * Install package
99
+ */
100
+ install : function()
101
+ {
102
+ var service = $('cem_service').value;
103
+ var packageIdentifier = arguments[0] != undefined ? arguments[0] : $('cem_package_identifier').value;
104
+ var licenseKey = $('cem_license_key').value;
105
+ var autoUpdate = $('cem_auto_update').value;
106
+
107
+ if(service.blank()) {
108
+ alert("<?php echo Mage::helper('cem')->__("Please provide a valid service url") ?>");
109
+ return;
110
+ }
111
+
112
+ if(packageIdentifier.blank()) {
113
+ alert("<?php echo Mage::helper('cem')->__("Please provide a valid package identifier") ?>");
114
+ return;
115
+ }
116
+
117
+ if(licenseKey.blank()) {
118
+ alert("<?php echo Mage::helper('cem')->__("Please provide a valid license key") ?>");
119
+ return;
120
+ }
121
+
122
+ new Ajax.Request(
123
+ '<?php echo $this->getInstallUrl() ?>',
124
+ {
125
+ method : 'POST',
126
+ parameters : '?service=' + service + '&package_identifier=' + packageIdentifier + '&license_key=' + licenseKey + '&auto_update=' + autoUpdate,
127
+ onSuccess : function(o){
128
+ try {
129
+ if(o.responseText) {
130
+ if(o.responseText==='SUCCESS') {
131
+ alert("<?php echo Mage::helper('cem')->__("The extension was successfully installed") ?>");
132
+ setLocation('<?php echo $this->getUrl('*/*/'); ?>');
133
+ }
134
+ else {
135
+ alert(o.responseText);
136
+ }
137
+ }
138
+ }
139
+ catch (e2) {
140
+ alert("<?php echo Mage::helper('cem')->__("An unknown error has occurred, the requested extension couldn't be installed") ?>");
141
+ }
142
+ },
143
+ onFailure : function(o) {
144
+ try {
145
+ console.log(o.statusText);
146
+ } catch (e2) {
147
+ alert(o.statusText);
148
+ }
149
+ location.reload();
150
+ }
151
+ }
152
+ );
153
+ },
154
+
155
+
156
+ /**
157
+ * Update package
158
+ */
159
+ update : function()
160
+ {
161
+ // var service = $('cem_service').value;
162
+ // var packageIdentifier = $('cem_package_identifier').value;
163
+ // var licenseKey = $('cem_license_key').value;
164
+ // var autoUpdate = $('cem_auto_update').value;
165
+
166
+ // packageIdentifier = packageIdentifier.substr(0,packageIdentifier.lastIndexOf('_')) + '_latest';
167
+
168
+ new Ajax.Request(
169
+ '<?php echo $this->getUpdateUrl() ?>',
170
+ {
171
+ method : 'POST',
172
+ parameters : '?ajax=1&id=<?php echo $this->getPackageId() ?>',
173
+ onSuccess : function(o){
174
+ try {
175
+ if(o.responseText) {
176
+ if(o.responseText==='SUCCESS') {
177
+ alert("<?php echo Mage::helper('cem')->__('The extension was updated successfully') ?>");
178
+ location.reload();
179
+ }
180
+ else {
181
+ alert(o.responseText);
182
+ }
183
+ }
184
+ }
185
+ catch (e2) {
186
+ alert("<?php echo Mage::helper('cem')->__("An unknown error has occurred, the requested extension couldn't be updated") ?>");
187
+ }
188
+ },
189
+ onFailure : function(o) {
190
+ try {
191
+ console.log(o.statusText);
192
+ } catch (e2) {
193
+ alert(o.statusText);
194
+ }
195
+ location.reload();
196
+ }
197
+ }
198
+ );
199
+ }
200
+
201
+ }
202
+
203
+ //]]>
204
+ </script>
app/design/adminhtml/default/default/template/cem/packages/register.phtml ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MageParts
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category MageParts
16
+ * @package design_default
17
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+ ?>
21
+
22
+ <style type="text/css">
23
+ .middle .content-header {
24
+ display:none;
25
+ }
26
+
27
+ .regform {
28
+ margin:50px auto;
29
+ width:500px;
30
+ border:1px solid #c0c0c0;
31
+ padding:40px;
32
+ }
33
+ </style>
34
+
35
+ <?php if(floatval(Mage::getVersion())<1.2): ?>
36
+ <div class="regform">
37
+ <p><?= Mage::helper('cem')->__('registration-magento-version', Mage::getVersion()); ?></p>
38
+
39
+ <br />
40
+
41
+ <?= Mage::helper('cem')->__('registration-process'); ?>
42
+
43
+ <br />
44
+
45
+ <?= Mage::helper('cem')->__('registration-note'); ?>
46
+
47
+ <br />
48
+
49
+ <p><?= Mage::helper('cem')->__('registration-assistence'); ?></p>
50
+
51
+ </div>
52
+ <?php else: ?>
53
+ <div class="regform">
54
+ <p><?= Mage::helper('cem')->__('registration-email'); ?></p>
55
+
56
+ <br />
57
+
58
+ <p><?= Mage::helper('cem')->__('registration-email-note'); ?></p>
59
+
60
+ <br />
61
+ <br />
62
+
63
+ <table>
64
+ <tr>
65
+ <td><p>Email</p></td>
66
+ <td><input type="text" id="email" /></td>
67
+ </tr>
68
+ </table>
69
+
70
+ <br />
71
+
72
+ <button class="scalable save" onclick="registerCem();"><span><?php echo Mage::helper('cem')->__('Register') ?></span></button>
73
+ </div>
74
+
75
+ <script type="text/javascript">
76
+
77
+
78
+ /**
79
+ * Register CEM
80
+ */
81
+ function registerCem()
82
+ {
83
+ var email = $('email').value;
84
+
85
+ new Ajax.Request(
86
+ '<?php echo $this->getUrl('*/*/setCemEmail'); ?>',
87
+ {
88
+ method : 'POST',
89
+ parameters : '?email=' + email,
90
+ onSuccess : function(o){
91
+ try {
92
+ if(o.responseText) {
93
+ if(o.responseText==='SUCCESS') {
94
+ alert("<?= Mage::helper('cem')->__('CEM has now been registered and is ready for use') ?>");
95
+ location.reload();
96
+ }
97
+ else {
98
+ alert(o.responseText);
99
+ }
100
+ }
101
+ }
102
+ catch (e2) {
103
+ alert("<?= Mage::helper('cem')->__('An unknown error has occurred, please contact MageParts and notify us of your issue') ?>");
104
+ }
105
+ },
106
+ onFailure : function(o) {
107
+ try {
108
+ console.log(o.statusText);
109
+ } catch (e2) {
110
+ alert(o.statusText);
111
+ }
112
+ }
113
+ }
114
+ );
115
+ }
116
+ </script>
117
+ <?php endif; ?>
app/etc/modules/Easy_CEM.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * MageParts
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category MageParts
17
+ * @package MageParts_Adminhtml
18
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+ -->
22
+ <config>
23
+ <modules>
24
+ <Easy_CEM>
25
+ <active>true</active>
26
+ <codePool>community</codePool>
27
+ </Easy_CEM>
28
+ </modules>
29
+ </config>
app/locale/cs_CZ/Easy_CEM.csv ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Register","Registrovat se"
2
+ "An unknown error has occurred, please contact MageParts and notify us of your issue","Došlo k neznámé chybě, prosím kontaktujte EasyCommerce a upozorněte nás na váš problém."
3
+ "OK","OK"
4
+ "Back","Zpět"
5
+ "License Management","Správa licencí"
6
+ "Lost CEM Key","Ztracený CEM klíč"
7
+ "Lost License Key","Ztracený licenční klíč"
8
+ "Update Extension '%s'","Aktualizovat rozšíření '%s'"
9
+ "Install New Extension","Instalovat nové rozšíření"
10
+ "Title","Titulek"
11
+ "Version","Verze"
12
+ "Updated at","Aktualizováno"
13
+ "Updates Available","Aktualizace k dispozici"
14
+ "Manage Extensions <span class=""powered""><a href=""http://www.mageparts.com"" target=""_blank"">Powered by MageParts.com</a></span>","Spravovat rozšíření <span class=""powered""><a href=""http://www.mageparts.com"" target=""_blank"">Powered by MageParts.com</a></span>"
15
+ "Update Extensions","Aktualizovat rozšíření"
16
+ "System","Systém"
17
+ "Magento Connect","Magento Connect"
18
+ "Commercial Extension Manager","Manažer komerčních rozšíření"
19
+ "The provided service url is either invalid or unreachable. Make sure that the service url you provided is correct and try again in a few minutes. If the problem consists we advise you to contact your software retailer for assistance.","Zadaná URL adresa služby je chybná nebo nedostupná. Ujistěte se, že zadaná URL adresa služby je správná a zkuste to znovu za několik minut. Pokud problém přetrvá, kontaktuje EasyCommerce pro asistenci."
20
+ "Unable to save service information in local database. Please contact your retailer for assistance.","Nepodařilo se uložit informace o službe do lokální databáze. Prosím, kontaktujte EasyCommerce pro asistenci."
21
+ "Unable data recieved from service database. Please contact your software retailer for assistance.","Nepodařilo se načíst informace o službě z databáze. Prosím, kontaktujte EasyCommerce pro asistenci."
22
+ "Unable to save CEM key information in local database. Please contact your retailer for assistance.","Nepodařilo se uložit CEM klíč do lokální databáze. Prosím, kontaktujte EasyCommerce pro asistenci."
23
+ "This package no longer exists","Tento balíček již neexistuje"
24
+ "Update Extension","Aktualizovat rozšíření"
25
+ "Install New Etension","Instalovat nové rozšíření"
26
+ "The installation couldn't be completed due to an unknown error. Please contact your software retailer for assistance.","Instalace nemohla být dokončena z důvodu neznámé chyby. Prosím, kontaktujte EasyCommerce pro asistenci."
27
+ "The extension is already up-to-date","Rozšíření je již aktuální."
28
+ "The email address you provided is invalid, please make sure that it's correct and try again.","Vámi zadaná emailová adresa je chybná, opravte ji prosím a zkuste to znovu."
29
+ "Unable to refresh cache, please refresh the cache manually.","Nepodařilo se obnovit cache, prosím obnovte cache ručně."
30
+ "You need to provide a valid email address","Musíte vyplnit platnou emailovou adresu."
31
+ "1 Hour","1 hodina"
32
+ "2 Hours","2 hodiny"
33
+ "6 Hours","6 hodin"
34
+ "12 Hours","12 hodin"
35
+ "24 Hours","24 hodin"
36
+ "Unable to save package information, please try again","Nepodařilo se uložit informace o balíčku, prosím zkuste to znovu."
37
+ "Unable to save CEM key, please contact your software retailer","Nepodařilo se uložit CEM klíč. Prosím, kontaktujte EasyCommerce pro asistenci."
38
+ "CEM key is empty, please contact your retailer","CEM klíč je prázný, kontaktujte EasyCommerce pro asistenci."
39
+ "The version of your Magento installation is too old to support the requested version of this extension. The minimum required version of Magento is %s, the maximum allowed is %s. The currently installed version of Magento is %s. Please upgrade your Magento installation to meet these requirements and try again. If you require any further assistance we advise you to contact your software retailer.","Verze vaší instalace Magento je příliš stará a nepodporuje požadovanou verzi tohoto rozšíření. Minimální požadovaná verze Magento je %s, maximální povolená je %s. Verze aktuální instalace Magento je %s. Prosím, zakupte adekvátní verzi rošíření pro vaši verzi instalace Magento nebo proveďte upgrade Magento, aby byly dodrženy požadavky a zkuste to znovu. Pokud potřebujete další asistenci, doporučujeme vám kontaktovat EasyCommerce."
40
+ "The version of your Magento installation is too new to support the requested version of this extension. You can not use this extension version togheter with a Magento installation with a version above %s or below %s. The currently installed version of Magento is %s. Please downgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer.","Verze vaší instalace Magento je příliš nová a nepodporuje požadovanou verzi tohoto rozšíření. Není možné použít toto rozšíření s verzí Magento instalace vyšší než %s nebo nižší než %s. Verze aktuální instalace Magento je %s. Prosím, zakupte adekvátní verzi rozšíření pro vaši verzi Magento nebo proveďte snížení verze Magento. Pokud potřebujete další asistenci, doporučujeme vám kontaktovat EasyCommerce."
41
+ "Unable to install extension, the following paths needs to be writable: \n\n","Nepodařilo se nainstalovat rozšíření, následující cesty musejí být zapisovatelné: \n\n"
42
+ "This package is already installed","Tento balíček je již instalován"
43
+ "Unable to create / locate temp download directory. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","Nepodařilo se vytvořit / nalézt adresář pro dočasné soubory (temp). Váš adresář Magento zřejmě nemá nastavena práva pro zápis, což tento webový instalátor vyžaduje. Prosím ujistěte se, že vaše oprávnění jsou správná a zkuste to znovu. Pokud potřebujete další asistenci, doporučujeme vám kontaktovat EasyCommerce."
44
+ "Unable to install the requested extension. Your var/tmp directory needs to be writable. If you are not sure how to make the directory writable we suggest that you contact your webadministrator for technical support.","Nepodařilo se instalovat požadované rozšíření. Váš adresář var/tmp v Magento musí být zapisovatelný. Pokud si nejste jisti jak nastavit tento adresář zapisovatelný, doporučujeme vám kontaktovat vašeho webadministrátora o pomoc."
45
+ "An error occurred while completing the download of the source package file. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","Nastala chyba při dokončování stažení zdrojového souboru balíčku. Váš adresář Magento zřejmě nemá dostatečná práva pro zápis, což tento webový instalátor vyžaduje. Prosím ujistěte se, že vaše oprávnění jsou správná a zkuste to znovu. Pokud potřebujete další asistenci, doporučujeme vám kontaktovat EasyCommerce."
46
+ "Unable to install package. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","Nepodařilo se instalovat balíček. Váš adresář Magento musí být zapisovatelný. Pokud si nejste jisti jak nastavit tento adresář zapisovatelný, doporučujeme vám kontaktovat vašeho webadministrátora o pomoc."
47
+ "The installation was successfull but unable to cleanup installation files. Please make sure that your Magento directory has read and write permissions to avoid this problem in the future.","Instalace proběhla úspěšně, ale nepodařilo se vyčistit instalační soubory. Ujistěte se, prosím, že Váš adresář Magento má dostatečná práva pro čtení / zápis, aby se do budoucna předešlo podobnému problému."
48
+ "An unknown SOAP error occurred while gathering module information. Please contact your retailer for assistance.","Nastala neznámá chyba SOAP při shromažďování informací o rozšíření. Prosím kontaktujte EasyCommerce pro asistenci."
49
+ "General Information","Obecné informace"
50
+ "Service URL","URL služby"
51
+ "CEM Key","CEM klíč"
52
+ "Please provide a valid service url","Prosím zadejte platnou URL adresu služby"
53
+ "The CEM key has been sent to your email inbox (%s). Please insert the CEM key into the 'Cem Key' field and click the 'OK' button once more to install the CEM key and all of its associated software.","CEM klíč vám byl zaslán do emailové schránky (%s). Zadejte prosím CEM klíč do pole 'CEM klíč' a klikněte znovu na tačítko 'OK' pro instalaci CEM klíče a s ním spojeného sofware."
54
+ "An unknown error has occurred, the requested action was interrupted","Nastala neznámá chyba, požadovaná operace byla přerušena"
55
+ "The requested CEM key was successfully installed. The following extensions could not be automatically installed on your system:","Vyžádaný CEM klíč byl úspěšně instalován. Následujících rozšíření nemohla být do systému automaticky instalována:"
56
+ "Any unknown errors were most likely caused by insufficient writing permission. The extensions which failed to be installed will have to be installed manually, we appologize for your inconvenience.","Většina neznámých chyb je zapřičiněna nedostatečnými právy pro zápis. Rozšíření, která se nepodařilo instalovat budou muset být instalována ručně, omlouváme se vám za potíž."
57
+ "The requested CEM key was successfully installed along with all associated extensions found on service","Požadovaný CEM klíč byl úspěšně instalován spolu s jím spojeným software."
58
+ "Module Identifier","Identifikátor modulu"
59
+ "The license key has been sent to your email inbox (%s).","Licenční klíč byl odeslán do vaší emailové schránky (%s)."
60
+ "Rollback","Vrácení verze"
61
+ "Update","Aktualizovat"
62
+ "Install","Instalovat"
63
+ "Extension Identifier","Identifikátor rozšíření"
64
+ "License","Licence"
65
+ "Update Automatically","Automaticky aktualizovat"
66
+ "Yes","Ano"
67
+ "No","ne"
68
+ "Please provide a valid package identifier","Prosím zadejte platný identifikátor balíčku"
69
+ "Please provide a valid license key","Prosím zadejte platný licenční klíč"
70
+ "The extension was successfully installed","Rozšíření bylo úspěšně instalováno."
71
+ "An unknown error has occurred, the requested extension couldn't be installed","Došlo k neznámé chybě, požadované rozšíření se nepodařilo instalovat."
72
+ "The extension was updated successfully","Rozšíření bylo úspěšně aktualizováno."
73
+ "An unknown error has occurred, the requested extension couldn't be updated","Došlo k neznámé chybě, požadované rozšíření se nepodařilo aktualizovat."
74
+ "registration-magento-version","Vaše verze Magento je <b>%s</b>. U verze nižší než <b>1.2.0</b> je nutné ručně vyplnit váš registrační email ručně před tím, než budete moci použít CEM rozšíření."
75
+ "registration-process","<p>1. Přejděte do <b>Systém &rarr; Nastavení</b> a klikněte na záložku <b>Systém</b> ve skupině <b>Rozšířené</b> ve spodní částí seznamu vlevo.</p>
76
+ <p>2. Klikněte na sekci <b>CEM</b> pro její rozbalení.</p>
77
+ <p>3. Nyní vyplňte svou emailovou adresu do příslušného pole.</p>
78
+ <p>4. Uložte nastavení.</p>
79
+ <p>5. Vymažte cache Magento.</p>"
80
+ "registration-note","<p><b><u>Upozornění</u></b></p><p>Emailová adresa, kterou ze vyplníte bude použita v případě, že budete potřebovat obnovit ztracené CEM a licenční klíče. Zaznamenejte emailovou adresu, kterou zde vyplníte, protože bude nutné vyplnit stejnou adresu, pokud se v budoucnu rozhodnete přeinstalovat Magento a budete chtít obnovit své licence a znovu instalovat svá komerční rozšíření.</p>"
81
+ "registration-assistence","Pokud potřebujete další asistenci, podívejte se na <a href=""http://easycommerce.cz/cem-uzivatelska-prirucka#c_3"" target=""_blank"">Možnosti nastavení CEM, kapitola 3</a>."
82
+ "registration-email","Abyste mohli používat Commercial Extension Manager, je nutné zadat emailovou adresu, která bude spojena se všemi vašemi licenčními klíči. Pokud byste v budoucnu přeinstalovali váš Magento obchod, tato adresa bude použita k obnově všech vašich licenčních klíčů. Ujistěte se, že vkládáte <b><u>platnou</u></b> emailovou adresu."
83
+ "registration-email-note","<b>Upozornění:</b> pokud reinstalujete váš Magento obchod nebo CEM rozšíření, je nutné zadat stejnou emailovou adresu, jako jste použili v předchozí instalaci, aby bylo možné obnovit vaše CEM a licenční klíče."
84
+ "CEM has now been registered and is ready for use","CEM byl úspěšně registrován a je připraven k použití."
85
+ "Recover Lost License Key","Obnovit ztracený licenční klíč"
86
+ "Recover Lost CEM Key","Obnovit ztracený CEM klíč"
87
+ "An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance.","Došlo k neznámé chybě SOAP při požadavku na CEM klíč. Prosím kontaktujte EasyCommerce pro asistenci."
88
+ "Please provide a valid service url and module identifier","Prosím zadejte platnou URL adresu služby a identifikátor modulu"
89
+ "The provided service url doesn't exists in your database. No matching CEM key was found. You'll have to retrieve your CEM key from the provided service using the 'Lost CEM Key' section before you can retrieve any lost license keys.","Zadaná URL adresa služby se nevyskytuje ve vaší databázi. Nebyl nalezen související CEM klíč. Je nutné, abyste nejprve získali váš CEM klíč služby v sekci 'Ztracený CEM klíč' před tím, než budete moci obnovit vaše licenční klíče."
90
+ "Unable to retrieve any CEM key. Please contact your software retailer for assistance.","Nepodařilo se získat žádný CEM klíč. Prosím kontaktujte EasyCommerce pro asistenci."
91
+ "An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance.","Došlo k neznámé chybě SOAP při požadavku na CEM klíč. Prosím kontaktujte EasyCommerce pro asistenci."
92
+ "Please provide a valid service url and CEM key","Prosím zadejte platnou URL adresu služby a CEM klíč"
93
+ "An unknown SOAP error occurred while install the CEM key. Please contact your retailer for assistance.","Došlo k neznámé chybě SOAP při instalaci CEM klíče. Prosím kontaktujte EasyCommerce pro asistenci."
94
+ "No packages could be found that were associated with the provided CEM key. Make sure that the CEM key is valid and try again.","Nebyly nalezeny žádné balíčky, které by byly spojeny se zadaným CEM klíčem. Ujistěte se, že CEM klíč je platný a zkuste to znovu."
95
+ "Unable to find the extension requested for update.","Nenalezeno žádné rozšíření k aktualizaci."
96
+ "An unknown SOAP error occurred while the new CEM key was created. Please contact your retailer for assistance.","Došlo k neznámé chybě SOAP při vytváření CEM klíče. Prosím kontaktujte EasyCommerce pro asistenci."
97
+ "An unknown SOAP error occurred while installing the extension. Please contact your retailer for assistance.","Došlo k neznámé chybě SOAP při instalaci rozšíření. Prosím kontaktujte EasyCommerce pro asistenci."
98
+ "PEAR has not been loaded. Unable to extract installation file.","PEAR nebyl načten. Není možné rozbalit instalační soubor."
99
+ "Archive_Tar has not been loaded. Unable to extract installation file.","Archive_Tar nebyl načten. Není možné rozbalit instalační soubor."
100
+ "No extensions were updated","Nebyla aktualizována žádná rozšíření"
101
+ "Extensions was successfully updated","Rozšíření byla aktualizována"
app/locale/en_US/Easy_CEM.csv ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Register","Register"
2
+ "An unknown error has occurred, please contact MageParts and notify us of your issue","An unknown error has occurred, please contact MageParts and notify us of your issue"
3
+ "OK","OK"
4
+ "Back","Back"
5
+ "License Management","License Management"
6
+ "Lost CEM Key","Lost CEM Key"
7
+ "Lost License Key","Lost License Key"
8
+ "Update Extension '%s'","Update Extension '%s'"
9
+ "Install New Extension","Install New Extension"
10
+ "Title","Title"
11
+ "Version","Version"
12
+ "Updated at","Updated at"
13
+ "Updates Available","Updates Available"
14
+ "Manage Extensions <span class=""powered""><a href=""http://www.mageparts.com"" target=""_blank"">Powered by MageParts.com</a></span>","Manage Extensions <span class=""powered""><a href=""http://www.mageparts.com"" target=""_blank"">Powered by MageParts.com</a></span>"
15
+ "Update Extensions","Update Extensions"
16
+ "System","System"
17
+ "Magento Connect","Magento Connect"
18
+ "Commercial Extension Manager","Commercial Extension Manager"
19
+ "The provided service url is either invalid or unreachable. Make sure that the service url you provided is correct and try again in a few minutes. If the problem consists we advise you to contact your software retailer for assistance.","The provided service url is either invalid or unreachable. Make sure that the service url you provided is correct and try again in a few minutes. If the problem consists we advise you to contact your software retailer for assistance."
20
+ "Unable to save service information in local database. Please contact your retailer for assistance.","Unable to save service information in local database. Please contact your retailer for assistance."
21
+ "Unable data recieved from service database. Please contact your software retailer for assistance.","Unable data recieved from service database. Please contact your software retailer for assistance."
22
+ "Unable to save CEM key information in local database. Please contact your retailer for assistance.","Unable to save CEM key information in local database. Please contact your retailer for assistance."
23
+ "This package no longer exists","This package no longer exists"
24
+ "Update Extension","Update Extension"
25
+ "Install New Etension","Install New Etension"
26
+ "The installation couldn't be completed due to an unknown error. Please contact your software retailer for assistance.","The installation couldn't be completed due to an unknown error. Please contact your software retailer for assistance."
27
+ "The extension is already up-to-date","The extension is already up-to-date"
28
+ "The email address you provided is invalid, please make sure that it's correct and try again.","The email address you provided is invalid, please make sure that it's correct and try again."
29
+ "Unable to refresh cache, please refresh the cache manually.","Unable to refresh cache, please refresh the cache manually."
30
+ "You need to provide a valid email address","You need to provide a valid email address"
31
+ "1 Hour","1 Hour"
32
+ "2 Hours","2 Hours"
33
+ "6 Hours","6 Hours"
34
+ "12 Hours","12 Hours"
35
+ "24 Hours","24 Hours"
36
+ "Unable to save package information, please try again","Unable to save package information, please try again"
37
+ "Unable to save CEM key, please contact your software retailer","Unable to save CEM key, please contact your software retailer"
38
+ "CEM key is empty, please contact your retailer","CEM key is empty, please contact your retailer"
39
+ "The version of your Magento installation is too old to support the requested version of this extension. The minimum required version of Magento is %s, the maximum allowed is %s. The currently installed version of Magento is %s. Please upgrade your Magento installation to meet these requirements and try again. If you require any further assistance we advise you to contact your software retailer.","The version of your Magento installation is too old to support the requested version of this extension. The minimum required version of Magento is %s, the maximum allowed is %s. The currently installed version of Magento is %s. Please upgrade your Magento installation to meet these requirements and try again. If you require any further assistance we advise you to contact your software retailer."
40
+ "The version of your Magento installation is too new to support the requested version of this extension. You can not use this extension version togheter with a Magento installation with a version above %s or below %s. The currently installed version of Magento is %s. Please downgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer.","The version of your Magento installation is too new to support the requested version of this extension. You can not use this extension version togheter with a Magento installation with a version above %s or below %s. The currently installed version of Magento is %s. Please downgrade your Magento installation to meet these requirements and try again. If you any require further assistance we advise you to contact your software retailer."
41
+ "Unable to install extension, the following paths needs to be writable: \n\n","Unable to install extension, the following paths needs to be writable: \n\n"
42
+ "This package is already installed","This package is already installed"
43
+ "Unable to create / locate temp download directory. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","Unable to create / locate temp download directory. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."
44
+ "Unable to install the requested extension. Your var/tmp directory needs to be writable. If you are not sure how to make the directory writable we suggest that you contact your webadministrator for technical support.","Unable to install the requested extension. Your var/tmp directory needs to be writable. If you are not sure how to make the directory writable we suggest that you contact your webadministrator for technical support."
45
+ "An error occurred while completing the download of the source package file. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","An error occurred while completing the download of the source package file. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."
46
+ "Unable to install package. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator.","Unable to install package. Your Magento folder might not have sufficient write permissions, which this web based downloader requires. Please make sure that your permissions are correct and try again. If you need further assistance, please contact your server administrator."
47
+ "The installation was successfull but unable to cleanup installation files. Please make sure that your Magento directory has read and write permissions to avoid this problem in the future.","The installation was successfull but unable to cleanup installation files. Please make sure that your Magento directory has read and write permissions to avoid this problem in the future."
48
+ "An unknown SOAP error occurred while gathering module information. Please contact your retailer for assistance.","An unknown SOAP error occurred while gathering module information. Please contact your retailer for assistance."
49
+ "General Information","General Information"
50
+ "Service URL","Service URL"
51
+ "CEM Key","CEM Key"
52
+ "Please provide a valid service url","Please provide a valid service url"
53
+ "The CEM key has been sent to your email inbox (%s). Please insert the CEM key into the 'Cem Key' field and click the 'OK' button once more to install the CEM key and all of its associated software.","The CEM key has been sent to your email inbox (%s). Please insert the CEM key into the 'Cem Key' field and click the 'OK' button once more to install the CEM key and all of its associated software."
54
+ "An unknown error has occurred, the requested action was interrupted","An unknown error has occurred, the requested action was interrupted"
55
+ "The requested CEM key was successfully installed. The following extensions could not be automatically installed on your system:","The requested CEM key was successfully installed. The following extensions could not be automatically installed on your system:"
56
+ "Any unknown errors were most likely caused by insufficient writing permission. The extensions which failed to be installed will have to be installed manually, we appologize for your inconvenience.","Any unknown errors were most likely caused by insufficient writing permission. The extensions which failed to be installed will have to be installed manually, we appologize for your inconvenience."
57
+ "The requested CEM key was successfully installed along with all associated extensions found on service","The requested CEM key was successfully installed along with all associated extensions found on service"
58
+ "Module Identifier","Module Identifier"
59
+ "The license key has been sent to your email inbox (%s).","The license key has been sent to your email inbox (%s)."
60
+ "Rollback","Rollback"
61
+ "Update","Update"
62
+ "Install","Install"
63
+ "Extension Identifier","Extension Identifier"
64
+ "License","License"
65
+ "Update Automatically","Update Automatically"
66
+ "Yes","Yes"
67
+ "No","No"
68
+ "Please provide a valid package identifier","Please provide a valid package identifier"
69
+ "Please provide a valid license key","Please provide a valid license key"
70
+ "The extension was successfully installed","The extension was successfully installed"
71
+ "An unknown error has occurred, the requested extension couldn't be installed","An unknown error has occurred, the requested extension couldn't be installed"
72
+ "The extension was updated successfully","The extension was updated successfully"
73
+ "An unknown error has occurred, the requested extension couldn't be updated","An unknown error has occurred, the requested extension couldn't be updated"
74
+ "registration-magento-version","Your Magento version is <b>%s</b>. In versions prior to <b>1.2.0</b> you will have to fill out your registration email manually before you can use the CEM extension."
75
+ "registration-process","<p>1. Go to <b>System &rarr; Configuration</b> and click on the <b>System</b> tab under the group <b>Advanced</b> at the bottom of the left-hand list.</p>
76
+ <p>2. Click on the <b>CEM</b> section to expand it.</p>
77
+ <p>3. Now fill out your email address in the corresponding field.</p>
78
+ <p>4. Save the configuration.</p>
79
+ <p>5. Clear your cache.</p>"
80
+ "registration-note","<p><b><u>Please note</u></b></p><p>The email address you provide here will be used when you need to recover lost CEM and license keys. Be sure to remember the email address you assign here, you will need to enter the same one if you ever reinstall your webshop in order to recover your license keys and reinstall your commercial extensions.</p>"
81
+ "registration-assistence","If you require further assistance we refer you to the <a href=""http://www.mageparts.com/mageparts-cem-user-guide#c_3"" target=""_blank"">CEM documentation chapter 3</a>."
82
+ "registration-email","In order to use the Commercial Extension Manager you will need to enter an email address which will be associated with all your license keys. If you would ever need to reinstall your Magento shop this email can be used to recover all your license keys, so please be sure to enter a <b><u>valid</u></b> email address."
83
+ "registration-email-note","<b>Please note:</b> if you are reinstalling your Magento shop or the CEM extension you will need to enter the same email address as you used on your previous installation in order to recover your CEM and license keys."
84
+ "CEM has now been registered and is ready for use","CEM has now been registered and is ready for use"
85
+ "Recover Lost License Key","Recover Lost License Key"
86
+ "Recover Lost CEM Key","Recover Lost CEM Key"
87
+ "An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance.","An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance."
88
+ "Please provide a valid service url and module identifier","Please provide a valid service url and module identifier"
89
+ "The provided service url doesn't exists in your database. No matching CEM key was found. You'll have to retrieve your CEM key from the provided service using the 'Lost CEM Key' section before you can retrieve any lost license keys.","The provided service url doesn't exists in your database. No matching CEM key was found. You'll have to retrieve your CEM key from the provided service using the 'Lost CEM Key' section before you can retrieve any lost license keys."
90
+ "Unable to retrieve any CEM key. Please contact your software retailer for assistance.","Unable to retrieve any CEM key. Please contact your software retailer for assistance."
91
+ "An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance.","An unknown SOAP error occurred while requesting the CEM key. Please contact your retailer for assistance."
92
+ "Please provide a valid service url and CEM key","Please provide a valid service url and CEM key"
93
+ "An unknown SOAP error occurred while install the CEM key. Please contact your retailer for assistance.","An unknown SOAP error occurred while install the CEM key. Please contact your retailer for assistance."
94
+ "No packages could be found that were associated with the provided CEM key. Make sure that the CEM key is valid and try again.","No packages could be found that were associated with the provided CEM key. Make sure that the CEM key is valid and try again."
95
+ "Unable to find the extension requested for update.","Unable to find the extension requested for update."
96
+ "An unknown SOAP error occurred while the new CEM key was created. Please contact your retailer for assistance.","An unknown SOAP error occurred while the new CEM key was created. Please contact your retailer for assistance."
97
+ "An unknown SOAP error occurred while installing the extension. Please contact your retailer for assistance.","An unknown SOAP error occurred while installing the extension. Please contact your retailer for assistance."
98
+ "PEAR has not been loaded. Unable to extract installation file.","PEAR has not been loaded. Unable to extract installation file."
99
+ "Archive_Tar has not been loaded. Unable to extract installation file.","Archive_Tar has not been loaded. Unable to extract installation file."
package.xml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Easy_CEM</name>
4
+ <version>1.0.5</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Czech: Mana&#x17E;er pro instalaci a aktualizaci komer&#x10D;n&#xED;ch roz&#x161;&#xED;&#x159;en&#xED; EasyCommerce zalo&#x17E;en&#xFD; na MageParts CEM.</summary>
10
+ <description>Czech&#xFEFF;&#xD;
11
+ &#xD;
12
+ Instalace a aktualizace komer&#x10D;n&#xED;ch roz&#x161;&#xED;&#x159;en&#xED; EasyCommerce v Magento je nyn&#xED; jednoduch&#xE1;, jak jen m&#x16F;&#x17E;e b&#xFD;t. EasyCommerce Mana&#x17E;er komer&#x10D;n&#xED;ch roz&#x161;&#xED;&#x159;en&#xED; (CEM) umo&#x17E;&#x148;uje jednodu&#x161;e instalovat roz&#x161;&#xED;&#x159;en&#xED; EasyCommerce a udr&#x17E;ovat je aktu&#xE1;ln&#xED;.&#xD;
13
+ &#xD;
14
+ Hlavn&#xED; p&#x159;ednosti:&#xD;
15
+ &#xD;
16
+ * Jednoduch&#xE1; instalace roz&#x161;&#xED;&#x159;en&#xED; &#xD;
17
+ &#xD;
18
+ * Automatick&#xE1; aktualizace zakoupen&#xFD;ch roz&#x161;&#xED;&#x159;en&#xED; EasyCommerce &#xD;
19
+ &#xD;
20
+ * Spr&#xE1;va licen&#x10D;n&#xED;ch kl&#xED;&#x10D;&#x16F; &#xD;
21
+ &#xD;
22
+ * Logov&#xE1;n&#xED; p&#x159;&#xED;padn&#xFD;ch chyb p&#x159;i instalaci (pokud nastane probl&#xE9;m b&#x11B;hem instalace nebo aktualizace roz&#x161;&#xED;&#x159;en&#xED;), o kter&#xFD;ch je EasyCommerce zasl&#xE1;n report pro sna&#x17E;&#x161;&#xED; &#x159;e&#x161;en&#xED;.</description>
23
+ <notes>Derived from MageParts CEM</notes>
24
+ <authors><author><name>Vladan Zajda</name><user>auto-converted</user><email>info@easycommerce.cz</email></author></authors>
25
+ <date>2011-05-18</date>
26
+ <time>07:52:42</time>
27
+ <contents><target name="magecommunity"><dir name="Easy"><dir name="CEM"><dir name="Block"><dir name="Adminhtml"><dir name="Licenses"><dir name="Edit"><dir name="Tab"><file name="LostCem.php" hash="fc8af356cb234661d6918914e072e771"/><file name="LostLicense.php" hash="bd1a84650d69c3ba6de44d6259520451"/></dir><file name="Form.php" hash="52d974fced36d0cd6b48a01434ca7d5d"/><file name="Tabs.php" hash="3aaaf3edc1b7e58d9fe3a8a61eb2e578"/></dir><file name="Edit.php" hash="e214adedd257a751c163a9df146d8433"/></dir><dir name="Packages"><dir name="Grid"><dir name="Renderer"><file name="UpdateAvailable.php" hash="dbd0a75910731924a2d20c488db3f053"/></dir></dir><file name="Edit.php" hash="885502a69f7ee43d12baf85506a8b0f0"/><file name="Grid.php" hash="298d0a574aa9bc2b3228894e8e508990"/></dir><file name="Packages.php" hash="55026b072f2d9c41a1d5340aec9b1d96"/></dir></dir><dir name="Helper"><file name="Data.php" hash="a1a1a87efd94a609831c3199b94c1d71"/></dir><dir name="Model"><dir name="Mysql4"><dir name="Licenses"><file name="Collection.php" hash="0ae7d35bd8e58fee87a4593fd8cd81a2"/></dir><dir name="Packages"><file name="Collection.php" hash="221c4a936dd379a158bc292815a451d5"/></dir><dir name="Services"><file name="Collection.php" hash="c79c3465fb8f77c377af3ebc167534ab"/></dir><file name="Licenses.php" hash="cd06234a3829d4037bfd510444d2b944"/><file name="Packages.php" hash="9e7e809ee21e8ec3a3fbdc11f64f70c5"/><file name="Services.php" hash="2722eca7d2a8eb16627ad8839f2bcc1e"/></dir><dir name="Soap"><file name="class.nusoap_base.php" hash="6fd24efd5f95d078f7211ba52299e226"/><file name="class.soap_fault.php" hash="a8f5a9a4e7dd155548b7c65bb78803c9"/><file name="class.soap_parser.php" hash="0aedf7ad6c87cccb2579f590996dc2bb"/><file name="class.soap_server.php" hash="c3031e2a691ec51900bccc36dacd41e5"/><file name="class.soap_transport_http.php" hash="9daa9314ee7314cae7a53569c62fa339"/><file name="class.soap_val.php" hash="0a42c13026e8d7c834363d71b092746f"/><file name="class.soapclient.php" hash="dce25c5cc15d3d92b6914060e3371729"/><file name="class.wsdl.php" hash="b74e13dd0148cc0bbdf7ffb262dd74ad"/><file name="class.wsdlcache.php" hash="4b29ee6819f0a7a396090b25c30bae6c"/><file name="class.xmlschema.php" hash="0215f77d8132d5cf2d9d7a4b4864e6bc"/><file name="nusoap.php" hash="f3b945d03d24503164def1a3d451d2e0"/><file name="nusoapmime.php" hash="38f7854e7c2e53827600fe7808e0d3d9"/></dir><dir name="System"><dir name="Config"><dir name="Source"><dir name="CEM"><file name="Frequency.php" hash="8289f3e6b50233bf848047d6069af94c"/></dir></dir></dir></dir><file name="Licenses.php" hash="52c6d0f6c7de78f48f5c54e6dab3cb5c"/><file name="Observer.php" hash="87ca85aa68bb29dd597452d3797451c1"/><file name="Packages.php" hash="c4d949eec74dda4ddbdcf474dba2fdf7"/><file name="Services.php" hash="98f707b3c8f851faf4c4b341b67b648f"/><file name="Soap.php" hash="46af565c585566107add6ba22c3b32f5"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="LicensesController.php" hash="c1aa28c8d61ab416ef084c58fa4f3953"/><file name="PackagesController.php" hash="da181da178e77387abc04ea2742e113e"/></dir><file name="IndexController.php" hash="ada180d021aa6682ed1e602b5488acd7"/></dir><dir name="etc"><file name="config.xml" hash="658f9f99ded623fe98733732d5b6bcd6"/><file name="system.xml" hash="4b2a4865616e109eb21a64e3306cf090"/></dir><dir name="sql"><dir name="cem_setup"><file name="mysql4-install-1.0.0.php" hash="9813d502640dd11eb65a64ae68adbf1d"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Easy_CEM.xml" hash="a753c329b278b7a586dcb1af2fd5d35b"/></dir></target><target name="magelocale"><dir name="en_US"><file name="Easy_CEM.csv" hash="26df2c2f7945f38271a17bd874126534"/></dir><dir name="cs_CZ"><file name="Easy_CEM.csv" hash="64d38b0a174540df50d35a715332f0c9"/></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="cem"><dir name="i"><file name="extension_icon.gif" hash="843f868b374f24ba7647a25a5ecbef78"/><file name="key_icon.gif" hash="058865b00e0b3bd3e6db418c3a0cee66"/><file name="lost_key_icon.gif" hash="b64ba0ec40a3e2a9bdd1b5ad00e754db"/><file name="notify_icon.gif" hash="2ec94a242362add6864f8f2845d9e58f"/><file name="package_add_icon.gif" hash="a742bc83cefc6ff1493b8c1afe6ef9ea"/></dir><file name="style.css" hash="d9e72d66b4b3267e93194afd242e12a0"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="cem.xml" hash="aeb450122e8e2ff80809e05f23831912"/></dir><dir name="template"><dir name="cem"><dir name="licenses"><file name="lostcem.phtml" hash="9c2753e3645e91ee77740ec36ec0b81c"/><file name="lostlicense.phtml" hash="ceccf7cb2a32666d98084f7b75dbd36c"/></dir><dir name="packages"><file name="install.phtml" hash="c0e38bdfa57441b8a4f34cc9222584d3"/><file name="register.phtml" hash="c819f026356d44f88f0820dab7ac16b2"/></dir></dir></dir></dir></dir></dir></target></contents>
28
+ <compatible/>
29
+ <dependencies/>
30
+ </package>
skin/adminhtml/default/default/cem/i/extension_icon.gif ADDED
Binary file
skin/adminhtml/default/default/cem/i/key_icon.gif ADDED
Binary file
skin/adminhtml/default/default/cem/i/lost_key_icon.gif ADDED
Binary file
skin/adminhtml/default/default/cem/i/notify_icon.gif ADDED
Binary file
skin/adminhtml/default/default/cem/i/package_add_icon.gif ADDED
Binary file
skin/adminhtml/default/default/cem/style.css ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * MageParts
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Open Software License (OSL 3.0)
7
+ * that is bundled with this package in the file LICENSE.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/osl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * @category MageParts
15
+ * @package skin_default
16
+ * @copyright Copyright (c) 2009 MageParts (http://www.mageparts.com/)
17
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
18
+ */
19
+
20
+ .grid-update-available-no {
21
+ background-image:none;
22
+ }
23
+
24
+ .grid-update-available-yes {
25
+ width:14px;
26
+ height:14px;
27
+ background:url(i/notify_icon.gif) no-repeat;
28
+ }
29
+
30
+ .head-cem-licenses {
31
+ background-image:url(../images/fam_page_white.gif);
32
+ }
33
+
34
+
35
+ .icon-head.head-adminhtml-packages {
36
+ background-image:url(i/extension_icon.gif);
37
+ }
38
+
39
+ .icon-head.head-adminhtml-packages-install {
40
+ background-image:url(i/package_add_icon.gif);
41
+ }
42
+
43
+ .icon-head.head-adminhtml-lost-key {
44
+ background-image:url(i/lost_key_icon.gif);
45
+ }
46
+
47
+ #cem_licenses_tabs .tab-item-link,
48
+ #cem_licenses_tabs .tab-item-link.active span {
49
+ background-position:5px 50%;
50
+ background-repeat:no-repeat;
51
+ }
52
+
53
+ #cem_licenses_tabs_lost_cem_section.tab-item-link,
54
+ #cem_licenses_tabs_lost_license_section.tab-item-link,
55
+ #cem_licenses_tabs_lost_cem_section.tab-item-link.active span,
56
+ #cem_licenses_tabs_lost_license_section.tab-item-link.active span {
57
+ background-image:url(i/lost_key_icon.gif);
58
+ }
59
+
60
+ #cem_licenses_tabs span.changed,
61
+ #cem_licenses_tabs span.error {
62
+ background-image:none;
63
+ }
64
+
65
+ #cem_licenses_tabs .tab-item-link span {
66
+ padding-left:25px;
67
+ }
68
+
69
+ span.powered {
70
+ font-size: 9px;
71
+ font-style: italic;
72
+ margin-left: 10px;
73
+ }
74
+
75
+ #cem_licenses_tabs_lost_cem_section.tab-item-link.active span span.changed,
76
+ #cem_licenses_tabs_lost_license_section.tab-item-link.active span span.changed {
77
+ background:none;
78
+ }
79
+
80
+ #cem_licenses_tabs_lost_cem_section.tab-item-link.active span span.error,
81
+ #cem_licenses_tabs_lost_license_section.tab-item-link.active span span.error {
82
+ background:none;
83
+ }