WP eCommerce - Version 3.8.12-beta

Version Description

Download this release

Release Info

Developer garyc40
Plugin Icon 128x128 WP eCommerce
Version 3.8.12-beta
Comparing to
See all releases

Code changes from version 3.8.11.1 to 3.8.12-beta

Files changed (77) hide show
  1. .gitignore +1 -0
  2. readme.txt +19 -2
  3. wp-shopping-cart.php +1 -1
  4. wpsc-admin/admin.php +0 -3
  5. wpsc-admin/ajax.php +0 -13
  6. wpsc-admin/css/admin.css +48 -9
  7. wpsc-admin/css/settingspage.css +64 -26
  8. wpsc-admin/display-coupon-add.php +1 -1
  9. wpsc-admin/display-coupon-edit.php +1 -1
  10. wpsc-admin/display-items.page.php +57 -25
  11. wpsc-admin/display-sales-logs.php +1 -1
  12. wpsc-admin/display-upgrades.page.php +0 -7
  13. wpsc-admin/includes/coupon-list-table-class.php +2 -8
  14. wpsc-admin/includes/purchase-log-list-table-class.php +10 -8
  15. wpsc-admin/includes/purchase-logs-page/item-details.php +1 -1
  16. wpsc-admin/includes/purchase-logs-page/list-table.php +0 -8
  17. wpsc-admin/includes/save-data.functions.php +340 -358
  18. wpsc-admin/includes/settings-tabs/admin.php +1 -1
  19. wpsc-admin/includes/settings-tabs/checkout.php +58 -65
  20. wpsc-admin/includes/settings-tabs/general.php +126 -118
  21. wpsc-admin/includes/settings-tabs/import.php +163 -63
  22. wpsc-admin/includes/settings-tabs/marketing.php +1 -1
  23. wpsc-admin/includes/settings-tabs/presentation.php +25 -14
  24. wpsc-admin/includes/settings-tabs/shipping.php +237 -226
  25. wpsc-admin/includes/settings-tabs/taxes.php +127 -157
  26. wpsc-admin/init.php +1 -5
  27. wpsc-admin/js/admin.js +1 -1
  28. wpsc-admin/js/ajax.js +0 -48
  29. wpsc-admin/js/dimensions.js +0 -325
  30. wpsc-admin/js/jquery-ui.js +0 -1
  31. wpsc-admin/js/product_tagcloud.js +0 -125
  32. wpsc-admin/js/settings-page.js +84 -27
  33. wpsc-admin/js/wpsc-swfupload-handlers.js +0 -362
  34. wpsc-components/merchant-core-v2/helpers/checkout.php +2 -2
  35. wpsc-core/images/black-star.png +0 -0
  36. wpsc-core/images/core-sprite.png +0 -0
  37. wpsc-core/images/gold-star.gif +0 -0
  38. wpsc-core/images/gold-star.png +0 -0
  39. wpsc-core/images/grey-star.gif +0 -0
  40. wpsc-core/images/grey-star.png +0 -0
  41. wpsc-core/images/mobile.png +0 -0
  42. wpsc-core/js/ajax.js +0 -48
  43. wpsc-core/js/iautocompleter.js +0 -536
  44. wpsc-core/js/interface.js +0 -8
  45. wpsc-core/js/jquery.accessible-news-slider.js +0 -67
  46. wpsc-core/js/jquery.infieldlabel.min.js +0 -11
  47. wpsc-core/js/jquery.jeditable.pack.js +0 -1
  48. wpsc-core/js/swfupload.js +0 -928
  49. wpsc-core/js/swfupload.swf +0 -0
  50. wpsc-core/js/swfupload/SWFObject License.txt +0 -4
  51. wpsc-core/js/swfupload/swfupload.cookies.js +0 -53
  52. wpsc-core/js/swfupload/swfupload.gears.js +0 -1035
  53. wpsc-core/js/swfupload/swfupload.queue.js +0 -77
  54. wpsc-core/js/swfupload/swfupload.swfobject.js +0 -110
  55. wpsc-core/js/user.js +2 -2
  56. wpsc-core/js/wp-e-commerce.js +5 -12
  57. wpsc-core/wpsc-constants.php +3 -3
  58. wpsc-core/wpsc-functions.php +7 -5
  59. wpsc-core/wpsc-installer.php +1 -0
  60. wpsc-includes/ajax.functions.php +10 -10
  61. wpsc-includes/cart.class.php +7 -4
  62. wpsc-includes/checkout.class.php +7 -6
  63. wpsc-includes/coupons.class.php +1 -1
  64. wpsc-includes/display.functions.php +54 -29
  65. wpsc-includes/nusoap/changelog +0 -584
  66. wpsc-includes/nusoap/class.nusoap_base.php +0 -984
  67. wpsc-includes/nusoap/class.soap_fault.php +0 -90
  68. wpsc-includes/nusoap/class.soap_parser.php +0 -639
  69. wpsc-includes/nusoap/class.soap_server.php +0 -1073
  70. wpsc-includes/nusoap/class.soap_transport_http.php +0 -1305
  71. wpsc-includes/nusoap/class.soap_val.php +0 -107
  72. wpsc-includes/nusoap/class.soapclient.php +0 -977
  73. wpsc-includes/nusoap/class.wsdl.php +0 -1904
  74. wpsc-includes/nusoap/class.wsdlcache.php +0 -209
  75. wpsc-includes/nusoap/class.xmlschema.php +0 -938
  76. wpsc-includes/nusoap/nusoap.php +0 -7993
  77. wpsc-includes/nusoap/nusoapmime.php +0 -423
.gitignore ADDED
@@ -0,0 +1 @@
 
1
+ .idea
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === WP e-Commerce ===
2
- Contributors: mufasa, garyc40, JustinSainton, mychelle
3
  Donate link: http://getshopped.org
4
  Tags: e-commerce, wp-e-commerce, shop, cart, paypal, authorize, stock control, ecommerce, shipping, tax
5
  Requires at least: 3.4
6
  Tested up to: 3.6
7
- Stable tag: 3.8.11.1
8
 
9
  WP e-Commerce is a free WordPress Shopping Cart Plugin that lets customers buy your products, services and digital downloads online.
10
 
@@ -146,6 +146,23 @@ After upgrading from earlier versions look for link "Update Store". This will up
146
 
147
  == Changelog ==
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  = 3.8.11.1 =
150
  * Fix: Some users had theme compatibilities and other configurations that caused "Add to Cart" to no longer function as expected.
151
  * Fix: Customer uploads for products broke with JS overhaul
1
  === WP e-Commerce ===
2
+ Contributors: mufasa, garyc40, JustinSainton
3
  Donate link: http://getshopped.org
4
  Tags: e-commerce, wp-e-commerce, shop, cart, paypal, authorize, stock control, ecommerce, shipping, tax
5
  Requires at least: 3.4
6
  Tested up to: 3.6
7
+ Stable tag: 3.8.11
8
 
9
  WP e-Commerce is a free WordPress Shopping Cart Plugin that lets customers buy your products, services and digital downloads online.
10
 
146
 
147
  == Changelog ==
148
 
149
+ = 3.8.12 =
150
+ * New: Filter to hide drafts on the front-end: "wpsc_product_display_status"
151
+ * New: Shipwire staging / production option
152
+ * Change: Remove deprecated and unused javascript (and by extension, CSS) from core
153
+ * Change: Remove nusoap
154
+ * Change: Improvements to Marketing admin panel
155
+ * Change: Improvements to Products List Admin Page
156
+ * Fix: WP e-Commerce pagination breaks WordPress pagination
157
+ * Fix: Wrong thumbnail size in Product Specials widget
158
+ * Fix: Filtering by a category also shows all products in subcategories
159
+ * Fix: admin.js throwing a Parse Error in Safari
160
+ * Fix: Product Image Links not working when over HTTPS
161
+ * Fix: If AJAX_URL returns HTTPS and Add to Cart is on HTTP, errors
162
+ * Fix: Add to Cart button doesn't work
163
+ * Fix: Can no longer upload customer attachments
164
+
165
+
166
  = 3.8.11.1 =
167
  * Fix: Some users had theme compatibilities and other configurations that caused "Add to Cart" to no longer function as expected.
168
  * Fix: Customer uploads for products broke with JS overhaul
wp-shopping-cart.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: WP e-Commerce
4
  * Plugin URI: http://getshopped.org/
5
  * Description: A plugin that provides a WordPress Shopping Cart. See also: <a href="http://getshopped.org" target="_blank">GetShopped.org</a> | <a href="http://getshopped.org/forums/" target="_blank">Support Forum</a> | <a href="http://docs.getshopped.org/" target="_blank">Documentation</a>
6
- * Version: 3.8.11.1
7
  * Author: Instinct Entertainment
8
  * Author URI: http://getshopped.org/
9
  **/
3
  * Plugin Name: WP e-Commerce
4
  * Plugin URI: http://getshopped.org/
5
  * Description: A plugin that provides a WordPress Shopping Cart. See also: <a href="http://getshopped.org" target="_blank">GetShopped.org</a> | <a href="http://getshopped.org/forums/" target="_blank">Support Forum</a> | <a href="http://docs.getshopped.org/" target="_blank">Documentation</a>
6
+ * Version: 3.8.12-beta
7
  * Author: Instinct Entertainment
8
  * Author URI: http://getshopped.org/
9
  **/
wpsc-admin/admin.php CHANGED
@@ -437,7 +437,6 @@ function wpsc_admin_include_coupon_js() {
437
  */
438
  function wpsc_admin_include_optionspage_css_and_js() {
439
  $version_identifier = WPSC_VERSION . "." . WPSC_MINOR_VERSION;
440
- wp_enqueue_script( 'wp-e-commerce-js-ajax', WPSC_URL . '/wpsc-core/js/ajax.js', false, $version_identifier );
441
  wp_enqueue_script( 'wp-e-commerce-admin-settings-page', WPSC_URL . '/wpsc-admin/js/settings-page.js', array( 'jquery-query' ), $version_identifier );
442
 
443
  wp_localize_script( 'wp-e-commerce-admin-settings-page', 'WPSC_Settings_Page', array(
@@ -533,8 +532,6 @@ function wpsc_admin_include_css_and_js_refac( $pagehook ) {
533
  wp_enqueue_script( 'livequery', WPSC_URL . '/wpsc-admin/js/jquery.livequery.js', array( 'jquery' ), '1.0.3' );
534
  wp_enqueue_script( 'wp-e-commerce-admin-parameters', admin_url( 'admin.php?wpsc_admin_dynamic_js=true' ), false, $version_identifier );
535
  wp_enqueue_script( 'wp-e-commerce-admin', WPSC_URL . '/wpsc-admin/js/admin.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-sortable' ), $version_identifier, false );
536
- wp_enqueue_script( 'wp-e-commerce-legacy-ajax', WPSC_URL . '/wpsc-admin/js/ajax.js', false, $version_identifier ); // needs removing
537
-
538
  wp_enqueue_script( 'wpsc-sortable-table', WPSC_URL . '/wpsc-admin/js/sortable-table.js', array( 'jquery' ) );
539
 
540
  if ( in_array( $current_screen->id, array( 'wpsc-product', 'edit-wpsc-variation', 'wpsc-product' ) ) ) {
437
  */
438
  function wpsc_admin_include_optionspage_css_and_js() {
439
  $version_identifier = WPSC_VERSION . "." . WPSC_MINOR_VERSION;
 
440
  wp_enqueue_script( 'wp-e-commerce-admin-settings-page', WPSC_URL . '/wpsc-admin/js/settings-page.js', array( 'jquery-query' ), $version_identifier );
441
 
442
  wp_localize_script( 'wp-e-commerce-admin-settings-page', 'WPSC_Settings_Page', array(
532
  wp_enqueue_script( 'livequery', WPSC_URL . '/wpsc-admin/js/jquery.livequery.js', array( 'jquery' ), '1.0.3' );
533
  wp_enqueue_script( 'wp-e-commerce-admin-parameters', admin_url( 'admin.php?wpsc_admin_dynamic_js=true' ), false, $version_identifier );
534
  wp_enqueue_script( 'wp-e-commerce-admin', WPSC_URL . '/wpsc-admin/js/admin.js', array( 'jquery', 'jquery-ui-core', 'jquery-ui-sortable' ), $version_identifier, false );
 
 
535
  wp_enqueue_script( 'wpsc-sortable-table', WPSC_URL . '/wpsc-admin/js/sortable-table.js', array( 'jquery' ) );
536
 
537
  if ( in_array( $current_screen->id, array( 'wpsc-product', 'edit-wpsc-variation', 'wpsc-product' ) ) ) {
wpsc-admin/ajax.php CHANGED
@@ -736,19 +736,6 @@ function _wpsc_ajax_add_tax_rate() {
736
  );
737
  $returnable = $wpec_taxes_controller->wpec_taxes_build_select_options( $regions, 'region_code', 'name', $default_option, $select_settings );
738
  break;
739
- case 'wpec_taxes_build_rates_form':
740
- $key = $_REQUEST['current_key'];
741
- $returnable = $wpec_taxes_controller->wpec_taxes_build_form( $key );
742
- break;
743
- case 'wpec_taxes_build_bands_form':
744
- $key = $_REQUEST['current_key'];
745
- //get a new key if a band is already defined for this key
746
- while($wpec_taxes_controller->wpec_taxes->wpec_taxes_get_band_from_index($key))
747
- {
748
- $key++;
749
- }
750
- $returnable = $wpec_taxes_controller->wpec_taxes_build_form( $key, false, 'bands' );
751
- break;
752
  }// switch
753
 
754
  return array(
736
  );
737
  $returnable = $wpec_taxes_controller->wpec_taxes_build_select_options( $regions, 'region_code', 'name', $default_option, $select_settings );
738
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  }// switch
740
 
741
  return array(
wpsc-admin/css/admin.css CHANGED
@@ -2,6 +2,29 @@
2
  * This is the new WPSC Admin CSS file
3
 
4
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  ul.variation_checkboxes li {
6
  margin: 1px 0 3px;
7
  }
@@ -1165,18 +1188,25 @@ ul.categorisation_links li{
1165
  ul.categorisation_links li.selected a{
1166
  color: #D54E21;
1167
  }
 
 
 
1168
 
1169
  .multiple-select {
1170
  background: white none repeat scroll 0px 0px;
1171
  border: 1px solid #DFDFDF;
1172
  display: inline-block;
1173
  height: 120px;
1174
- margin: 10px 0;
1175
  overflow-x: hidden;
1176
  overflow-y: auto;
1177
- padding: 0px;
1178
  position: relative;
1179
- width:98%
 
 
 
 
 
1180
  }
1181
 
1182
  table.category_forms a.delete_button {
@@ -1362,14 +1392,13 @@ a.wpsc_featured_product_toggle {
1362
  display: block;
1363
  height: 18px;
1364
  width: 18px;
1365
- margin: 4px 0px 0px 6px;
1366
  }
1367
 
1368
- a.wpsc_featured_product_toggle img {
1369
- display: block;
1370
- margin: 0px auto 0px auto;
1371
-
1372
- }
1373
 
1374
  div.wpsc_clear {
1375
  clear: both;
@@ -1979,3 +2008,13 @@ div.new_layer,
1979
  div#table_rate {
1980
  display:none;
1981
  }
 
 
 
 
 
 
 
 
 
 
2
  * This is the new WPSC Admin CSS file
3
 
4
  */
5
+ table.wp-list-table .column-title {
6
+ width: 26%;
7
+ }
8
+ table.wp-list-table .column-featured {
9
+ width: 30px;
10
+ }
11
+ table.wp-list-table .column-price,
12
+ table.wp-list-table .column-sale_price {
13
+ width: 8%;
14
+ }
15
+ table.wp-list-table .column-SKU {
16
+ width: 11%;
17
+ }
18
+ table.wp-list-table .column-stock {
19
+ width: 8%;
20
+ }
21
+ table.wp-list-table .column-weight {
22
+ width: 7%;
23
+ }
24
+ table.wp-list-table .column-cats {
25
+ width: 15%;
26
+ }
27
+
28
  ul.variation_checkboxes li {
29
  margin: 1px 0 3px;
30
  }
1188
  ul.categorisation_links li.selected a{
1189
  color: #D54E21;
1190
  }
1191
+ .multiple-select-container {
1192
+ margin-left: 0.5em;
1193
+ }
1194
 
1195
  .multiple-select {
1196
  background: white none repeat scroll 0px 0px;
1197
  border: 1px solid #DFDFDF;
1198
  display: inline-block;
1199
  height: 120px;
 
1200
  overflow-x: hidden;
1201
  overflow-y: auto;
1202
+ padding: 0 0 0 5px;
1203
  position: relative;
1204
+ }
1205
+ .multiple-select input {
1206
+ width: inherit;
1207
+ }
1208
+ .multiple-select label {
1209
+ display: inherit;
1210
  }
1211
 
1212
  table.category_forms a.delete_button {
1392
  display: block;
1393
  height: 18px;
1394
  width: 18px;
1395
+ margin: 4px 0px 0px 0px;
1396
  }
1397
 
1398
+ .column-featured a { background:url( '../../wpsc-core/images/core-sprite.png') no-repeat 0 -32px transparent; }
1399
+ .column-featured a.gold-star { background-position:0 -16px; }
1400
+ .column-featured a:active,
1401
+ .column-featured a.gold-star:active { background-position:0 0; }
 
1402
 
1403
  div.wpsc_clear {
1404
  clear: both;
2008
  div#table_rate {
2009
  display:none;
2010
  }
2011
+
2012
+ body.edit-tags-php img.wpsc_category_image {
2013
+ max-width:256px;
2014
+ max-height:256px;
2015
+ min-width:128px;
2016
+ }
2017
+
2018
+ .wpsc-width-height-fields label {
2019
+ display: inline;
2020
+ }
wpsc-admin/css/settingspage.css CHANGED
@@ -12,9 +12,6 @@ th#actions{
12
  th#drag{
13
  width:50px;
14
  }
15
- th#name {
16
- width:205px;
17
- }
18
  tr.wpsc_grey{
19
  background-color: #ededed;
20
  }
@@ -22,12 +19,35 @@ td.drag a:hover{
22
  cursor: move;
23
  }
24
 
25
- th.column-type{
26
- width:150px;
 
 
 
27
  }
28
 
29
  th.column-unique_name {
30
- width:150px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
33
  #checkout_message{
@@ -55,18 +75,14 @@ td.drag a img {
55
  margin-left:4px;
56
  }
57
 
58
- th.column-mandatory, th.column-display {
59
- width: 101px;
60
- }
61
-
62
- .widefat th.column-mandatory, td.mandatorycol, .widefat th.column-display, td.displaycol, .widefat th.column-trash, td.trashcol {
63
- text-align:center;
64
- }
65
-
66
  #wpsc_checkout_list .ui-sortable-helper {
67
  margin-left:0;
68
  }
69
 
 
 
 
 
70
  #wpsc_checkout_list .actionscol .cell-wrapper {
71
  float:right !important;
72
  }
@@ -97,7 +113,7 @@ tr.checkout-placeholder td {
97
  }
98
 
99
  #options_presentation{
100
- min-width:850px;
101
  }
102
 
103
  table.wpsc-edit-module-options tr td {
@@ -108,27 +124,35 @@ table.wpsc-edit-module-options tr td {
108
  padding: 0 0 8px 8px;
109
  width:394px;
110
  }
111
- .gateway_settings_form {
 
112
  padding: .5em;
113
  }
114
- .widefat .gateway_settings_form td {
 
115
  border: none;
116
  overflow: initial;
117
  }
 
 
 
 
118
  .widefat p.description {
119
  color: #666;
120
  }
121
  .widefat .inactive p.description {
122
  margin-left: 0;
123
  }
124
- .gateway_settings_form p.submit {
 
125
  margin-top: 2em;
126
  }
127
 
128
  .gateway_settings input[type=text]{
129
  width: 200px;
130
  }
131
- .edit-payment-module-update {
 
132
  float: right;
133
  }
134
 
@@ -162,6 +186,9 @@ table#form_field_table tr td.namecol{ }
162
  table#form_field_table tr *.namecol{ width: 170px; padding-right: 8px; }
163
  table#form_field_table tr *.namecol input{ width: 160px; }
164
 
 
 
 
165
  table#form_field_table tr *.typecol{ width: 120px; }
166
  table#form_field_table tr *.typecol select{ width: 115px; }
167
 
@@ -209,21 +236,20 @@ table#form_field_table tr th{ padding-left: 0px; padding-right: 0px; }
209
  }
210
 
211
  h3.form_group {
212
- clear: both;
213
  }
214
  h3.form_group a{
215
  color: #000;
216
  }
217
  div.product_and_button_settings {
218
- width: 450px;
219
- float: left;
220
-
221
  }
222
 
223
  div#themes_and_appearance {
224
  border: 1px solid #DFDFDF;
225
  width: 360px;
226
- float: left;
 
227
  }
228
 
229
  div#themes_and_appearance p {
@@ -364,7 +390,7 @@ a.nav-tab-loading {
364
  }
365
 
366
  .js #wpsc_checkout_list .edit-options {
367
- display:none;
368
  }
369
 
370
  .js .form-field-options {
@@ -380,7 +406,7 @@ a.nav-tab-loading {
380
  }
381
 
382
  #wpsc_checkout_list .wpsc-field-options-table td .field-option-cell-wrapper {
383
- padding:7px 0;
384
  }
385
 
386
  #wpsc_checkout_list .wpsc-field-options-table .column-actions {
@@ -421,4 +447,16 @@ table.form-table td .updated.shipwire-update {
421
  display : none;
422
  font-size : 12px;
423
  line-height : 1.6em;
 
 
 
 
 
 
 
 
 
 
 
 
424
  }
12
  th#drag{
13
  width:50px;
14
  }
 
 
 
15
  tr.wpsc_grey{
16
  background-color: #ededed;
17
  }
19
  cursor: move;
20
  }
21
 
22
+ th.column-type {
23
+ width: 9em;
24
+ }
25
+ #wpsc_checkout_list th.column-type {
26
+ width: 9em;
27
  }
28
 
29
  th.column-unique_name {
30
+ width: 9em;
31
+ }
32
+
33
+ th.column-mandatory, th.column-display {
34
+ width: 6em;
35
+ }
36
+
37
+ .widefat th.column-mandatory, td.mandatorycol, .widefat th.column-display, td.displaycol, .widefat th.column-trash, td.trashcol {
38
+ text-align:center;
39
+ vertical-align: top
40
+ }
41
+
42
+ #wpsc_checkout_list td.typecol select {
43
+ width: 100%;
44
+ }
45
+
46
+ #wpsc_imported_columns ol {
47
+ margin-top: 0;
48
+ }
49
+ #wpsc_imported_columns .empty {
50
+ color: #999;
51
  }
52
 
53
  #checkout_message{
75
  margin-left:4px;
76
  }
77
 
 
 
 
 
 
 
 
 
78
  #wpsc_checkout_list .ui-sortable-helper {
79
  margin-left:0;
80
  }
81
 
82
+ #wpsc_checkout_list .namecol input {
83
+ width: 98%;
84
+ }
85
+
86
  #wpsc_checkout_list .actionscol .cell-wrapper {
87
  float:right !important;
88
  }
113
  }
114
 
115
  #options_presentation{
116
+ margin-right: 370px;
117
  }
118
 
119
  table.wpsc-edit-module-options tr td {
124
  padding: 0 0 8px 8px;
125
  width:394px;
126
  }
127
+ .gateway_settings_form,
128
+ .shipping-module-settings-form {
129
  padding: .5em;
130
  }
131
+ .widefat .gateway_settings_form td,
132
+ .widefat .shipping-module-settings-form td {
133
  border: none;
134
  overflow: initial;
135
  }
136
+ .widefat .shipping-module-settings-form th {
137
+ font-family: inherit;
138
+ font-size: 12px;
139
+ }
140
  .widefat p.description {
141
  color: #666;
142
  }
143
  .widefat .inactive p.description {
144
  margin-left: 0;
145
  }
146
+ .gateway_settings_form p.submit,
147
+ .shipping-module-settings-form p.submit {
148
  margin-top: 2em;
149
  }
150
 
151
  .gateway_settings input[type=text]{
152
  width: 200px;
153
  }
154
+ .edit-payment-module-update,
155
+ .edit-shipping-module-update {
156
  float: right;
157
  }
158
 
186
  table#form_field_table tr *.namecol{ width: 170px; padding-right: 8px; }
187
  table#form_field_table tr *.namecol input{ width: 160px; }
188
 
189
+ tr td.namecol{ padding-left: 2em; }
190
+ tr.field_type_heading td.namecol { padding-left: 0; }
191
+
192
  table#form_field_table tr *.typecol{ width: 120px; }
193
  table#form_field_table tr *.typecol select{ width: 115px; }
194
 
236
  }
237
 
238
  h3.form_group {
239
+ clear: left;
240
  }
241
  h3.form_group a{
242
  color: #000;
243
  }
244
  div.product_and_button_settings {
245
+ position: relative;
 
 
246
  }
247
 
248
  div#themes_and_appearance {
249
  border: 1px solid #DFDFDF;
250
  width: 360px;
251
+ position: absolute;
252
+ left: 45em;
253
  }
254
 
255
  div#themes_and_appearance p {
390
  }
391
 
392
  .js #wpsc_checkout_list .edit-options {
393
+ display: none;
394
  }
395
 
396
  .js .form-field-options {
406
  }
407
 
408
  #wpsc_checkout_list .wpsc-field-options-table td .field-option-cell-wrapper {
409
+ padding: 2px 0;
410
  }
411
 
412
  #wpsc_checkout_list .wpsc-field-options-table .column-actions {
447
  display : none;
448
  font-size : 12px;
449
  line-height : 1.6em;
450
+ }
451
+
452
+ /* tax */
453
+
454
+
455
+ .wpsc-tax-bands-row, .wpsc-tax-rates-row {
456
+ line-height: 3.2;
457
+ }
458
+
459
+ .wpsc-tax-bands-row.prototype,
460
+ .wpsc-tax-rates-row.prototype {
461
+ display: none;
462
  }
wpsc-admin/display-coupon-add.php CHANGED
@@ -30,7 +30,7 @@
30
  <label for="add_discount_type"><?php _e( 'Discount Type', 'wpsc' ); ?></label>
31
  </th>
32
  <td>
33
- <select name='add_discount_type' id='add_discount_type' onchange = 'show_shipping_options();'>
34
  <option value='0'><?php _e( 'Fixed Amount', 'wpsc' ); ?></option>
35
  <option value='1'><?php _e( 'Percentage', 'wpsc' ); ?></option>
36
  <option value='2'><?php _e( 'Free shipping', 'wpsc' ); ?></option>
30
  <label for="add_discount_type"><?php _e( 'Discount Type', 'wpsc' ); ?></label>
31
  </th>
32
  <td>
33
+ <select name='add_discount_type' id='add_discount_type'>
34
  <option value='0'><?php _e( 'Fixed Amount', 'wpsc' ); ?></option>
35
  <option value='1'><?php _e( 'Percentage', 'wpsc' ); ?></option>
36
  <option value='2'><?php _e( 'Free shipping', 'wpsc' ); ?></option>
wpsc-admin/display-coupon-edit.php CHANGED
@@ -48,7 +48,7 @@ $coupon = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM `" . WPSC_TABLE_COUP
48
  </th>
49
  <td>
50
  <?php $type = absint( $coupon['is-percentage'] ); ?>
51
- <select name='edit_discount_type' id='edit_discount_type' onchange='show_shipping_options();'>
52
  <option value='0'<?php selected( 0, $type ); ?>><?php _e( 'Fixed Amount', 'wpsc' ); ?></option>
53
  <option value='1'<?php selected( 1, $type ); ?>><?php _e( 'Percentage', 'wpsc' ); ?></option>
54
  <option value='2'<?php selected( 2, $type ); ?>><?php _e( 'Free shipping', 'wpsc' ); ?></option>
48
  </th>
49
  <td>
50
  <?php $type = absint( $coupon['is-percentage'] ); ?>
51
+ <select name='edit_discount_type' id='edit_discount_type'>
52
  <option value='0'<?php selected( 0, $type ); ?>><?php _e( 'Fixed Amount', 'wpsc' ); ?></option>
53
  <option value='1'<?php selected( 1, $type ); ?>><?php _e( 'Percentage', 'wpsc' ); ?></option>
54
  <option value='2'<?php selected( 2, $type ); ?>><?php _e( 'Free shipping', 'wpsc' ); ?></option>
wpsc-admin/display-items.page.php CHANGED
@@ -26,13 +26,13 @@ function wpsc_additional_column_names( $columns ){
26
  $columns['cb'] = '<input type="checkbox" />';
27
  $columns['image'] = '';
28
  $columns['title'] = __('Name', 'wpsc');
29
- $columns['weight'] = __('Weight', 'wpsc');
30
  $columns['stock'] = __('Stock', 'wpsc');
31
  $columns['price'] = __('Price', 'wpsc');
32
- $columns['sale_price'] = __('Sale Price', 'wpsc');
33
  $columns['SKU'] = __('SKU', 'wpsc');
 
34
  $columns['cats'] = __('Categories', 'wpsc');
35
- $columns['featured'] = __('Featured', 'wpsc');
36
  $columns['hidden_alerts'] = '';
37
  $columns['date'] = __('Date', 'wpsc');
38
 
@@ -285,15 +285,16 @@ add_action( 'wpsc_manage_products_column_cats', '_wpsc_manage_products_column_ca
285
  */
286
  function _wpsc_manage_products_column_featured( $post, $post_id ) {
287
  $featured_product_url = wp_nonce_url( "index.php?wpsc_admin_action=update_featured_product&amp;product_id=$post->ID", 'feature_product_' . $post->ID);
 
 
 
 
 
 
 
288
  ?>
289
- <a class="wpsc_featured_product_toggle featured_toggle_<?php echo $post->ID; ?>" href='<?php echo $featured_product_url; ?>' >
290
- <?php if ( in_array( $post->ID, (array)get_option( 'sticky_products' ) ) ) : ?>
291
- <img class='gold-star' src='<?php echo WPSC_CORE_IMAGES_URL; ?>/gold-star.gif' alt='<?php _e( 'Unmark as Featured', 'wpsc' ); ?>' title='<?php _e( 'Unmark as Featured', 'wpsc' ); ?>' />
292
- <?php else: ?>
293
- <img class='grey-star' src='<?php echo WPSC_CORE_IMAGES_URL; ?>/grey-star.gif' alt='<?php _e( 'Mark as Featured', 'wpsc' ); ?>' title='<?php _e( 'Mark as Featured', 'wpsc' ); ?>' />
294
- <?php endif; ?>
295
- </a>
296
- <?php
297
  }
298
  add_action( 'wpsc_manage_products_column_featured', '_wpsc_manage_products_column_featured', 10, 2 );
299
 
@@ -474,12 +475,45 @@ function wpsc_sortable_column_load() {
474
  add_filter( 'request', 'wpsc_column_sql_orderby', 8 );
475
  }
476
 
477
- add_action( 'load-edit.php', 'wpsc_sortable_column_load' );
478
- add_action( 'restrict_manage_posts', 'wpsc_cats_restrict_manage_posts' );
479
- add_action( 'manage_wpsc-product_posts_custom_column', 'wpsc_additional_column_data', 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  add_filter( 'manage_edit-wpsc-product_sortable_columns', 'wpsc_additional_sortable_column_names' );
481
- add_filter( 'manage_edit-wpsc-product_columns', 'wpsc_additional_column_names' );
482
- add_filter( 'manage_wpsc-product_posts_columns', 'wpsc_additional_column_names' );
483
 
484
 
485
 
@@ -487,14 +521,13 @@ add_filter( 'manage_wpsc-product_posts_columns', 'wpsc_additional_column_names'
487
  * wpsc_update_featured_products function.
488
  *
489
  * @access public
490
- * @todo Should be refactored to e
491
  * @return void
492
  *
493
- * @uses check_admin_referrer() Makes sure that a user was referred from another admin page.
494
- * @uses get_option() Gets option from the WordPress database
495
- * @uses update_option() Updates an option in the WordPress database
496
- * @uses wp_redirect() Redirects to another page.
497
- * @uses wp_get_referrer() Retrieve referer from '_wp_http_referer' or HTTP referer.
498
  */
499
  function wpsc_update_featured_products() {
500
  if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) &&
@@ -527,8 +560,8 @@ function wpsc_update_featured_products() {
527
  $json_response = array(
528
  'text' => $new_status ? esc_attr__( 'Unmark as Featured', 'wpsc' ) : esc_attr__( 'Mark as Featured', 'wpsc' ),
529
  'product_id' => $product_id,
530
- 'class' => $new_status ? 'gold-star' : 'grey-star',
531
- 'image' => $new_status ? WPSC_CORE_IMAGES_URL . '/gold-star.gif' : WPSC_CORE_IMAGES_URL . '/grey-star.gif'
532
  );
533
 
534
  echo json_encode( $json_response );
@@ -537,7 +570,6 @@ function wpsc_update_featured_products() {
537
  }
538
  wp_redirect( wp_get_referer() );
539
  exit;
540
-
541
  }
542
 
543
  add_filter( 'page_row_actions','my_action_row', 10, 2 );
26
  $columns['cb'] = '<input type="checkbox" />';
27
  $columns['image'] = '';
28
  $columns['title'] = __('Name', 'wpsc');
 
29
  $columns['stock'] = __('Stock', 'wpsc');
30
  $columns['price'] = __('Price', 'wpsc');
31
+ $columns['sale_price'] = __('Sale', 'wpsc');
32
  $columns['SKU'] = __('SKU', 'wpsc');
33
+ $columns['weight'] = __('Weight', 'wpsc');
34
  $columns['cats'] = __('Categories', 'wpsc');
35
+ $columns['featured'] = '<img src="' . WPSC_CORE_IMAGES_URL . '/black-star.png" alt="' . __( 'Featured', 'wpsc' ) . '" title="' . __( 'Featured', 'wpsc' ) . '">';
36
  $columns['hidden_alerts'] = '';
37
  $columns['date'] = __('Date', 'wpsc');
38
 
285
  */
286
  function _wpsc_manage_products_column_featured( $post, $post_id ) {
287
  $featured_product_url = wp_nonce_url( "index.php?wpsc_admin_action=update_featured_product&amp;product_id=$post->ID", 'feature_product_' . $post->ID);
288
+ if ( in_array( $post->ID, (array) get_option( 'sticky_products' ) ) ) {
289
+ $class = 'gold-star';
290
+ $title = __( 'Unmark as Featured', 'wpsc' );
291
+ } else {
292
+ $class = 'grey-star';
293
+ $title = __( 'Mark as Featured', 'wpsc' );
294
+ }
295
  ?>
296
+ <a class="wpsc_featured_product_toggle featured_toggle_<?php echo $post->ID; ?> <?php echo esc_attr( $class ); ?>" href='<?php echo $featured_product_url; ?>' title="<?php echo esc_attr( $title ); ?>" ></a>
297
+ <?php
 
 
 
 
 
 
298
  }
299
  add_action( 'wpsc_manage_products_column_featured', '_wpsc_manage_products_column_featured', 10, 2 );
300
 
475
  add_filter( 'request', 'wpsc_column_sql_orderby', 8 );
476
  }
477
 
478
+ /**
479
+ * Product List Exclude Child Categories
480
+ *
481
+ * When filtering the product list by category in the admin this ensures that
482
+ * only products in the selected category are shown, not any of it's sub-categories.
483
+ *
484
+ * @param object $query WP_Query
485
+ *
486
+ * @uses get_current_screen()
487
+ */
488
+ function wpsc_product_list_exclude_child_categories( $query ) {
489
+
490
+ if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) )
491
+ return;
492
+
493
+ if ( 'edit-wpsc-product' == get_current_screen()->id ) {
494
+ $wpsc_product_category = $query->get( 'wpsc_product_category' );
495
+ if ( ! empty( $wpsc_product_category ) ) {
496
+ $category_query = array(
497
+ 'taxonomy' => 'wpsc_product_category',
498
+ 'field' => 'slug',
499
+ 'terms' => array( $wpsc_product_category ),
500
+ 'include_children' => false,
501
+ 'operator' => 'IN'
502
+ );
503
+ $query->set( 'tax_query', array( $category_query ) );
504
+ $query->tax_query->queries = $query->get( 'tax_query' );
505
+ }
506
+ }
507
+ }
508
+
509
+ add_action( 'pre_get_posts', 'wpsc_product_list_exclude_child_categories', 15 );
510
+
511
+ add_action( 'load-edit.php' , 'wpsc_sortable_column_load' );
512
+ add_action( 'restrict_manage_posts' , 'wpsc_cats_restrict_manage_posts' );
513
+ add_action( 'manage_wpsc-product_posts_custom_column' , 'wpsc_additional_column_data', 10, 2 );
514
  add_filter( 'manage_edit-wpsc-product_sortable_columns', 'wpsc_additional_sortable_column_names' );
515
+ add_filter( 'manage_edit-wpsc-product_columns' , 'wpsc_additional_column_names' );
516
+ add_filter( 'manage_wpsc-product_posts_columns' , 'wpsc_additional_column_names' );
517
 
518
 
519
 
521
  * wpsc_update_featured_products function.
522
  *
523
  * @access public
 
524
  * @return void
525
  *
526
+ * @uses check_admin_referer() Makes sure that a user was referred from another admin page.
527
+ * @uses get_option() Gets option from the WordPress database
528
+ * @uses update_option() Updates an option in the WordPress database
529
+ * @uses wp_redirect() Redirects to another page.
530
+ * @uses wp_get_referer() Retrieve referer from '_wp_http_referer' or HTTP referer.
531
  */
532
  function wpsc_update_featured_products() {
533
  if ( ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) &&
560
  $json_response = array(
561
  'text' => $new_status ? esc_attr__( 'Unmark as Featured', 'wpsc' ) : esc_attr__( 'Mark as Featured', 'wpsc' ),
562
  'product_id' => $product_id,
563
+ 'color' => $new_status ? 'gold-star' : 'grey-star',
564
+ 'image' => $new_status ? WPSC_CORE_IMAGES_URL . '/gold-star.png' : WPSC_CORE_IMAGES_URL . '/grey-star.png'
565
  );
566
 
567
  echo json_encode( $json_response );
570
  }
571
  wp_redirect( wp_get_referer() );
572
  exit;
 
573
  }
574
 
575
  add_filter( 'page_row_actions','my_action_row', 10, 2 );
wpsc-admin/display-sales-logs.php CHANGED
@@ -47,7 +47,7 @@ class WPSC_Purchase_Log_Page {
47
  private function purchase_logs_fix_options( $id ) {
48
  ?>
49
  <select name='<?php echo $id; ?>'>
50
- <option value='-1'><?php echo esc_html_x( 'Select an Option', 'Dropdown default when called in uniquename dropdown', 'wpsc' ); ?>'</option>
51
  <option value='billingfirstname'><?php esc_html_e( 'Billing First Name', 'wpsc' ); ?></option>
52
  <option value='billinglastname'><?php esc_html_e( 'Billing Last Name', 'wpsc' ); ?></option>
53
  <option value='billingaddress'><?php esc_html_e( 'Billing Address', 'wpsc' ); ?></option>
47
  private function purchase_logs_fix_options( $id ) {
48
  ?>
49
  <select name='<?php echo $id; ?>'>
50
+ <option value='-1'><?php echo esc_html_x( 'Select an Option', 'Dropdown default when called in uniquename dropdown', 'wpsc' ); ?></option>
51
  <option value='billingfirstname'><?php esc_html_e( 'Billing First Name', 'wpsc' ); ?></option>
52
  <option value='billinglastname'><?php esc_html_e( 'Billing Last Name', 'wpsc' ); ?></option>
53
  <option value='billingaddress'><?php esc_html_e( 'Billing Address', 'wpsc' ); ?></option>
wpsc-admin/display-upgrades.page.php CHANGED
@@ -57,13 +57,6 @@ function wpsc_display_upgrades_page() {
57
  <p class='wpsc_gold_text'><?php esc_html_e( 'This plugin offers shop owners the ability to provide Fedex Shipping Quotes for products with weights.', 'wpsc' ); ?></p>
58
  <span class='wpsc_gold_info'><?php esc_html_e( '$40', 'wpsc' ); ?></span>
59
  </div>
60
- <div class='wpsc_gold_module'>
61
- <br />
62
- <a href="http://www.bravenewcode.com/store/plugins/piggy/?utm_source=affiliate-6331&amp;utm_medium=affiliates&amp;utm_campaign=wpec" target="_blank"><strong><?php esc_html_e( 'Piggy', 'wpsc' ); ?> </strong></a>
63
- <p class='wpsc_gold_text'><?php esc_html_e( 'Your WP E-Commerce sales, in your pocket. Piggy is a web-app that provides mobile access to view sales data for your WP E-Commerce powered WordPress website. Works on iOS and Android.', 'wpsc' ); ?></p>
64
- <span class='wpsc_gold_info'><?php esc_html_e( '$39', 'wpsc' ); ?></span>
65
- </div>
66
-
67
  </div>
68
 
69
  <h2><?php esc_html_e( 'Upgrades', 'wpsc' ); ?></h2>
57
  <p class='wpsc_gold_text'><?php esc_html_e( 'This plugin offers shop owners the ability to provide Fedex Shipping Quotes for products with weights.', 'wpsc' ); ?></p>
58
  <span class='wpsc_gold_info'><?php esc_html_e( '$40', 'wpsc' ); ?></span>
59
  </div>
 
 
 
 
 
 
 
60
  </div>
61
 
62
  <h2><?php esc_html_e( 'Upgrades', 'wpsc' ); ?></h2>
wpsc-admin/includes/coupon-list-table-class.php CHANGED
@@ -403,16 +403,10 @@ class WPSC_Coupons_List_Table extends WP_List_Table {
403
  $offset = ( $page - 1 ) * $this->per_page;
404
 
405
  $status = isset( $_GET['status'] ) ? absint( $_GET['status'] ) : false;
 
406
 
407
- if( $status !== false )
408
- $where = "WHERE active = $status";
409
- else
410
- $where = '';
411
-
412
- $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
413
-
414
  $limit = " LIMIT $offset,$per_page;";
415
-
416
  $coupons = $wpdb->get_results( "SELECT * FROM `" . WPSC_TABLE_COUPON_CODES . "` {$where} ORDER BY id {$order} {$limit} ", ARRAY_A );
417
 
418
  if ( $coupons ) {
403
  $offset = ( $page - 1 ) * $this->per_page;
404
 
405
  $status = isset( $_GET['status'] ) ? absint( $_GET['status'] ) : false;
406
+ $where = $status !== false ? "WHERE active = $status" : '';
407
 
408
+ $order = strtoupper( $_GET['order'] ) === 'ASC' ? 'ASC' : 'DESC';
 
 
 
 
 
 
409
  $limit = " LIMIT $offset,$per_page;";
 
410
  $coupons = $wpdb->get_results( "SELECT * FROM `" . WPSC_TABLE_COUPON_CODES . "` {$where} ORDER BY id {$order} {$limit} ", ARRAY_A );
411
 
412
  if ( $coupons ) {
wpsc-admin/includes/purchase-log-list-table-class.php CHANGED
@@ -64,8 +64,10 @@ class WPSC_Purchase_Log_List_Table extends WP_List_Table {
64
  $joins = array();
65
  $where = array( '1 = 1' );
66
 
67
- if ( isset( $_REQUEST['post'] ) )
68
- $where[] = 'p.id IN (' . implode( ', ', $_REQUEST['post'] ) . ')';
 
 
69
 
70
  $i = 1;
71
  $selects = array( 'p.id', 'p.totalprice AS amount', 'p.processed AS status', 'p.track_id', 'p.date' );
@@ -125,19 +127,19 @@ class WPSC_Purchase_Log_List_Table extends WP_List_Table {
125
  }
126
 
127
  $selects = apply_filters( 'wpsc_manage_purchase_logs_selects', implode( ', ', $selects ) );
128
- $this->joins = apply_filters( 'wpsc_manage_purchase_logs_joins', implode( ' ', $joins ) );
129
- $this->where = apply_filters( 'wpsc_manage_purchase_logs_where', implode( ' AND ', $where ) );
130
-
131
  $limit = ( $this->per_page !== 0 ) ? "LIMIT {$offset}, {$this->per_page}" : '';
132
 
133
  $orderby = empty( $_REQUEST['orderby'] ) ? 'p.id' : 'p.' . $_REQUEST['orderby'];
134
- $order = empty( $_REQUEST['order'] ) ? 'DESC' : $_REQUEST['order'];
135
 
136
  $orderby = esc_sql( apply_filters( 'wpsc_manage_purchase_logs_orderby', $orderby ) );
137
- $order = esc_sql( $order );
138
 
139
  $submitted_data_log = WPSC_TABLE_SUBMITTED_FORM_DATA;
140
- $purchase_log_sql = apply_filters( 'wpsc_manage_purchase_logs_sql', "
141
  SELECT SQL_CALC_FOUND_ROWS {$selects}
142
  FROM " . WPSC_TABLE_PURCHASE_LOGS . " AS p
143
  {$this->joins}
64
  $joins = array();
65
  $where = array( '1 = 1' );
66
 
67
+ if ( isset( $_REQUEST['post'] ) ) {
68
+ $posts = array_map( 'absint', $_REQUEST['post'] );
69
+ $where[] = 'p.id IN (' . implode( ', ', $posts ) . ')';
70
+ }
71
 
72
  $i = 1;
73
  $selects = array( 'p.id', 'p.totalprice AS amount', 'p.processed AS status', 'p.track_id', 'p.date' );
127
  }
128
 
129
  $selects = apply_filters( 'wpsc_manage_purchase_logs_selects', implode( ', ', $selects ) );
130
+ $this->joins = apply_filters( 'wpsc_manage_purchase_logs_joins' , implode( ' ', $joins ) );
131
+ $this->where = apply_filters( 'wpsc_manage_purchase_logs_where' , implode( ' AND ', $where ) );
132
+
133
  $limit = ( $this->per_page !== 0 ) ? "LIMIT {$offset}, {$this->per_page}" : '';
134
 
135
  $orderby = empty( $_REQUEST['orderby'] ) ? 'p.id' : 'p.' . $_REQUEST['orderby'];
136
+ $order = empty( $_REQUEST['order'] ) ? 'DESC' : $_REQUEST['order'];
137
 
138
  $orderby = esc_sql( apply_filters( 'wpsc_manage_purchase_logs_orderby', $orderby ) );
139
+ $order = esc_sql( $order );
140
 
141
  $submitted_data_log = WPSC_TABLE_SUBMITTED_FORM_DATA;
142
+ $purchase_log_sql = apply_filters( 'wpsc_manage_purchase_logs_sql', "
143
  SELECT SQL_CALC_FOUND_ROWS {$selects}
144
  FROM " . WPSC_TABLE_PURCHASE_LOGS . " AS p
145
  {$this->joins}
wpsc-admin/includes/purchase-logs-page/item-details.php CHANGED
@@ -151,7 +151,7 @@
151
  <h3><?php esc_html_e( 'Actions', 'wpsc' ); ?></h3>
152
  <?php do_action( 'wpsc_purchlogitem_links_start' ); ?>
153
  <?php if ( wpsc_purchlogs_have_downloads_locked() != false ): ?>
154
- <img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/lock_open.png' alt='<?php _e( 'clear lock icon', 'wpsc' ); ?>' />&ensp;<a href='<?php echo $_SERVER['REQUEST_URI'].'&amp;wpsc_admin_action=clear_locks'; ?>'><?php echo wpsc_purchlogs_have_downloads_locked(); ?></a><br /><br class='small' />
155
  <?php endif; ?>
156
  <img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/printer.png' alt='<?php _e( 'printer icon', 'wpsc' ); ?>' />&ensp;<a target="_blank" href='<?php echo add_query_arg( 'c', 'packing_slip' ); ?>'><?php esc_html_e( 'View Packing Slip', 'wpsc' ); ?></a>
157
  <br /><br class='small' />
151
  <h3><?php esc_html_e( 'Actions', 'wpsc' ); ?></h3>
152
  <?php do_action( 'wpsc_purchlogitem_links_start' ); ?>
153
  <?php if ( wpsc_purchlogs_have_downloads_locked() != false ): ?>
154
+ <img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/lock_open.png' alt='<?php _e( 'clear lock icon', 'wpsc' ); ?>' />&ensp;<a href='<?php echo esc_url( add_query_arg( 'wpsc_admin_action', 'clear_locks' ) ); ?>'><?php echo wpsc_purchlogs_have_downloads_locked(); ?></a><br /><br class='small' />
155
  <?php endif; ?>
156
  <img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/printer.png' alt='<?php _e( 'printer icon', 'wpsc' ); ?>' />&ensp;<a target="_blank" href='<?php echo add_query_arg( 'c', 'packing_slip' ); ?>'><?php esc_html_e( 'View Packing Slip', 'wpsc' ); ?></a>
157
  <br /><br class='small' />
wpsc-admin/includes/purchase-logs-page/list-table.php CHANGED
@@ -74,18 +74,10 @@
74
  <?php do_action( 'wpsc_purchase_logs_list_table_after' ); ?>
75
  </form>
76
 
77
- <?php
78
- $piggy_url = 'http://www.bravenewcode.com/store/plugins/piggy/?utm_source=affiliate-6331&utm_medium=affiliates&utm_campaign=wpec#1';
79
- ?>
80
-
81
  <p>
82
  <a class='admin_download' href='<?php echo esc_url( add_query_arg( 'action', 'download_csv' ) ); ?>' >
83
  <img class='wpsc_pushdown_img' src='<?php echo WPSC_CORE_IMAGES_URL; ?>/download.gif' alt='' title='' />
84
  <span><?php _e( 'Download CSV', 'wpsc' ); ?></span>
85
  </a>
86
- <a target="_blank" class='admin_download' href='<?php echo esc_url( $piggy_url) ; ?>'>
87
- <img class='wpsc_pushdown_img' src='<?php echo esc_url( WPSC_CORE_IMAGES_URL ); ?>/mobile.png' alt='' title='' />
88
- <span><?php _e( 'Mobile Sales App', 'wpsc' ); ?></span>
89
- </a>
90
  </p>
91
  </div>
74
  <?php do_action( 'wpsc_purchase_logs_list_table_after' ); ?>
75
  </form>
76
 
 
 
 
 
77
  <p>
78
  <a class='admin_download' href='<?php echo esc_url( add_query_arg( 'action', 'download_csv' ) ); ?>' >
79
  <img class='wpsc_pushdown_img' src='<?php echo WPSC_CORE_IMAGES_URL; ?>/download.gif' alt='' title='' />
80
  <span><?php _e( 'Download CSV', 'wpsc' ); ?></span>
81
  </a>
 
 
 
 
82
  </p>
83
  </div>
wpsc-admin/includes/save-data.functions.php CHANGED
@@ -18,7 +18,7 @@ function wpsc_ajax_set_variation_order(){
18
 
19
  $value = preg_replace( '/[^0-9]/', '', $value );
20
 
21
- if( !wpsc_update_meta( $value, 'sort_order', $key, 'wpsc_variation' ) )
22
  $result = false;
23
  }
24
  }
@@ -38,13 +38,13 @@ function wpsc_ajax_set_category_order(){
38
  $parent_id = $_POST['parent_id'];
39
 
40
  $result = true;
41
- foreach( $sort_order as $key=>$value ){
42
  if ( empty( $value ) )
43
  continue;
44
 
45
  $value = preg_replace( '/[^0-9]/', '', $value );
46
 
47
- if( !wpsc_update_meta( $value, 'sort_order', $key, 'wpsc_category' ) )
48
  $result = false;
49
  }
50
  }
@@ -65,17 +65,17 @@ add_action( 'edited_wpsc_product_category', 'wpsc_save_category_set', 10 , 2 );
65
  */
66
 
67
  function wpsc_custom_category_columns( $columns ) {
68
- // Doing it this funny way to ensure that image stays in far left, even if other items are added via plugin.
69
- unset( $columns["cb"] );
70
 
71
- $custom_array = array(
72
- 'cb' => '<input type="checkbox" />',
73
- 'image' => __( 'Image', 'wpsc' )
74
- );
75
 
76
- $columns = array_merge( $custom_array, $columns );
77
 
78
- return $columns;
79
  }
80
  /**
81
  * wpsc_custom_category_column_data
@@ -91,12 +91,12 @@ function wpsc_custom_category_column_data( $string, $column_name, $term_id ) {
91
  $name = get_term_by( 'id', $term_id, 'wpsc_product_category' );
92
  $name = $name->name;
93
 
94
- if( !empty( $image ) )
95
- $image = "<img src=\"".WPSC_CATEGORY_URL . $image . "\" title='" . esc_attr( $name ) . "' alt='" . esc_attr( $name ) . "' width='30' height='30' />";
96
  else
97
- $image = "<img src='" . WPSC_CORE_IMAGES_URL . "/no-image-uploaded.gif' title='" . esc_attr( $name ) . "' alt='" . esc_attr( $name ) . "' width='30' height='30' />";
98
 
99
- return $image;
100
 
101
  }
102
 
@@ -106,28 +106,36 @@ function wpsc_custom_category_column_data( $string, $column_name, $term_id ) {
106
  * for use in other list functions
107
  * @param int $parent_id
108
  */
109
- function wpsc_admin_get_category_array($parent_id = null){
110
- global $wpdb;
111
- $orderedList = array();
112
- if(!isset($parent_id)) $parent_id = 0;
113
- $category_list = get_terms('wpsc_product_category','hide_empty=0&parent='.$parent_id);
114
- if(!is_array($category_list)){
115
- return false;
116
- }
117
- foreach($category_list as $category){
118
- $category_order = wpsc_get_categorymeta($category->term_id, 'order');
119
- $category_image = wpsc_get_categorymeta($category->term_id, 'image');
120
- if(!isset($category_order) || $category_order == 0) $category_order = (count($orderedList) +1);
121
- print "<!-- setting category Order number to ".$category_order."-->";
122
- $orderedList[$category_order]['id'] = $category->term_id;
123
- $orderedList[$category_order]['name'] = $category->name;
124
- $orderedList[$category_order]['image'] = $category_image;
125
- $orderedList[$category_order]['parent_id'] = $parent_id;
126
- $orderedList[$category_order]['children'] = wpsc_admin_get_category_array($category->term_id);
127
- }
128
-
129
- ksort($orderedList);
130
- return($orderedList);
 
 
 
 
 
 
 
 
131
  }
132
 
133
  /**
@@ -140,145 +148,107 @@ function wpsc_admin_category_forms_add() {
140
  $display_type = isset( $category['display_type'] ) ? $category['display_type'] : '';
141
  ?>
142
 
143
- <h3><?php esc_html_e('Advanced Settings', 'wpsc'); ?></h3>
144
-
145
- <div id="poststuff" class="postbox">
146
- <h3 class="hndle"><?php esc_html_e('Presentation Settings', 'wpsc'); ?></h3>
147
-
148
- <div class="inside">
149
- <tr>
150
- <td>
151
- <label for='image'><?php esc_html_e( 'Category Image' , 'wpsc' ); ?></label>
152
- </td>
153
- <td>
154
- <input type='file' name='image' value='' /><br /><br />
155
- </td>
156
- </tr>
157
- <tr>
158
- <td>
159
- <?php esc_html_e( 'Catalog View', 'wpsc' ); ?>
160
- </td>
161
- <td>
162
- <select name='display_type'>
163
- <option value='default'<?php selected( $display_type, 'default' ); ?>><?php esc_html_e('Default View', 'wpsc'); ?></option>
164
- <option value='list'<?php disabled( _wpsc_is_display_type_supported( 'list' ), false ); ?><?php selected( $display_type, 'list' ); ?>><?php esc_html_e('List View', 'wpsc'); ?></option>
165
- <option value='grid'<?php disabled( _wpsc_is_display_type_supported( 'grid' ), false ); ?><?php selected( $display_type, 'grid' ); ?>><?php esc_html_e('Grid View', 'wpsc'); ?></option>
166
- </select><br /><br />
167
- </td>
168
- </tr>
169
- <tr>
170
- <td>
171
- <span class='small'><?php esc_html_e('To over-ride the presentation settings for this group you can enter in your prefered settings here', 'wpsc'); ?></span><br /><br />
172
- </td>
173
- </tr>
174
-
175
- <?php if(function_exists("getimagesize")) { ?>
176
- <tr>
177
- <td>
178
- <?php esc_html_e('Thumbnail&nbsp;Size', 'wpsc'); ?>
179
- </td>
180
- <td>
181
- <?php esc_html_e('Width', 'wpsc'); ?> <input type='text' value='<?php if (isset($category['image_width'])) echo $category['image_width']; ?>' name='image_width' size='6'/>
182
- <?php esc_html_e('Height', 'wpsc'); ?> <input type='text' value='<?php if (isset($category['image_height'])) echo $category['image_height']; ?>' name='image_height' size='6'/><br/>
183
- </td>
184
- </tr>
185
- <?php
186
- }
187
- ?>
188
- </div>
189
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- <!-- START OF TARGET MARKET SELECTION -->
192
- <div id="poststuff" class="postbox">
193
- <h3 class="hndle"><?php esc_html_e( 'Target Market Restrictions', 'wpsc' ); ?></h3>
194
- <div class="inside"><?php
195
  $category_id = '';
196
- if (isset($_GET["tag_ID"])) $category_id = $_GET["tag_ID"];
197
- $countrylist = $wpdb->get_results("SELECT id,country,visible FROM `".WPSC_TABLE_CURRENCY_LIST."` ORDER BY country ASC ",ARRAY_A);
198
- $selectedCountries = wpsc_get_meta($category_id,'target_market','wpsc_category');
199
- $output = '';
200
- $output .= " <tr>\n\r";
201
- $output .= " <td>\n\r";
202
- $output .= esc_html__( 'Target Markets', 'wpsc' ).":\n\r";
203
- $output .= " </td>\n\r";
204
- $output .= " <td>\n\r";
205
-
206
- if(@extension_loaded('suhosin')) {
207
- $output .= "<em>".esc_html__( "The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature then disable the suhosin extension, if you can not do this, you will need to contact your hosting provider.
208
- ",'wpsc' )."</em>";
209
-
210
- } else {
211
- $output .= "<span>" . esc_html__( 'Select', 'wpsc' ) . " <a href='' class='wpsc_select_all'>" . esc_html__( 'All', 'wpsc' ) . "</a>&nbsp; <a href='' class='wpsc_select_none'>" . esc_html__( 'None', 'wpsc' ) . "</a></span><br />";
212
- $output .= " <div id='resizeable' class='ui-widget-content multiple-select'>\n\r";
213
- foreach($countrylist as $country){
214
- if(in_array($country['id'], (array)$selectedCountries)){
215
- $output .= " <input type='checkbox' name='countrylist2[]' value='".$country['id']."' checked='".$country['visible']."' />".$country['country']."<br />\n\r";
216
- } else {
217
- $output .= " <input type='checkbox' name='countrylist2[]' value='".$country['id']."' />".$country['country']."<br />\n\r";
218
- }
219
- }
220
- $output .= " </div><br /><br />";
221
- $output .= " <span class='wpscsmall description'>" . esc_html__( 'Select the markets you are selling this category to.', 'wpsc' ) . "<span>\n\r";
222
- }
223
- $output .= " </td>\n\r";
224
- $output .= " </tr>\n\r";
225
 
226
- echo $output;
227
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  </div>
229
- </div>
230
 
231
- <!-- Checkout settings -->
232
- <div id="poststuff" class="postbox">
233
- <h3 class="hndle"><?php esc_html_e( 'Checkout Settings', 'wpsc' ); ?></h3>
234
- <div class="inside">
235
- <table class='category_forms'>
 
 
 
 
 
 
236
  <?php
237
- if (!isset($category['term_id'])) $category['term_id'] = '';
238
- $used_additonal_form_set = wpsc_get_categorymeta($category['term_id'], 'use_additional_form_set'); ?>
239
- <tr>
240
- <td>
241
- <?php esc_html_e( 'This category requires additional checkout form fields', 'wpsc' ); ?>
242
- </td>
243
- <td>
244
- <select name='use_additional_form_set'>
245
- <option value=''><?php esc_html_e( 'None', 'wpsc' ); ?></option>
246
- <?php
247
- $checkout_sets = get_option( 'wpsc_checkout_form_sets' );
248
- unset($checkout_sets[0]);
249
-
250
- foreach((array)$checkout_sets as $key => $value) {
251
- $selected_state = "";
252
- if($used_additonal_form_set == $key)
253
- $selected_state = "selected='selected'";
254
- ?>
255
- <option <?php echo $selected_state; ?> value='<?php echo $key; ?>'><?php echo esc_html( $value ); ?></option>
256
- <?php
257
- }
258
- ?>
259
- </select>
260
- </td>
261
- </tr>
262
- <?php $uses_billing_address = (bool)wpsc_get_categorymeta($category['term_id'], 'uses_billing_address'); ?>
263
- <tr>
264
- <td>
265
- <?php esc_html_e( 'Products in this category use the billing address to calculate shipping', 'wpsc' ); ?>
266
- </td>
267
- <td>
268
- <input type='radio' value='1' name='uses_billing_address' <?php echo (($uses_billing_address == true) ? "checked='checked'" : ""); ?> /><?php esc_html_e( 'Yes', 'wpsc' ); ?>
269
- <input type='radio' value='0' name='uses_billing_address' <?php echo (($uses_billing_address != true) ? "checked='checked'" : ""); ?> /><?php esc_html_e( 'No', 'wpsc' ); ?>
270
- </td>
271
- </tr>
272
- </table>
273
  </div>
274
- </div>
275
 
276
- <table class="category_forms">
277
- <tr>
 
 
 
 
 
278
 
279
- </tr>
280
- </table>
281
- <?php
 
 
 
282
  }
283
 
284
  /**
@@ -301,178 +271,190 @@ function wpsc_admin_category_forms_edit() {
301
  $category_name = '';
302
  $category = array();
303
 
304
- $category_id = absint( $_REQUEST["tag_ID"] );
305
- $category = get_term($category_id, 'wpsc_product_category', ARRAY_A);
306
- $category['nice-name'] = wpsc_get_categorymeta($category['term_id'], 'nice-name');
307
- $category['description'] = wpsc_get_categorymeta($category['term_id'], 'description');
308
- $category['image'] = wpsc_get_categorymeta($category['term_id'], 'image');
309
- $category['fee'] = wpsc_get_categorymeta($category['term_id'], 'fee');
310
- $category['active'] = wpsc_get_categorymeta($category['term_id'], 'active');
311
- $category['order'] = wpsc_get_categorymeta($category['term_id'], 'order');
312
- $category['display_type'] = wpsc_get_categorymeta($category['term_id'], 'display_type');
313
- $category['image_height'] = wpsc_get_categorymeta($category['term_id'], 'image_height');
314
- $category['image_width'] = wpsc_get_categorymeta($category['term_id'], 'image_width');
315
- $category['use_additional_form_set'] = wpsc_get_categorymeta($category['term_id'], 'use_additional_form_set');
316
-
317
 
318
  ?>
319
 
320
- <tr>
321
- <td colspan="2">
322
- <h3><?php esc_html_e( 'Advanced Settings', 'wpsc' ); ?></h3>
 
 
 
 
323
 
324
- </td>
325
- </tr>
326
 
327
  <tr class="form-field">
328
- <th scope="row" valign="top">
329
- <label for="display_type"><?php esc_html_e( 'Catalog View', 'wpsc' ); ?></label>
330
- </th>
331
- <td>
332
- <?php
333
- $display_type = isset( $category['display_type'] ) ? $category['display_type'] : '';
334
- ?>
335
- <select name='display_type'>
336
- <option value='default'<?php selected( $display_type, 'default' ); ?>><?php esc_html_e( 'Default View', 'wpsc' ); ?></option>
337
- <option value='list'<?php disabled( _wpsc_is_display_type_supported( 'list' ), false ); ?><?php selected( $display_type, 'list' ); ?>><?php esc_html_e('List View', 'wpsc'); ?></option>
338
- <option value='grid' <?php disabled( _wpsc_is_display_type_supported( 'grid' ), false ); ?><?php selected( $display_type, 'grid' ); ?>><?php esc_html_e( 'Grid View', 'wpsc' ); ?></option>
339
- </select><br />
340
- <span class="description"><?php esc_html_e( 'To over-ride the presentation settings for this group you can enter in your prefered settings here', 'wpsc' ); ?></span>
341
- </td>
342
  </tr>
343
- <tr class="form-field">
344
- <th scope="row" valign="top">
345
- <label for="image"><?php esc_html_e( 'Category Image', 'wpsc' ); ?></label>
346
- </th>
347
- <td>
348
- <input type='file' name='image' value='' /><br />
349
- <label><input type='checkbox' name='deleteimage' class="wpsc_cat_box" value='1' /><?php esc_html_e( 'Delete Image', 'wpsc' ); ?></label><br/>
350
- <span class="description"><?php esc_html_e( 'You can set an image for the category here. If one exists, check the box to delete.', 'wpsc' ); ?></span>
351
- </td>
 
 
 
 
 
352
  </tr>
353
- <?php if( function_exists( "getimagesize" ) ) : ?>
354
- <tr class="form-field">
355
- <th scope="row" valign="top">
356
- <label for="image"><?php esc_html_e( 'Thumbnail Size', 'wpsc' ); ?></label>
357
- </th>
358
- <td>
359
- <?php esc_html_e( 'Width', 'wpsc' ); ?> <input type='text' class="wpsc_cat_image_size" value='<?php if (isset($category['image_width'])) echo $category['image_width']; ?>' name='image_width' size='6' />
360
- <?php esc_html_e( 'Height', 'wpsc' ); ?> <input type='text' class="wpsc_cat_image_size" value='<?php if (isset($category['image_height'])) echo $category['image_height']; ?>' name='image_height' size='6' /><br/>
361
- </td>
 
 
 
 
 
 
 
 
 
 
 
362
  </tr>
363
- <?php endif; // 'getimagesize' condition ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
  <tr>
365
- <td colspan="2"><h3><?php esc_html_e( 'Shortcodes and Template Tags', 'wpsc' ); ?></h3></td>
366
- </tr>
367
-
368
- <tr class="form-field">
369
- <th scope="row" valign="top">
370
- <label for="image"><?php esc_html_e( 'Display Category Shortcode', 'wpsc' ); ?>:</label>
371
- </th>
372
- <td>
373
- <span>[wpsc_products category_url_name='<?php echo $category["slug"]; ?>']</span><br />
374
- <span class="description"><?php esc_html_e( 'Shortcodes are used to display a particular category or group within any WordPress page or post.', 'wpsc' ); ?></span>
375
- </td>
376
  </tr>
377
- <tr class="form-field">
378
- <th scope="row" valign="top">
379
- <label for="image"><?php esc_html_e( 'Display Category Template Tag', 'wpsc' ); ?>:</label>
380
- </th>
381
- <td>
382
- <span>&lt;?php echo wpsc_display_products_page( array( 'category_url_name'=>'<?php echo $category["slug"]; ?>' ) ); ?&gt;</span><br />
383
- <span class="description"><?php esc_html_e( 'Template tags are used to display a particular category or group within your theme / template.', 'wpsc' ); ?></span>
384
- </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  </tr>
386
 
387
- <!-- START OF TARGET MARKET SELECTION -->
388
-
389
- <tr>
390
- <td colspan="2">
391
- <h3><?php esc_html_e( 'Target Market Restrictions', 'wpsc' ); ?></h3>
392
- </td>
393
- </tr>
394
- <?php
395
- $countrylist = $wpdb->get_results( "SELECT id,country,visible FROM `".WPSC_TABLE_CURRENCY_LIST."` ORDER BY country ASC ",ARRAY_A );
396
- $selectedCountries = wpsc_get_meta( $category_id,'target_market','wpsc_category' );
397
- ?>
398
- <tr class="form-field">
399
- <th scope="row" valign="top">
400
- <label for="image"><?php esc_html_e( 'Target Markets', 'wpsc' ); ?>:</label>
401
- </th>
402
- <td>
403
- <?php
404
- if ( wpsc_is_suhosin_enabled() ) :
405
- ?>
406
- <em><?php esc_html_e( 'The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature, then disable the suhosin extension. If you can not do this, you will need to contact your hosting provider.','wpsc' ); ?></em>
407
-
408
- <?php
409
- else :
410
- ?>
411
- <span><?php esc_html_e( 'Select', 'wpsc' ); ?>: <a href='' class='wpsc_select_all'><?php esc_html_e( 'All', 'wpsc' ); ?></a>&nbsp; <a href='' class='wpsc_select_none'><?php esc_html_e( 'None', 'wpsc' ); ?></a></span><br />
412
- <div id='resizeable' class='ui-widget-content multiple-select'>
413
- <?php
414
- foreach( $countrylist as $country ) {
415
- if( in_array( $country['id'], (array)$selectedCountries ) )
416
- echo " <input type='checkbox' class='wpsc_cat_box' name='countrylist2[]' value='".$country['id']."' checked='".$country['visible']."' />".$country['country']."<br />";
417
- else
418
- echo " <input type='checkbox' class='wpsc_cat_box' name='countrylist2[]' value='".$country['id']."' />".$country['country']."<br />";
419
- }
420
- ?>
421
- </div>
422
- <?php
423
- endif;
424
- ?><br />
425
- <span class="description"><?php esc_html_e( 'Select the markets you are selling this category to.', 'wpsc' ); ?></span>
426
- </td>
427
  </tr>
428
- <!-- Checkout settings -->
429
-
430
- <tr>
431
- <td colspan="2">
432
- <h3><?php esc_html_e( 'Checkout Settings', 'wpsc' ); ?></h3>
433
- </td>
434
- </tr>
435
- <?php
436
- if ( !isset( $category['term_id'] ) )
437
- $category['term_id'] = '';
438
- $used_additonal_form_set = wpsc_get_categorymeta( $category['term_id'], 'use_additional_form_set' );
439
- $checkout_sets = get_option('wpsc_checkout_form_sets');
440
- unset($checkout_sets[0]);
441
- $uses_billing_address = (bool)wpsc_get_categorymeta( $category['term_id'], 'uses_billing_address' );
442
- ?>
443
- <tr class="form-field">
444
- <th scope="row" valign="top">
445
- <label for="image"><?php esc_html_e( 'Category requires additional checkout form fields', 'wpsc' ); ?></label>
446
- </th>
447
- <td>
448
- <select name='use_additional_form_set'>
449
- <option value=''><?php esc_html_e( 'None', 'wpsc' ); ?></option>
450
- <?php
451
- foreach( (array) $checkout_sets as $key => $value ) {
452
- $selected_state = "";
453
- if( $used_additonal_form_set == $key )
454
- $selected_state = "selected='selected'";
455
- ?>
456
- <option <?php echo $selected_state; ?> value='<?php echo $key; ?>'><?php echo esc_html( $value ); ?></option>
457
- <?php
458
- }
459
- ?>
460
- </select><br />
461
- </td>
462
  </tr>
463
 
464
- <tr class="form-field">
465
- <th scope="row" valign="top">
466
- <label for="image"><?php esc_html_e( 'Products in this category use the billing address to calculate shipping', 'wpsc' ); ?></label>
467
- </th>
468
- <td>
469
- <input type='radio' class="wpsc_cat_box" value='1' name='uses_billing_address' <?php echo ( ( $uses_billing_address == true ) ? "checked='checked'" : "" ); ?> /><?php esc_html_e( 'Yes', 'wpsc' ); ?>
470
- <input type='radio' class="wpsc_cat_box" value='0' name='uses_billing_address' <?php echo (($uses_billing_address != true) ? "checked='checked'" : ""); ?> /><?php esc_html_e( 'No', 'wpsc' ); ?>
471
- <br />
472
- </td>
473
  </tr>
474
 
475
- <?php
476
  }
477
 
478
  /**
@@ -480,14 +462,14 @@ function wpsc_admin_category_forms_edit() {
480
  * @param nothing
481
  * @return nothing
482
  */
483
- function wpsc_save_category_set($category_id, $tt_id) {
484
  global $wpdb;
485
 
486
- if( !empty( $_POST ) ) {
487
  /* Image Processing Code*/
488
- if( !empty( $_FILES['image'] ) && preg_match( "/\.(gif|jp(e)*g|png){1}$/i", $_FILES['image']['name'] ) ) {
489
- if( function_exists( "getimagesize" ) ) {
490
- if( isset( $_POST['width'] ) && ( (int) $_POST['width'] > 10 && (int) $_POST['width'] < 512 ) && ((int)$_POST['height'] > 10 && (int)$_POST['height'] < 512) ) {
491
  $width = (int) $_POST['width'];
492
  $height = (int) $_POST['height'];
493
  image_processing( $_FILES['image']['tmp_name'], ( WPSC_CATEGORY_DIR.$_FILES['image']['name'] ), $width, $height, 'image' );
@@ -507,36 +489,36 @@ function wpsc_save_category_set($category_id, $tt_id) {
507
  $image = '';
508
  }
509
  //Good to here
510
- if( isset( $_POST['tag_ID'] ) ) {
511
- //Editing
512
- $category_id= $_POST['tag_ID'];
513
- $category = get_term_by( 'id', $category_id, 'wpsc_product_category' );
514
- $url_name=$category->slug;
515
-
516
- }
517
- if(isset($_POST['deleteimage']) && $_POST['deleteimage'] == 1) {
518
- wpsc_delete_categorymeta($category_id, 'image');
519
- } else if($image != '') {
520
- wpsc_update_categorymeta($category_id, 'image', $image);
521
  }
522
 
523
- if ( !empty( $_POST['height'] ) && is_numeric( $_POST['height'] ) && !empty( $_POST['width'] ) && is_numeric( $_POST['width'] ) && $image == null ) {
524
- $imagedata = wpsc_get_categorymeta($category_id, 'image');
525
- if($imagedata != null) {
526
  $height = $_POST['height'];
527
  $width = $_POST['width'];
528
  $imagepath = WPSC_CATEGORY_DIR . $imagedata;
529
  $image_output = WPSC_CATEGORY_DIR . $imagedata;
530
- image_processing($imagepath, $image_output, $width, $height);
531
  }
532
  }
533
 
534
- wpsc_update_categorymeta($category_id, 'fee', '0');
535
- wpsc_update_categorymeta($category_id, 'active', '1');
536
- wpsc_update_categorymeta($category_id, 'order', '0');
537
 
538
  if ( isset( $_POST['display_type'] ) )
539
- wpsc_update_categorymeta($category_id, 'display_type',esc_sql(stripslashes($_POST['display_type'])));
540
 
541
  if ( isset( $_POST['image_height'] ) )
542
  wpsc_update_categorymeta( $category_id, 'image_height', absint( $_POST['image_height'] ) );
@@ -545,34 +527,34 @@ function wpsc_save_category_set($category_id, $tt_id) {
545
  wpsc_update_categorymeta( $category_id, 'image_width', absint($_POST['image_width'] ) );
546
 
547
  if ( ! empty( $_POST['use_additional_form_set'] ) ) {
548
- wpsc_update_categorymeta($category_id, 'use_additional_form_set', $_POST['use_additional_form_set']);
549
  //exit('<pre>'.print_r($_POST,1).'</pre>');
550
  } else {
551
- wpsc_delete_categorymeta($category_id, 'use_additional_form_set');
552
  }
553
 
554
  if ( ! empty( $_POST['uses_billing_address'] ) ) {
555
- wpsc_update_categorymeta($category_id, 'uses_billing_address', 1);
556
  $uses_additional_forms = true;
557
  } else {
558
- wpsc_update_categorymeta($category_id, 'uses_billing_address', 0);
559
  $uses_additional_forms = false;
560
  }
561
 
562
- if( ! empty( $_POST['countrylist2'] ) && ($category_id > 0)){
563
- $AllSelected = false;
564
- $countryList = $wpdb->get_col("SELECT `id` FROM `".WPSC_TABLE_CURRENCY_LIST."`");
565
 
566
- if($AllSelected != true){
567
- $unselectedCountries = array_diff($countryList, $_POST['countrylist2']);
568
  //find the countries that are selected
569
- $selectedCountries = array_intersect($countryList, $_POST['countrylist2']);
570
- wpsc_update_categorymeta( $category_id, 'target_market', $selectedCountries);
571
  }
572
 
573
- } elseif ( ! isset($_POST['countrylist2'] ) ){
574
- wpsc_update_categorymeta( $category_id, 'target_market','');
575
- $AllSelected = true;
576
  }
577
 
578
  }
18
 
19
  $value = preg_replace( '/[^0-9]/', '', $value );
20
 
21
+ if( ! wpsc_update_meta( $value, 'sort_order', $key, 'wpsc_variation' ) )
22
  $result = false;
23
  }
24
  }
38
  $parent_id = $_POST['parent_id'];
39
 
40
  $result = true;
41
+ foreach ( $sort_order as $key=>$value ){
42
  if ( empty( $value ) )
43
  continue;
44
 
45
  $value = preg_replace( '/[^0-9]/', '', $value );
46
 
47
+ if ( ! wpsc_update_meta( $value, 'sort_order', $key, 'wpsc_category' ) )
48
  $result = false;
49
  }
50
  }
65
  */
66
 
67
  function wpsc_custom_category_columns( $columns ) {
68
+ // Doing it this funny way to ensure that image stays in far left, even if other items are added via plugin.
69
+ unset( $columns["cb"] );
70
 
71
+ $custom_array = array(
72
+ 'cb' => '<input type="checkbox" />',
73
+ 'image' => __( 'Image', 'wpsc' )
74
+ );
75
 
76
+ $columns = array_merge( $custom_array, $columns );
77
 
78
+ return $columns;
79
  }
80
  /**
81
  * wpsc_custom_category_column_data
91
  $name = get_term_by( 'id', $term_id, 'wpsc_product_category' );
92
  $name = $name->name;
93
 
94
+ if ( ! empty( $image ) )
95
+ $image = "<img src='" . WPSC_CATEGORY_URL . $image . "' title='" . esc_attr( $name ) . "' alt='" . esc_attr( $name ) . "' width='30' height='30' />";
96
  else
97
+ $image = "<img src='" . WPSC_CORE_IMAGES_URL . "/no-image-uploaded.gif' title='" . esc_attr( $name ) . "' alt='" . esc_attr( $name ) . "' width='30' height='30' />";
98
 
99
+ return $image;
100
 
101
  }
102
 
106
  * for use in other list functions
107
  * @param int $parent_id
108
  */
109
+ function wpsc_admin_get_category_array( $parent_id = null ){
110
+ global $wpdb;
111
+
112
+ $orderedList = array();
113
+
114
+ if ( ! isset( $parent_id ) )
115
+ $parent_id = 0;
116
+
117
+ $category_list = get_terms( 'wpsc_product_category', 'hide_empty=0&parent=' . $parent_id );
118
+
119
+ if ( ! is_array( $category_list ) ) {
120
+ return false;
121
+ }
122
+
123
+ foreach ( $category_list as $category ) {
124
+ $category_order = wpsc_get_categorymeta( $category->term_id, 'order' );
125
+ $category_image = wpsc_get_categorymeta( $category->term_id, 'image' );
126
+
127
+ if ( ! isset( $category_order ) || $category_order == 0 )
128
+ $category_order = ( count( $orderedList ) + 1 );
129
+ print "<!-- setting category Order number to " . $category_order . "-->";
130
+ $orderedList[$category_order]['id'] = $category->term_id;
131
+ $orderedList[$category_order]['name'] = $category->name;
132
+ $orderedList[$category_order]['image'] = $category_image;
133
+ $orderedList[$category_order]['parent_id'] = $parent_id;
134
+ $orderedList[$category_order]['children'] = wpsc_admin_get_category_array( $category->term_id );
135
+ }
136
+
137
+ ksort( $orderedList );
138
+ return $orderedList;
139
  }
140
 
141
  /**
148
  $display_type = isset( $category['display_type'] ) ? $category['display_type'] : '';
149
  ?>
150
 
151
+ <h3><?php esc_html_e('Advanced Store Settings', 'wpsc'); ?></h3>
152
+ <h4><?php esc_html_e('Presentation Settings', 'wpsc'); ?></h4>
153
+ <p class='description'><?php esc_html_e( 'These settings override the general presentation settings found in Settings &gt; Store &gt; Presentation.', 'wpsc' ); ?></p>
154
+ <div class="form-field">
155
+ <label for='image'><?php esc_html_e( 'Category Image' , 'wpsc' ); ?></label>
156
+ <input type='file' name='image' value='' />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  </div>
158
+ <div class="form-field">
159
+ <label for='display_type'><?php esc_html_e( 'Product Display', 'wpsc' ); ?></label>
160
+ <select name='display_type'>
161
+ <option value='default'<?php checked( $display_type, 'default' ); ?>><?php esc_html_e('Default View', 'wpsc'); ?></option>
162
+ <option value='list'<?php disabled( _wpsc_is_display_type_supported( 'list' ), false ); ?><?php checked( $display_type, 'list' ); ?>><?php esc_html_e('List View', 'wpsc'); ?></option>
163
+ <option value='grid'<?php disabled( _wpsc_is_display_type_supported( 'grid' ), false ); ?><?php checked( $display_type, 'grid' ); ?>><?php esc_html_e('Grid View', 'wpsc'); ?></option>
164
+ </select>
165
+ </div>
166
+ <?php if ( function_exists( "getimagesize" ) ) : ?>
167
+ <div class="form-field">
168
+ <?php esc_html_e( 'Thumbnail Size', 'wpsc' ); ?>
169
+ <fieldset class="wpsc-width-height-fields">
170
+ <legend class="screen-reader-text"><span><?php esc_html_e( 'Thumbnail Size', 'wpsc' ); ?></span></legend>
171
+ <label for="image_width"><?php esc_html_e( 'Width', 'wpsc' ); ?></label>
172
+ <input name="image_width" type="number" step="1" min="0" id="image_width" value="<?php if ( isset( $category['image_width'] ) ) echo esc_attr( $category['image_width'] ); ?>" class="small-text">
173
+ <label for="large_size_h"><?php esc_html_e( 'Height', 'wpsc' ); ?></label>
174
+ <input name="image_height" type="number" step="1" min="0" id="image_height" value="<?php if ( isset( $category['image_height'] ) ) echo esc_attr( $category['image_height'] ); ?>" class="small-text">
175
+ </fieldset>
176
+ </div>
177
+ <?php endif;?>
178
 
179
+ <!-- START OF TARGET MARKET SELECTION -->
180
+ <?php
 
 
181
  $category_id = '';
182
+ if ( isset( $_GET["tag_ID"] ) )
183
+ $category_id = $_GET["tag_ID"];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
+ $countrylist = $wpdb->get_results("SELECT id,country,visible FROM `" . WPSC_TABLE_CURRENCY_LIST . "` ORDER BY country ASC ", ARRAY_A);
186
+ $selectedCountries = wpsc_get_meta( $category_id, 'target_market', 'wpsc_category' );
187
+ ?>
188
+ <h4><?php esc_html_e( 'Restrict to Target Markets', 'wpsc' )?></h4>
189
+ <div class='form-field'>
190
+ <?php if( @extension_loaded( 'suhosin' ) ) : ?>
191
+ <em><?php esc_html__( "The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature then disable the suhosin extension, if you can not do this, you will need to contact your hosting provider.", 'wpsc' ); ?></em>
192
+ <?php else: ?>
193
+ <div class='multiple-select-container'>
194
+ <span><?php esc_html_e( 'Select', 'wpsc' ); ?> <a href='' class='wpsc_select_all'><?php esc_html_e( 'All', 'wpsc' ); ?></a>&nbsp; <a href='' class='wpsc_select_none'><?php esc_html_e( 'None', 'wpsc' ); ?></a></span><br />
195
+ <div id='resizeable' class='ui-widget-content multiple-select'>
196
+ <?php foreach( $countrylist as $country ): ?>
197
+ <?php if ( in_array( $country['id'], (array)$selectedCountries ) ): ?>
198
+ <input type='checkbox' name='countrylist2[]' id='countrylist2-<?php echo $country['id']; ?>' value='<?php echo $country['id']; ?>' checked='<?php echo $country['visible']; ?>' />
199
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
200
+ <?php else: ?>
201
+ <input type='checkbox' name='countrylist2[]' id='countrylist2-<?php echo $country['id']; ?>' value='<?php echo $country['id']; ?>' />
202
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
203
+ <?php endif; ?>
204
+ <?php endforeach; ?>
205
+ </div>
206
+ </div>
207
+ <span class='wpscsmall description'><?php esc_html_e( 'Select the markets you are selling this category to.', 'wpsc' ); ?><span>
208
+ <?php endif; ?>
209
  </div>
 
210
 
211
+ <!-- Checkout settings -->
212
+ <h4><?php esc_html_e( 'Checkout Settings', 'wpsc' ); ?></h4>
213
+
214
+ <?php
215
+ if ( ! isset( $category['term_id'] ) ) $category['term_id'] = '';
216
+ $used_additonal_form_set = wpsc_get_categorymeta( $category['term_id'], 'use_additional_form_set' );
217
+ ?>
218
+ <div class='form-field'>
219
+ <label for="use_additional_form_set"><?php esc_html_e( 'Category requires additional checkout form fields', 'wpsc' ); ?></label>
220
+ <select name='use_additional_form_set'>
221
+ <option value=''><?php esc_html_e( 'None', 'wpsc' ); ?></option>
222
  <?php
223
+ $checkout_sets = get_option( 'wpsc_checkout_form_sets' );
224
+ unset( $checkout_sets[0] );
225
+
226
+ foreach ( (array)$checkout_sets as $key => $value ) {
227
+ $selected_state = "";
228
+ if ( $used_additonal_form_set == $key )
229
+ $selected_state = "selected='selected'";
230
+ ?>
231
+ <option <?php echo $selected_state; ?> value='<?php echo $key; ?>'><?php echo esc_html( $value ); ?></option>
232
+ <?php
233
+ }
234
+ ?>
235
+ </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  </div>
 
237
 
238
+ <?php $uses_billing_address = (bool)wpsc_get_categorymeta( $category['term_id'], 'uses_billing_address' ); ?>
239
+ <div>
240
+ <label><?php esc_html_e( 'Address to calculate shipping with', 'wpsc' ); ?></label>
241
+ <label><input type='radio' value='1' name='uses_billing_address' <?php echo ( ( $uses_billing_address == true ) ? "checked='checked'" : "" ); ?> /> <?php esc_html_e( 'Billing Address', 'wpsc' ); ?></label>
242
+ <label><input type='radio' value='0' name='uses_billing_address' <?php echo ( ( $uses_billing_address != true ) ? "checked='checked'" : "" ); ?> /> <?php esc_html_e( 'Default Setting', 'wpsc' ); ?></label>
243
+ <p class='description'><?php esc_html_e( 'Products in this category will use the address specified to calculate shipping costs.', 'wpsc' ); ?></p>
244
+ </div>
245
 
246
+ <table class="category_forms">
247
+ <tr>
248
+
249
+ </tr>
250
+ </table>
251
+ <?php
252
  }
253
 
254
  /**
271
  $category_name = '';
272
  $category = array();
273
 
274
+ $category_id = absint( $_REQUEST["tag_ID"] );
275
+ $category = get_term( $category_id, 'wpsc_product_category', ARRAY_A );
276
+ $category['nice-name'] = wpsc_get_categorymeta( $category['term_id'], 'nice-name' );
277
+ $category['description'] = wpsc_get_categorymeta( $category['term_id'], 'description' );
278
+ $category['image'] = wpsc_get_categorymeta( $category['term_id'], 'image' );
279
+ $category['fee'] = wpsc_get_categorymeta( $category['term_id'], 'fee' );
280
+ $category['active'] = wpsc_get_categorymeta( $category['term_id'], 'active' );
281
+ $category['order'] = wpsc_get_categorymeta( $category['term_id'], 'order' );
282
+ $category['display_type'] = wpsc_get_categorymeta( $category['term_id'], 'display_type' );
283
+ $category['image_height'] = wpsc_get_categorymeta( $category['term_id'], 'image_height' );
284
+ $category['image_width'] = wpsc_get_categorymeta( $category['term_id'], 'image_width' );
285
+ $category['use_additional_form_set'] = wpsc_get_categorymeta( $category['term_id'], 'use_additional_form_set' );
 
286
 
287
  ?>
288
 
289
+ <tr>
290
+ <td colspan="2">
291
+ <h3><?php esc_html_e( 'Advanced Store Settings', 'wpsc' ); ?></h3>
292
+ <h4><?php esc_html_e( 'Shortcodes and Template Tags', 'wpsc' ); ?></h4>
293
+ <p class='description'><?php esc_html_e( 'These settings override the general presentation settings found in Settings &gt; Store &gt; Presentation.', 'wpsc' ); ?></p>
294
+ </td>
295
+ </tr>
296
 
 
 
297
 
298
  <tr class="form-field">
299
+ <th scope="row" valign="top">
300
+ <label for="display_type"><?php esc_html_e( 'Catalog View', 'wpsc' ); ?></label>
301
+ </th>
302
+ <td>
303
+ <?php
304
+ $display_type = isset( $category['display_type'] ) ? $category['display_type'] : '';
305
+ ?>
306
+ <select name='display_type'>
307
+ <option value='default'<?php checked( $display_type, 'default' ); ?>><?php esc_html_e( 'Default View', 'wpsc' ); ?></option>
308
+ <option value='list'<?php disabled( _wpsc_is_display_type_supported( 'list' ), false ); ?><?php checked( $display_type, 'list' ); ?>><?php esc_html_e('List View', 'wpsc'); ?></option>
309
+ <option value='grid' <?php disabled( _wpsc_is_display_type_supported( 'grid' ), false ); ?><?php checked( $display_type, 'grid' ); ?>><?php esc_html_e( 'Grid View', 'wpsc' ); ?></option>
310
+ </select><br />
311
+ </td>
 
312
  </tr>
313
+ <tr class="form-field">
314
+ <th scope="row" valign="top">
315
+ <label for="image"><?php esc_html_e( 'Category Image', 'wpsc' ); ?></label>
316
+ </th>
317
+ <td>
318
+ <?php
319
+ $category_image = wpsc_category_image( $category['term_id'] );
320
+ if ( $category_image )
321
+ echo '<p><img src=' . esc_url( $category_image ) . ' alt="' . esc_attr( $category['name'] ) . '" title="' . esc_attr( $category['name'] ) . '" class="wpsc_category_image" /></p>';
322
+ ?>
323
+ <input type='file' name='image' value='' /><br />
324
+ <label><input type='checkbox' name='deleteimage' class="wpsc_cat_box" value='1' /><?php esc_html_e( 'Delete Image', 'wpsc' ); ?></label><br/>
325
+ <span class="description"><?php esc_html_e( 'You can set an image for the category here. If one exists, check the box to delete.', 'wpsc' ); ?></span>
326
+ </td>
327
  </tr>
328
+ <?php if ( function_exists( "getimagesize" ) ) : ?>
329
+ <tr class="form-field">
330
+ <th scope="row" valign="top">
331
+ <label for="image"><?php esc_html_e( 'Thumbnail Size', 'wpsc' ); ?></label>
332
+ </th>
333
+ <td>
334
+ <fieldset class="wpsc-width-height-fields">
335
+ <legend class="screen-reader-text"><span><?php esc_html_e( 'Thumbnail Size', 'wpsc' ); ?></span></legend>
336
+ <label for="image_width"><?php esc_html_e( 'Width', 'wpsc' ); ?></label>
337
+ <input name="image_width" type="number" step="1" min="0" id="image_width" value="<?php if ( isset( $category['image_width'] ) ) echo esc_attr( $category['image_width'] ); ?>" class="small-text">
338
+ <label for="large_size_h"><?php esc_html_e( 'Height', 'wpsc' ); ?></label>
339
+ <input name="image_height" type="number" step="1" min="0" id="image_height" value="<?php if ( isset( $category['image_height'] ) ) echo esc_attr( $category['image_height'] ); ?>" class="small-text">
340
+ </fieldset>
341
+ </td>
342
+ </tr>
343
+ <?php endif; // 'getimagesize' condition ?>
344
+
345
+
346
+ <tr>
347
+ <td colspan="2"><h4><?php esc_html_e( 'Shortcodes and Template Tags', 'wpsc' ); ?></h4></td>
348
  </tr>
349
+
350
+ <tr class="form-field">
351
+ <th scope="row" valign="top">
352
+ <label for="image"><?php esc_html_e( 'Display Category Shortcode', 'wpsc' ); ?></label>
353
+ </th>
354
+ <td>
355
+ <code>[wpsc_products category_url_name='<?php echo $category["slug"]; ?>']</code><br />
356
+ <span class="description"><?php esc_html_e( 'Shortcodes are used to display a particular category or group within any WordPress page or post.', 'wpsc' ); ?></span>
357
+ </td>
358
+ </tr>
359
+ <tr class="form-field">
360
+ <th scope="row" valign="top">
361
+ <label for="image"><?php esc_html_e( 'Display Category Template Tag', 'wpsc' ); ?></label>
362
+ </th>
363
+ <td>
364
+ <code>&lt;?php echo wpsc_display_products_page( array( 'category_url_name' => '<?php echo $category["slug"]; ?>' ) ); ?&gt;</code><br />
365
+ <span class="description"><?php esc_html_e( 'Template tags are used to display a particular category or group within your theme / template.', 'wpsc' ); ?></span>
366
+ </td>
367
+ </tr>
368
+
369
+ <!-- START OF TARGET MARKET SELECTION -->
370
+
371
  <tr>
372
+ <td colspan="2">
373
+ <h4><?php esc_html_e( 'Target Market Restrictions', 'wpsc' ); ?></h4>
374
+ </td>
 
 
 
 
 
 
 
 
375
  </tr>
376
+ <?php
377
+ $countrylist = $wpdb->get_results( "SELECT id,country,visible FROM `".WPSC_TABLE_CURRENCY_LIST."` ORDER BY country ASC ",ARRAY_A );
378
+ $selectedCountries = wpsc_get_meta( $category_id,'target_market','wpsc_category' );
379
+ ?>
380
+ <tr>
381
+ <th scope="row" valign="top">
382
+ <label for="image"><?php esc_html_e( 'Target Markets', 'wpsc' ); ?></label>
383
+ </th>
384
+ <td>
385
+ <?php if ( wpsc_is_suhosin_enabled() ) : ?>
386
+ <em><?php esc_html_e( 'The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature, then disable the suhosin extension. If you can not do this, you will need to contact your hosting provider.','wpsc' ); ?></em>
387
+ <?php else : ?>
388
+ <span><?php esc_html_e( 'Select', 'wpsc' ); ?>: <a href='' class='wpsc_select_all'><?php esc_html_e( 'All', 'wpsc' ); ?></a>&nbsp; <a href='' class='wpsc_select_none'><?php esc_html_e( 'None', 'wpsc' ); ?></a></span><br />
389
+ <div id='resizeable' class='ui-widget-content multiple-select'>
390
+ <?php foreach( $countrylist as $country ) {
391
+ if ( in_array( $country['id'], (array)$selectedCountries ) ) {
392
+ ?>
393
+ <input type='checkbox' name='countrylist2[]' id='countrylist2-<?php echo $country['id']; ?>' value='<?php echo $country['id']; ?>' checked='<?php echo $country['visible']; ?>' />
394
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
395
+ <?php
396
+ } else {
397
+ ?>
398
+ <input type='checkbox' name='countrylist2[]' id='countrylist2-<?php echo $country['id']; ?>' value='<?php echo $country['id']; ?>' />
399
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
400
+ <?php
401
+ }
402
+ } ?>
403
+ </div>
404
+ <?php endif; ?><br />
405
+ <span class="description"><?php esc_html_e( 'Select the markets you are selling this category to.', 'wpsc' ); ?></span>
406
+ </td>
407
  </tr>
408
 
409
+ <!-- Checkout settings -->
410
+
411
+ <tr>
412
+ <td colspan="2">
413
+ <h4><?php esc_html_e( 'Checkout Settings', 'wpsc' ); ?></h4>
414
+ </td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  </tr>
416
+ <?php
417
+ if ( !isset( $category['term_id'] ) )
418
+ $category['term_id'] = '';
419
+
420
+ $used_additonal_form_set = wpsc_get_categorymeta( $category['term_id'], 'use_additional_form_set' );
421
+ $checkout_sets = get_option('wpsc_checkout_form_sets');
422
+ unset($checkout_sets[0]);
423
+ $uses_billing_address = (bool)wpsc_get_categorymeta( $category['term_id'], 'uses_billing_address' );
424
+ ?>
425
+ <tr class="form-field">
426
+ <th scope="row" valign="top">
427
+ <label for="image"><?php esc_html_e( 'Category requires additional checkout form fields', 'wpsc' ); ?></label>
428
+ </th>
429
+ <td>
430
+ <select name='use_additional_form_set'>
431
+ <option value=''><?php esc_html_e( 'None', 'wpsc' ); ?></option>
432
+ <?php
433
+ foreach( (array) $checkout_sets as $key => $value ) {
434
+ $selected_state = "";
435
+ if ( $used_additonal_form_set == $key ) {
436
+ $selected_state = "selected='selected'";
437
+ } ?>
438
+ <option <?php echo $selected_state; ?> value='<?php echo $key; ?>'><?php echo esc_html( $value ); ?></option>
439
+ <?php
440
+ }
441
+ ?>
442
+ </select>
443
+ </td>
 
 
 
 
 
 
444
  </tr>
445
 
446
+ <tr class="form-field">
447
+ <th scope="row" valign="top">
448
+ <label><?php esc_html_e( 'Address to calculate shipping with', 'wpsc' ); ?></label>
449
+ </th>
450
+ <td>
451
+ <label><input type='radio' class='wpsc_cat_box' value='0' name='uses_billing_address' <?php echo ( ( $uses_billing_address != true ) ? "checked='checked'" : "" ); ?> /> <?php esc_html_e( 'Default Setting', 'wpsc' ); ?></label>
452
+ <label><input type='radio' class='wpsc_cat_box' value='1' name='uses_billing_address' <?php echo ( ( $uses_billing_address == true ) ? "checked='checked'" : "" ); ?> /> <?php esc_html_e( 'Billing Address', 'wpsc' ); ?></label>
453
+ <p class='description'><?php esc_html_e( 'Products in this category will use the address specified to calculate shipping costs.', 'wpsc' ); ?></p>
454
+ </td>
455
  </tr>
456
 
457
+ <?php
458
  }
459
 
460
  /**
462
  * @param nothing
463
  * @return nothing
464
  */
465
+ function wpsc_save_category_set( $category_id, $tt_id ) {
466
  global $wpdb;
467
 
468
+ if ( ! empty( $_POST ) ) {
469
  /* Image Processing Code*/
470
+ if ( ! empty( $_FILES['image'] ) && preg_match( "/\.(gif|jp(e)*g|png){1}$/i", $_FILES['image']['name'] ) ) {
471
+ if ( function_exists( "getimagesize" ) ) {
472
+ if ( isset( $_POST['width'] ) && ( (int) $_POST['width'] > 10 && (int) $_POST['width'] < 512 ) && ( (int)$_POST['height'] > 10 && (int)$_POST['height'] < 512 ) ) {
473
  $width = (int) $_POST['width'];
474
  $height = (int) $_POST['height'];
475
  image_processing( $_FILES['image']['tmp_name'], ( WPSC_CATEGORY_DIR.$_FILES['image']['name'] ), $width, $height, 'image' );
489
  $image = '';
490
  }
491
  //Good to here
492
+ if ( isset( $_POST['tag_ID'] ) ) {
493
+ //Editing
494
+ $category_id = $_POST['tag_ID'];
495
+ $category = get_term_by( 'id', $category_id, 'wpsc_product_category' );
496
+ $url_name = $category->slug;
497
+
498
+ }
499
+ if ( isset( $_POST['deleteimage'] ) && $_POST['deleteimage'] == 1 ) {
500
+ wpsc_delete_categorymeta( $category_id, 'image' );
501
+ } else if ( $image != '' ) {
502
+ wpsc_update_categorymeta( $category_id, 'image', $image );
503
  }
504
 
505
+ if ( ! empty( $_POST['height'] ) && is_numeric( $_POST['height'] ) && ! empty( $_POST['width'] ) && is_numeric( $_POST['width'] ) && $image == null ) {
506
+ $imagedata = wpsc_get_categorymeta( $category_id, 'image' );
507
+ if ( $imagedata != null ) {
508
  $height = $_POST['height'];
509
  $width = $_POST['width'];
510
  $imagepath = WPSC_CATEGORY_DIR . $imagedata;
511
  $image_output = WPSC_CATEGORY_DIR . $imagedata;
512
+ image_processing( $imagepath, $image_output, $width, $height );
513
  }
514
  }
515
 
516
+ wpsc_update_categorymeta( $category_id, 'fee', '0' );
517
+ wpsc_update_categorymeta( $category_id, 'active', '1' );
518
+ wpsc_update_categorymeta( $category_id, 'order', '0' );
519
 
520
  if ( isset( $_POST['display_type'] ) )
521
+ wpsc_update_categorymeta( $category_id, 'display_type', esc_sql( stripslashes( $_POST['display_type'] ) ) );
522
 
523
  if ( isset( $_POST['image_height'] ) )
524
  wpsc_update_categorymeta( $category_id, 'image_height', absint( $_POST['image_height'] ) );
527
  wpsc_update_categorymeta( $category_id, 'image_width', absint($_POST['image_width'] ) );
528
 
529
  if ( ! empty( $_POST['use_additional_form_set'] ) ) {
530
+ wpsc_update_categorymeta( $category_id, 'use_additional_form_set', $_POST['use_additional_form_set'] );
531
  //exit('<pre>'.print_r($_POST,1).'</pre>');
532
  } else {
533
+ wpsc_delete_categorymeta( $category_id, 'use_additional_form_set' );
534
  }
535
 
536
  if ( ! empty( $_POST['uses_billing_address'] ) ) {
537
+ wpsc_update_categorymeta( $category_id, 'uses_billing_address', 1 );
538
  $uses_additional_forms = true;
539
  } else {
540
+ wpsc_update_categorymeta( $category_id, 'uses_billing_address', 0 );
541
  $uses_additional_forms = false;
542
  }
543
 
544
+ if ( ! empty( $_POST['countrylist2'] ) && ( $category_id > 0 ) ) {
545
+ $AllSelected = false;
546
+ $countryList = $wpdb->get_col( "SELECT `id` FROM `" . WPSC_TABLE_CURRENCY_LIST . "`" );
547
 
548
+ if ( $AllSelected != true ){
549
+ $unselectedCountries = array_diff( $countryList, $_POST['countrylist2'] );
550
  //find the countries that are selected
551
+ $selectedCountries = array_intersect( $countryList, $_POST['countrylist2'] );
552
+ wpsc_update_categorymeta( $category_id, 'target_market', $selectedCountries );
553
  }
554
 
555
+ } elseif ( ! isset( $_POST['countrylist2'] ) ){
556
+ wpsc_update_categorymeta( $category_id, 'target_market', '' );
557
+ $AllSelected = true;
558
  }
559
 
560
  }
wpsc-admin/includes/settings-tabs/admin.php CHANGED
@@ -8,7 +8,7 @@ class WPSC_Settings_Tab_Admin extends WPSC_Settings_Tab {
8
  <tr>
9
  <th scope="row"><?php esc_html_e( 'Max downloads per file', 'wpsc' ); ?>: </th>
10
  <td>
11
- <input type='text' size='10' value='<?php echo esc_attr( get_option('max_downloads') ); ?>' name='wpsc_options[max_downloads]' />
12
  </td>
13
  </tr>
14
  <?php
8
  <tr>
9
  <th scope="row"><?php esc_html_e( 'Max downloads per file', 'wpsc' ); ?>: </th>
10
  <td>
11
+ <input type="number" size="10" value="<?php echo esc_attr( get_option('max_downloads') ); ?>" name="wpsc_options[max_downloads]" />
12
  </td>
13
  </tr>
14
  <?php
wpsc-admin/includes/settings-tabs/checkout.php CHANGED
@@ -12,13 +12,13 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
12
  public function __construct() {
13
  global $wpdb;
14
 
15
- $this->require_register = get_option( 'require_register', 0 );
16
  $this->shipping_same_as_billing = get_option( 'shippingsameasbilling', 0 );
17
- $this->force_ssl = get_option( 'wpsc_force_ssl', 0 );
18
- $this->checkout_sets = get_option( 'wpsc_checkout_form_sets' );
19
- $this->current_checkout_set = empty( $_GET['checkout_set'] ) ? 0 : (int) $_GET['checkout_set'];
20
- $this->field_types = get_option( 'wpsc_checkout_form_fields' );
21
- $this->user_field_types = array('text','textarea','heading','select','radio','checkbox');
22
 
23
  if ( ! isset( $this->checkout_sets[$this->current_checkout_set] ) ) {
24
  wp_redirect( remove_query_arg( 'checkout_set' ) );
@@ -131,7 +131,8 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
131
  $value = $_POST['form_options'][$field_id]['value'][$key];
132
  if ( $label === '' && $value === '')
133
  continue;
134
- $options[$label] = $value;
 
135
  }
136
  $data['options'] = serialize( $options );
137
  $data_format[] = '%s';
@@ -270,8 +271,7 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
270
  </td>
271
  <td class="namecol">
272
  <div class="cell-wrapper">
273
- <input type="text" name="new_field_name[<?php echo $new_field_id; ?>]" value="" />
274
- <a class="edit-options" href="#"><?php esc_html_e( 'Edit Options', 'wpsc' ); ?></a>
275
  </div>
276
  </td>
277
  <td class="typecol">
@@ -286,6 +286,7 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
286
  </div>
287
  </td>
288
  <td class="uniquenamecol">
 
289
  </td>
290
  <td class="displaycol">
291
  <div class="cell-wrapper">
@@ -353,53 +354,44 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
353
  do_action( 'wpsc_checkout_form_fields_page' );
354
  ?>
355
 
356
- <div class='metabox-holder' style='width:95%;'>
357
- <div class='postbox'>
358
- <input type='hidden' name='checkout_submits' value='true' />
359
- <h3 class='hndle'><?php esc_html_e( 'Misc Checkout Options' , 'wpsc' ); ?></h3>
360
- <div class='inside'>
361
- <table>
362
- <tr>
363
- <td><?php esc_html_e('Users must register before checking out', 'wpsc'); ?>:</td>
364
- <td>
365
- <input type='radio' value='1' name='wpsc_options[require_register]' id='require_register1' <?php checked( $this->require_register, 1 ); ?> />
366
- <label for='require_register1'><?php _e( 'Yes', 'wpsc' );?></label> &nbsp;
367
- <input type='radio' value='0' name='wpsc_options[require_register]' id='require_register2' <?php checked( $this->require_register, 0 ); ?> />
368
- <label for='require_register2'><?php _e( 'No', 'wpsc' );?></label>
369
- </td>
370
- <td>
371
- <a title='<?php esc_attr_e( 'If yes then you must also turn on the wordpress option "Any one can register"', 'wpsc' ); ?>' class='flag_email' href='#' ><img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/help.png' alt='' /> </a>
372
- </td>
373
- </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
 
375
- <tr>
376
- <td scope="row"><?php esc_html_e('Enable Shipping Same as Billing Option', 'wpsc' ); ?>:</td>
377
- <td>
378
- <input type='radio' value='1' name='wpsc_options[shippingsameasbilling]' id='shippingsameasbilling1' <?php checked( $this->shipping_same_as_billing, 1 ); ?> />
379
- <label for='shippingsameasbilling1'><?php _e( 'Yes', 'wpsc' );?></label> &nbsp;
380
- <input type='radio' value='0' name='wpsc_options[shippingsameasbilling]' id='shippingsameasbilling2' <?php checked( $this->shipping_same_as_billing, 0 ); ?> />
381
- <label for='shippingsameasbilling2'><?php _e( 'No', 'wpsc' );?></label>
382
- </td>
383
- </tr>
384
- <tr>
385
- <td><?php _e('Force users to use SSL', 'wpsc'); ?>:</td>
386
- <td>
387
- <input type='radio' value='1' name='wpsc_options[wpsc_force_ssl]' id='wpsc_force_ssl1' <?php checked( $this->force_ssl, 1 ); ?> />
388
- <label for='wpsc_force_ssl1'><?php _e( 'Yes', 'wpsc' );?></label> &nbsp;
389
- <input type='radio' value='0' name='wpsc_options[wpsc_force_ssl]' id='wpsc_force_ssl2' <?php checked( $this->force_ssl, 0 ); ?> />
390
- <label for='wpsc_force_ssl2'><?php _e( 'No', 'wpsc' );?></label>
391
- </td>
392
- <td>
393
- <a title='<?php esc_html_e( 'This can cause warnings for your users if you do not have a properly configured SSL certificate', 'wpsc' );?>' class='flag_email' href='#' ><img src='<?php echo WPSC_CORE_IMAGES_URL; ?>/help.png' alt='' /> </a>
394
- </td>
395
- </tr>
396
- </table>
397
- </div>
398
- </div>
399
- </div>
400
 
401
- <h3><?php esc_html_e( 'Form Fields', 'wpsc' ); ?></h3>
402
- <p><?php esc_html_e( 'Here you can customise the forms to be displayed in your checkout page. The checkout page is where you collect important user information that will show up in your purchase logs i.e. the buyers address, and name...', 'wpsc' );?></p>
403
 
404
  <p>
405
  <label for='wpsc_form_set'><?php esc_html_e( 'Select a Form Set' , 'wpsc' ); ?>:</label>
@@ -441,7 +433,8 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
441
  <?php $this->prototype_field( 'new' ); ?>
442
  <?php else: ?>
443
  <?php foreach ( $this->form_fields as $form_field ): ?>
444
- <tr data-field-id="<?php echo esc_attr( $form_field->id ); ?>" id="checkout_<?php echo esc_attr( $form_field->id ); ?>" class="checkout_form_field">
 
445
  <td class="drag">
446
  <div class="cell-wrapper">
447
  <a title="<?php esc_attr_e( 'Click and Drag to Order Checkout Fields', 'wpsc' ); ?>">
@@ -453,13 +446,6 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
453
  <td class="namecol">
454
  <div class="cell-wrapper">
455
  <input type="text" name="form_name[<?php echo esc_attr( $form_field->id ); ?>]" value="<?php echo esc_attr( $form_field->name ); ?>" />
456
- <a
457
- class="edit-options" href="#"
458
- <?php
459
- if ( in_array( $form_field->type, array( 'select', 'radio', 'checkbox' ) ) )
460
- echo 'style="display:inline;"';
461
- ?>
462
- ><?php esc_html_e( 'Edit Options', 'wpsc' ); ?></a>
463
  </div>
464
  </td>
465
  <td class="typecol">
@@ -490,9 +476,16 @@ class WPSC_Settings_Tab_Checkout extends WPSC_Settings_Tab {
490
 
491
  <td class="uniquenamecol">
492
  <div class="cell-wrapper">
493
- <?php if ( $form_field->type != 'heading' && ! empty( $form_field->unique_name ) ): ?>
494
- <small><?php echo esc_html( $form_field->unique_name ); ?></small>
495
- <?php endif ?>
 
 
 
 
 
 
 
496
  </div>
497
  </td>
498
  <td class="displaycol">
12
  public function __construct() {
13
  global $wpdb;
14
 
15
+ $this->require_register = get_option( 'require_register', 0 );
16
  $this->shipping_same_as_billing = get_option( 'shippingsameasbilling', 0 );
17
+ $this->force_ssl = get_option( 'wpsc_force_ssl', 0 );
18
+ $this->checkout_sets = get_option( 'wpsc_checkout_form_sets' );
19
+ $this->current_checkout_set = empty( $_GET['checkout_set'] ) ? 0 : (int) $_GET['checkout_set'];
20
+ $this->field_types = get_option( 'wpsc_checkout_form_fields' );
21
+ $this->user_field_types = array('text','textarea','heading','select','radio','checkbox');
22
 
23
  if ( ! isset( $this->checkout_sets[$this->current_checkout_set] ) ) {
24
  wp_redirect( remove_query_arg( 'checkout_set' ) );
131
  $value = $_POST['form_options'][$field_id]['value'][$key];
132
  if ( $label === '' && $value === '')
133
  continue;
134
+ $label = sanitize_text_field( $label );
135
+ $options[$label] = sanitize_text_field( $value );
136
  }
137
  $data['options'] = serialize( $options );
138
  $data_format[] = '%s';
271
  </td>
272
  <td class="namecol">
273
  <div class="cell-wrapper">
274
+ <input type="text" name="new_field_name[<?php echo $new_field_id; ?>]" value="" /><br />
 
275
  </div>
276
  </td>
277
  <td class="typecol">
286
  </div>
287
  </td>
288
  <td class="uniquenamecol">
289
+ <a class="edit-options" href="#"><?php esc_html_e( 'Edit Options', 'wpsc' ); ?></a>
290
  </td>
291
  <td class="displaycol">
292
  <div class="cell-wrapper">
354
  do_action( 'wpsc_checkout_form_fields_page' );
355
  ?>
356
 
357
+ <input type='hidden' name='checkout_submits' value='true' />
358
+ <h3><?php esc_html_e( 'Checkout Settings' , 'wpsc' ); ?></h3>
359
+ <table class='form-table'>
360
+ <tr>
361
+ <th scope="row"><?php esc_html_e('Force User Registration', 'wpsc'); ?></th>
362
+ <td>
363
+ <input type='radio' value='0' name='wpsc_options[require_register]' id='require_register2' <?php checked( $this->require_register, 0 ); ?> />
364
+ <label for='require_register2'><?php _e( 'Users can checkout without a user account', 'wpsc' );?></label><br />
365
+ <input type='radio' value='1' name='wpsc_options[require_register]' id='require_register1' <?php checked( $this->require_register, 1 ); ?> />
366
+ <label for='require_register1'><?php _e( 'Users must register before checking out', 'wpsc' );?></label>
367
+ <p class='description'><?php esc_attr_e( 'If users must register, you must also turn on "Membership: Anyone can register" from within WordPress Settings &gt; General', 'wpsc' ); ?></p>
368
+ </td>
369
+ </tr>
370
+
371
+ <tr>
372
+ <th scope="row"><?php esc_html_e('Shipping Same as Billing', 'wpsc' ); ?></th>
373
+ <td>
374
+ <input type='radio' value='1' name='wpsc_options[shippingsameasbilling]' id='shippingsameasbilling1' <?php checked( $this->shipping_same_as_billing, 1 ); ?> />
375
+ <label for='shippingsameasbilling1'><?php _e( 'Enable "Same as billing address" checkbox with Shipping Address fields', 'wpsc' );?></label><br />
376
+ <input type='radio' value='0' name='wpsc_options[shippingsameasbilling]' id='shippingsameasbilling2' <?php checked( $this->shipping_same_as_billing, 0 ); ?> />
377
+ <label for='shippingsameasbilling2'><?php _e( 'Users must re-enter Shipping Address', 'wpsc' );?></label>
378
+ </td>
379
+ </tr>
380
+ <tr>
381
+ <th scope="row"><?php _e('Security and Encryption', 'wpsc'); ?></th>
382
+ <td>
383
+ <input type='radio' value='1' name='wpsc_options[wpsc_force_ssl]' id='wpsc_force_ssl1' <?php checked( $this->force_ssl, 1 ); ?> />
384
+ <label for='wpsc_force_ssl1'><?php _e( 'Force users to use SSL Encryption', 'wpsc' );?></label><br />
385
+ <input type='radio' value='0' name='wpsc_options[wpsc_force_ssl]' id='wpsc_force_ssl2' <?php checked( $this->force_ssl, 0 ); ?> />
386
+ <label for='wpsc_force_ssl2'><?php _e( 'Allow site to be used insecurely and unencrypted', 'wpsc' );?></label>
387
+ <p class='description'><?php esc_html_e( 'This can cause warnings for your users if you do not have a properly configured SSL certificate', 'wpsc' );?></p>
388
+ </td>
389
+ </tr>
390
+ </table>
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
 
393
+ <h3><?php esc_html_e( 'Checkout Form Fields', 'wpsc' ); ?></h3>
394
+ <p><?php esc_html_e( 'Here you can customise the forms to be displayed in your checkout page. The checkout page is where you collect important user information that will show up in your purchase logs i.e. the buyer\'s address, and name...', 'wpsc' );?></p>
395
 
396
  <p>
397
  <label for='wpsc_form_set'><?php esc_html_e( 'Select a Form Set' , 'wpsc' ); ?>:</label>
433
  <?php $this->prototype_field( 'new' ); ?>
434
  <?php else: ?>
435
  <?php foreach ( $this->form_fields as $form_field ): ?>
436
+
437
+ <tr data-field-id="<?php echo esc_attr( $form_field->id ); ?>" data-field-type="<?php echo $form_field->type; ?>" id="checkout_<?php echo esc_attr( $form_field->id ); ?>" class="checkout_form_field field_type_<?php echo $form_field->type; ?>">
438
  <td class="drag">
439
  <div class="cell-wrapper">
440
  <a title="<?php esc_attr_e( 'Click and Drag to Order Checkout Fields', 'wpsc' ); ?>">
446
  <td class="namecol">
447
  <div class="cell-wrapper">
448
  <input type="text" name="form_name[<?php echo esc_attr( $form_field->id ); ?>]" value="<?php echo esc_attr( $form_field->name ); ?>" />
 
 
 
 
 
 
 
449
  </div>
450
  </td>
451
  <td class="typecol">
476
 
477
  <td class="uniquenamecol">
478
  <div class="cell-wrapper">
479
+ <?php if ( $form_field->type != 'heading' && ! empty( $form_field->unique_name ) ): ?>
480
+ <small><?php echo esc_html( $form_field->unique_name ); ?></small>
481
+ <?php endif ?>
482
+ <?php
483
+ $style = '';
484
+ if ( in_array( $form_field->type, array( 'select', 'radio', 'checkbox' ) ) ) {
485
+ $style = 'style="display: inline;"';
486
+ }
487
+ ?>
488
+ <a class="edit-options" href="#" <?php echo $style; ?> ><?php esc_html_e( 'Edit Options', 'wpsc' ); ?></a>
489
  </div>
490
  </td>
491
  <td class="displaycol">
wpsc-admin/includes/settings-tabs/general.php CHANGED
@@ -41,7 +41,7 @@ class WPSC_Settings_Tab_General extends WPSC_Settings_Tab {
41
  <h3><?php echo esc_html_e( 'General Settings', 'wpsc' ); ?></h3>
42
  <table class='wpsc_options form-table'>
43
  <tr>
44
- <th scope="row"><?php esc_html_e( 'Base Country/Region', 'wpsc' ); ?>: </th>
45
  <td>
46
  <?php
47
  wpsc_country_dropdown( array(
@@ -55,144 +55,152 @@ class WPSC_Settings_Tab_General extends WPSC_Settings_Tab {
55
  <?php $this->display_region_drop_down(); ?>
56
  <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
57
  </span>
58
- <br /><?php esc_html_e( 'Select your primary business location.', 'wpsc' ); ?>
59
  </td>
60
  </tr>
 
61
  <?php
62
- /* START OF TARGET MARKET SELECTION */
63
- $countrylist = $wpdb->get_results( "SELECT id,country,visible FROM `" . WPSC_TABLE_CURRENCY_LIST . "` ORDER BY country ASC ", ARRAY_A );
64
  ?>
65
- <tr>
66
- <th scope="row">
67
- <?php esc_html_e( 'Target Markets', 'wpsc' ); ?>:
68
- </th>
69
- <td>
70
  <?php
71
  // check for the suhosin module
72
  if ( wpsc_is_suhosin_enabled() ) {
73
  echo "<em>" . __( "The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature then disable the suhosin extension, if you can not do this, you will need to contact your hosting provider.", 'wpsc' ) . "</em>";
74
  } else {
75
- ?>
76
  <span>
77
- <?php printf( __( 'Select: <a href="%1$s" class="wpsc-select-all" title="All">All</a> <a href="%2$s" class="wpsc-select-none" title="None">None</a>' , 'wpsc') , add_query_arg( array( 'selected_all' => 'all' ) ), add_query_arg( array( 'selected_all' => 'none' ) ) ); ?>
78
  </span><br />
79
  <div id='wpsc-target-markets' class='ui-widget-content multiple-select'>
80
- <?php
81
- foreach ( (array)$countrylist as $country ) {
82
- if ( $country['visible'] == 1 ) {
83
- ?>
84
- <input type='checkbox' id="countrylist2-<?php echo $country['id']; ?>" name='countrylist2[]' value='<?php echo $country['id']; ?>' checked='checked' /> <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
85
- <?php } else {
86
- ?>
87
- <input type='checkbox' id="countrylist2-<?php echo $country['id']; ?>" name='countrylist2[]' value='<?php echo $country['id']; ?>' /> <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
88
- <?php }
89
- } ?>
90
- </div><br />
91
- <?php esc_html_e( 'Select the markets you are selling products to.' , 'wpsc');
 
92
  }
93
- ?>
94
- </td>
95
- </tr>
96
- <?php
97
- $stock_keeping_time = get_option( 'wpsc_stock_keeping_time', 1 );
98
- $stock_keeping_interval = get_option( 'wpsc_stock_keeping_interval', 'day' );
99
- ?>
100
- <tr>
101
- <th scope="row">
102
- <label for="wpsc-stock-keeping-time"><?php esc_html_e( 'Keep stock in cart for', 'wpsc' ); ?>:</label>
103
- </th>
104
- <td>
105
- <input type="text" name="wpsc_options[wpsc_stock_keeping_time]" id="wpsc-stock-keeping-time" size="2" value="<?php echo esc_attr( $stock_keeping_time ); ?>" />
106
- <select name="wpsc_options[wpsc_stock_keeping_interval]">
107
- <option value="hour" <?php selected( 'hour', $stock_keeping_interval ); ?>><?php echo _n( 'hour', 'hours', $stock_keeping_time, 'wpsc' ); ?></option>
108
- <option value="day" <?php selected( 'day', $stock_keeping_interval ); ?>><?php echo _n( 'day', 'days', $stock_keeping_time, 'wpsc' ) ?></option>
109
- <option value="week" <?php selected( 'week', $stock_keeping_interval ); ?>><?php echo _n( 'week', 'weeks', $stock_keeping_time, 'wpsc' ) ?></option>
110
- </select><br />
111
- <?php esc_html_e( "Set the amount of time items in a customer's cart are reserved. You can also specify decimal amounts such as '0.5 days' or '1.25 weeks'. Note that the minimum interval you can enter is 1 hour, i.e. you can't schedule it to run every 0.5 hour.", 'wpsc' ) ?>
112
- </td>
113
- </tr>
114
- <?php $hierarchical_category = get_option( 'product_category_hierarchical_url', 0 ); ?>
115
- <tr>
116
- <th scope="row">
117
- <?php _e( 'Use Hierarchical Product Category URL', 'wpsc' ); ?>:
118
- </th>
119
- <td>
120
- <label><input type="radio" <?php checked( $hierarchical_category, 1 ); ?> name="wpsc_options[product_category_hierarchical_url]" value="1" /> <?php _e( 'Yes', 'wpsc' ); ?></label>&nbsp;&nbsp;
121
- <label><input type="radio" <?php checked( $hierarchical_category, 0 ); ?>name="wpsc_options[product_category_hierarchical_url]" value="0" /> <?php _e( 'No', 'wpsc' ); ?></label><br />
122
- <?php _e( 'When Hierarchical Product Category URL is enabled, parent product categories are also included in the product URL.<br />For example: example.com/products-page/parent-cat/sub-cat/product-name', 'wpsc' ); ?>
123
- </td>
124
- </tr>
125
- </table>
126
 
127
- <h3 class="form_group"><?php esc_html_e( 'Currency Settings', 'wpsc' ); ?>:</h3>
128
- <table class='wpsc_options form-table'>
129
- <tr>
130
- <th scope="row"><?php esc_html_e( 'Currency Type', 'wpsc' ); ?>:</th>
 
 
 
 
131
  <td>
132
- <select name='wpsc_options[currency_type]' onchange='getcurrency(this.options[this.selectedIndex].value);'>
133
- <?php
134
- $currency_data = $wpdb->get_results( "SELECT * FROM `" . WPSC_TABLE_CURRENCY_LIST . "` ORDER BY `country` ASC", ARRAY_A );
135
- $currency_type = esc_attr( get_option( 'currency_type' ) );
136
- foreach ( $currency_data as $currency ) {
137
- ?>
138
- <option value='<?php echo $currency['id']; ?>' <?php selected( $currency['id'], $currency_type ); ?>><?php esc_html_e( $currency['country'] ); ?> (<?php echo $currency['currency']; ?>)</option>
139
- <?php
140
- }
141
- $currency_data = $wpdb->get_row( "SELECT `symbol`,`symbol_html`,`code` FROM `" . WPSC_TABLE_CURRENCY_LIST . "` WHERE `id`='" . esc_attr( get_option( 'currency_type' ) ) . "' LIMIT 1", ARRAY_A );
142
- if ( $currency_data['symbol'] != '' ) {
143
- $currency_sign = esc_attr( $currency_data['symbol_html'] );
144
- } else {
145
- $currency_sign = esc_attr( $currency_data['code'] );
146
- }
147
- ?>
148
  </select>
 
149
  </td>
150
  </tr>
 
 
 
 
151
  <tr>
152
- <th scope="row"><?php esc_html_e( 'Currency Sign Location', 'wpsc' ); ?>:</th>
153
- <td>
154
- <?php
155
- $currency_sign_location = esc_attr( get_option( 'currency_sign_location' ) );
156
- $csl1 = "";
157
- $csl2 = "";
158
- $csl3 = "";
159
- $csl4 = "";
160
- switch ( $currency_sign_location ) {
161
- case 1:
162
- $csl1 = "checked ='checked'";
163
- break;
164
 
165
- case 2:
166
- $csl2 = "checked ='checked'";
167
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- case 3:
170
- $csl3 = "checked ='checked'";
171
- break;
172
 
173
- case 4:
174
- $csl4 = "checked ='checked'";
175
- break;
176
- } ?>
177
- <input type='radio' value='1' name='wpsc_options[currency_sign_location]' id='csl1' <?php echo $csl1; ?> />
178
- <label for='csl1'><?php _ex( '100', 'Currency sign location - option 1', 'wpsc' ); ?><span id='cslchar1'><?php echo $currency_sign; ?></span></label> &nbsp;
179
- <input type='radio' value='2' name='wpsc_options[currency_sign_location]' id='csl2' <?php echo $csl2; ?> />
180
- <label for='csl2'><?php _ex( '100', 'Currency sign location - option 2', 'wpsc' ); ?> <span id='cslchar2'><?php echo $currency_sign; ?></span></label> &nbsp;
181
- <input type='radio' value='3' name='wpsc_options[currency_sign_location]' id='csl3' <?php echo $csl3; ?> />
182
- <label for='csl3'><span id='cslchar3'><?php echo $currency_sign; ?></span><?php _ex( '100', 'Currency sign location - option 3', 'wpsc' ); ?></label> &nbsp;
183
- <input type='radio' value='4' name='wpsc_options[currency_sign_location]' id='csl4' <?php echo $csl4; ?> />
184
- <label for='csl4'><span id='cslchar4'><?php echo $currency_sign; ?></span> <?php _ex( '100', 'Currency sign location - option 4', 'wpsc' ); ?></label>
185
- </td>
186
- </tr>
187
- <tr>
188
- <th scope="row"><?php esc_html_e( 'Thousands and decimal separators', 'wpsc' ); ?>:</th>
189
- <td>
190
- <?php esc_html_e( 'Thousands separator', 'wpsc' ); ?>: <input name="wpsc_options[wpsc_thousands_separator]" type="text" maxlength="1" size="1" value="<?php echo esc_attr( get_option( 'wpsc_thousands_separator' ) ); ?>" /> <br />
191
- <?php esc_html_e( 'Decimal separator', 'wpsc' ); ?>: <input name="wpsc_options[wpsc_decimal_separator]" type="text" maxlength="1" size="1" value="<?php echo esc_attr( get_option( 'wpsc_decimal_separator' ) ); ?>" /> <br />
192
- <?php esc_html_e( 'Preview:', 'wpsc' ); ?> 10<?php echo esc_attr( get_option( 'wpsc_thousands_separator' ) ); ?>000<?php echo esc_attr( get_option( 'wpsc_decimal_separator' ) ); ?>00
193
- </td>
194
- </tr>
195
- </table>
 
 
 
 
 
 
 
 
196
  <?php
197
  }
198
- }
41
  <h3><?php echo esc_html_e( 'General Settings', 'wpsc' ); ?></h3>
42
  <table class='wpsc_options form-table'>
43
  <tr>
44
+ <th scope="row"><label for="wpsc-base-country-drop-down"><?php esc_html_e( 'Base Country/Region', 'wpsc' ); ?></label></th>
45
  <td>
46
  <?php
47
  wpsc_country_dropdown( array(
55
  <?php $this->display_region_drop_down(); ?>
56
  <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
57
  </span>
58
+ <p class='description'><?php esc_html_e( 'Select your primary business location.', 'wpsc' ); ?></p>
59
  </td>
60
  </tr>
61
+
62
  <?php
63
+ /* START OF TARGET MARKET SELECTION */
64
+ $countrylist = $wpdb->get_results( "SELECT id,country,visible FROM `" . WPSC_TABLE_CURRENCY_LIST . "` ORDER BY country ASC ", ARRAY_A );
65
  ?>
66
+ <tr>
67
+ <th scope="row">
68
+ <?php esc_html_e( 'Target Markets', 'wpsc' ); ?>
69
+ </th>
70
+ <td>
71
  <?php
72
  // check for the suhosin module
73
  if ( wpsc_is_suhosin_enabled() ) {
74
  echo "<em>" . __( "The Target Markets feature has been disabled because you have the Suhosin PHP extension installed on this server. If you need to use the Target Markets feature then disable the suhosin extension, if you can not do this, you will need to contact your hosting provider.", 'wpsc' ) . "</em>";
75
  } else {
76
+ ?>
77
  <span>
78
+ <?php printf( __( 'Select: <a href="%1$s" class="wpsc-select-all" title="All">All</a> <a href="%2$s" class="wpsc-select-none" title="None">None</a>' , 'wpsc') , add_query_arg( array( 'selected_all' => 'all' ) ), add_query_arg( array( 'selected_all' => 'none' ) ) ); ?>
79
  </span><br />
80
  <div id='wpsc-target-markets' class='ui-widget-content multiple-select'>
81
+ <?php foreach ( (array)$countrylist as $country ) : ?>
82
+ <?php if ( $country['visible'] == 1 ) : ?>
83
+ <input type='checkbox' id="countrylist2-<?php echo $country['id']; ?>" name='countrylist2[]' value='<?php echo $country['id']; ?>' checked='checked' />
84
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
85
+ <?php else : ?>
86
+ <input type='checkbox' id="countrylist2-<?php echo $country['id']; ?>" name='countrylist2[]' value='<?php echo $country['id']; ?>' />
87
+ <label for="countrylist2-<?php echo $country['id']; ?>"><?php esc_html_e( $country['country'] ); ?></label><br />
88
+ <?php endif; ?>
89
+ <?php endforeach; ?>
90
+ </div>
91
+
92
+ <p class='description'><?php esc_html_e( 'Select the markets you are selling products to.' , 'wpsc'); ?></p>
93
+ <?php
94
  }
95
+ ?>
96
+ </td>
97
+ </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
+ <?php
100
+ $stock_keeping_time = get_option( 'wpsc_stock_keeping_time', 1 );
101
+ $stock_keeping_interval = get_option( 'wpsc_stock_keeping_interval', 'day' );
102
+ ?>
103
+ <tr>
104
+ <th scope="row">
105
+ <label for="wpsc-stock-keeping-time"><?php esc_html_e( 'Keep stock in cart for', 'wpsc' ); ?></label>
106
+ </th>
107
  <td>
108
+ <input type="text" name="wpsc_options[wpsc_stock_keeping_time]" id="wpsc-stock-keeping-time" size="2" value="<?php echo esc_attr( $stock_keeping_time ); ?>" />
109
+ <select name="wpsc_options[wpsc_stock_keeping_interval]">
110
+ <option value="hour" <?php selected( 'hour', $stock_keeping_interval ); ?>><?php echo _n( 'hour', 'hours', $stock_keeping_time, 'wpsc' ); ?></option>
111
+ <option value="day" <?php selected( 'day', $stock_keeping_interval ); ?>><?php echo _n( 'day', 'days', $stock_keeping_time, 'wpsc' ) ?></option>
112
+ <option value="week" <?php selected( 'week', $stock_keeping_interval ); ?>><?php echo _n( 'week', 'weeks', $stock_keeping_time, 'wpsc' ) ?></option>
 
 
 
 
 
 
 
 
 
 
 
113
  </select>
114
+ <p class='description'><?php esc_html_e( "Set the amount of time items in a customer's cart are reserved. You can also specify decimal amounts such as '0.5 days' or '1.25 weeks'. Note that the minimum interval you can enter is 1 hour, i.e. you can't schedule it to run every 0.5 hour.", 'wpsc' ) ?></p>
115
  </td>
116
  </tr>
117
+
118
+ <?php
119
+ $hierarchical_category = get_option( 'product_category_hierarchical_url', 0 );
120
+ ?>
121
  <tr>
122
+ <th scope="row">
123
+ <?php _e( 'Use Hierarchical Product Category URL', 'wpsc' ); ?>
124
+ </th>
125
+ <td>
126
+ <label><input type="radio" <?php checked( $hierarchical_category, 1 ); ?> name="wpsc_options[product_category_hierarchical_url]" value="1" /> <?php _e( 'Yes', 'wpsc' ); ?></label>&nbsp;&nbsp;
127
+ <label><input type="radio" <?php checked( $hierarchical_category, 0 ); ?>name="wpsc_options[product_category_hierarchical_url]" value="0" /> <?php _e( 'No', 'wpsc' ); ?></label><br />
128
+ <p class='description'><?php _e( 'When Hierarchical Product Category URL is enabled, parent product categories are also included in the product URL.<br />For example: <code>http://example.com/products-page/parent-cat/sub-cat/product-name</code>', 'wpsc' ); ?></p>
129
+ </td>
130
+ </tr>
131
+ </table>
 
 
132
 
133
+ <h3 class="form_group"><?php esc_html_e( 'Currency Settings', 'wpsc' ); ?></h3>
134
+ <table class='wpsc_options form-table'>
135
+ <?php
136
+ $currency_data = $wpdb->get_results( "SELECT * FROM `" . WPSC_TABLE_CURRENCY_LIST . "` ORDER BY `country` ASC", ARRAY_A );
137
+ $currency_type = esc_attr( get_option( 'currency_type' ) );
138
+ ?>
139
+ <tr>
140
+ <th scope="row"><label for="wpsc_options_currency_type"><?php esc_html_e( 'Currency Type', 'wpsc' ); ?></label></th>
141
+ <td>
142
+ <select id="wpsc_options_currency_type" name='wpsc_options[currency_type]' onchange='getcurrency(this.options[this.selectedIndex].value);'>
143
+ <?php foreach ( $currency_data as $currency ) : ?>
144
+ <option value='<?php echo $currency['id']; ?>' <?php selected( $currency['id'], $currency_type ); ?>><?php esc_html_e( $currency['country'] ); ?> (<?php echo $currency['currency']; ?>)</option>
145
+ <?php endforeach; ?>
146
+ </select>
147
+ </td>
148
+ </tr>
149
+
150
+ <?php
151
+ $currency_data = $wpdb->get_row( "SELECT `symbol`,`symbol_html`,`code` FROM `" . WPSC_TABLE_CURRENCY_LIST . "` WHERE `id`='" . esc_attr( get_option( 'currency_type' ) ) . "' LIMIT 1", ARRAY_A );
152
+
153
+ if ( $currency_data['symbol'] != '' ) {
154
+ $currency_sign = esc_attr( $currency_data['symbol_html'] );
155
+ } else {
156
+ $currency_sign = esc_attr( $currency_data['code'] );
157
+ }
158
+
159
+ $currency_sign_location = esc_attr( get_option( 'currency_sign_location' ) );
160
+ $csl1 = "";
161
+ $csl2 = "";
162
+ $csl3 = "";
163
+ $csl4 = "";
164
+ switch ( $currency_sign_location ) {
165
+ case 1:
166
+ $csl1 = "checked='checked'";
167
+ break;
168
 
169
+ case 2:
170
+ $csl2 = "checked='checked'";
171
+ break;
172
 
173
+ case 3:
174
+ $csl3 = "checked='checked'";
175
+ break;
176
+
177
+ case 4:
178
+ $csl4 = "checked='checked'";
179
+ break;
180
+ }
181
+ ?>
182
+ <tr>
183
+ <th scope="row"><?php esc_html_e( 'Currency Sign Location', 'wpsc' ); ?></th>
184
+ <td>
185
+ <input type='radio' value='1' name='wpsc_options[currency_sign_location]' id='csl1' <?php echo $csl1; ?> />
186
+ <label for='csl1'><?php _ex( '100', 'Currency sign location - option 1', 'wpsc' ); ?><span id='cslchar1'><?php echo $currency_sign; ?></span></label> &nbsp;
187
+ <input type='radio' value='2' name='wpsc_options[currency_sign_location]' id='csl2' <?php echo $csl2; ?> />
188
+ <label for='csl2'><?php _ex( '100', 'Currency sign location - option 2', 'wpsc' ); ?> <span id='cslchar2'><?php echo $currency_sign; ?></span></label> &nbsp;
189
+ <input type='radio' value='3' name='wpsc_options[currency_sign_location]' id='csl3' <?php echo $csl3; ?> />
190
+ <label for='csl3'><span id='cslchar3'><?php echo $currency_sign; ?></span><?php _ex( '100', 'Currency sign location - option 3', 'wpsc' ); ?></label> &nbsp;
191
+ <input type='radio' value='4' name='wpsc_options[currency_sign_location]' id='csl4' <?php echo $csl4; ?> />
192
+ <label for='csl4'><span id='cslchar4'><?php echo $currency_sign; ?></span> <?php _ex( '100', 'Currency sign location - option 4', 'wpsc' ); ?></label>
193
+ </td>
194
+ </tr>
195
+ <tr>
196
+ <th scope="row"><?php esc_html_e( 'Thousands and decimal separators', 'wpsc' ); ?></th>
197
+ <td>
198
+ <label for="wpsc_options_wpsc_thousands_separator"><?php esc_html_e( 'Thousands separator', 'wpsc' ); ?></label>: <input name="wpsc_options[wpsc_thousands_separator]" id="wpsc_options_wpsc_thousands_separator" type="text" maxlength="1" size="1" value="<?php echo esc_attr( get_option( 'wpsc_thousands_separator' ) ); ?>" /><br />
199
+ <label for="wpsc_options_wpsc_decimal_separator"><?php esc_html_e( 'Decimal separator', 'wpsc' ); ?></label>: <input name="wpsc_options[wpsc_decimal_separator]" id="wpsc_options_wpsc_decimal_separator" type="text" maxlength="1" size="1" value="<?php echo esc_attr( get_option( 'wpsc_decimal_separator' ) ); ?>" /><br />
200
+ <?php esc_html_e( 'Preview:', 'wpsc' ); ?> 10<?php echo esc_attr( get_option( 'wpsc_thousands_separator' ) ); ?>000<?php echo esc_attr( get_option( 'wpsc_decimal_separator' ) ); ?>00
201
+ </td>
202
+ </tr>
203
+ </table>
204
  <?php
205
  }
206
+ } // end class
wpsc-admin/includes/settings-tabs/import.php CHANGED
@@ -38,13 +38,25 @@ class WPSC_Settings_Tab_Import extends WPSC_Settings_Tab {
38
  $this->reset_state();
39
  return;
40
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
- $first_row = @fgetcsv( $handle );
43
  $categories = get_terms( 'wpsc_product_category', 'hide_empty=0' );
44
 
45
  $this->display_data = array(
46
- 'columns' => $first_row,
47
- 'categories' => $categories,
48
  );
49
  }
50
 
@@ -68,6 +80,8 @@ class WPSC_Settings_Tab_Import extends WPSC_Settings_Tab {
68
  $column_map = array_flip( $_POST['value_name'] );
69
  extract( $column_map, EXTR_SKIP );
70
 
 
 
71
  while ( $row = @fgetcsv( $handle, $length, ',' ) ) {
72
  $product = array(
73
  'post_title' => isset( $row[$column_name] ) ? $row[$column_name] : '',
@@ -108,12 +122,15 @@ class WPSC_Settings_Tab_Import extends WPSC_Settings_Tab {
108
  // status needs to be set here because wpsc_sanitise_product_forms overwrites it :/
109
  $product['post_status'] = $_POST['post_status'];
110
  $product_id = wpsc_insert_product( $product );
111
- wp_set_object_terms( $product_id , array( (int)$_POST['category'] ) , 'wpsc_product_category' );
 
 
 
112
  }
113
 
114
  $this->reset_state();
115
  $this->completed = true;
116
- add_settings_error( 'wpsc-settings', 'settings_updated', __( 'CSV file imported.', 'wpsc' ), 'updated' );
117
  }
118
 
119
  public function callback_submit_options() {
@@ -137,73 +154,156 @@ class WPSC_Settings_Tab_Import extends WPSC_Settings_Tab {
137
  private function display_imported_columns() {
138
  extract( $this->display_data );
139
  ?>
140
- <p><?php esc_html_e( 'For each column, select the field it corresponds to in \'Belongs to\'. You can upload as many products as you like.', 'wpsc' ); ?></p>
141
- <div class='metabox-holder' style='width:90%'>
142
- <div style='width:100%;' class='postbox'>
143
- <h3 class='hndle'><?php esc_html_e( 'Product Status' , 'wpsc' ); ?></h3>
144
- <div class='inside'>
145
- <table>
146
- <tr>
147
- <td style='width:80%;'>
148
- <?php esc_html_e( 'Select if you would like to import your products in as Drafts or Publish them right away.' , 'wpsc' ); ?>
149
- <br />
150
- </td>
151
- <td>
152
- <select name='post_status'>
153
- <option value='publish'><?php esc_html_e( 'Publish', 'wpsc' ); ?></option>
154
- <option value='draft' ><?php esc_html_e( 'Draft' , 'wpsc' ); ?></option>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  </select>
156
- </td>
157
- </tr>
158
- </table>
159
- </div>
160
- </div>
161
- <?php foreach ( $columns as $key => $datum ): ?>
162
- <div style='width:100%;' class='postbox'>
163
- <h3 class='hndle'><?php printf( __('Column (%s)', 'wpsc' ), ( $key + 1 ) ); ?></h3>
164
- <div class='inside'>
165
- <table>
166
- <tr>
167
- <td style='width:80%;'>
168
- <?php echo $datum; ?>
169
- <br />
170
- </td>
171
- <td>
172
- <select name='value_name[<?php echo $key; ?>]'>
173
- <option <?php selected( $key, 0 ); ?> value='column_name' ><?php esc_html_e( 'Product Name' , 'wpsc' ); ?></option>
174
- <option <?php selected( $key, 1 ); ?> value='column_description' ><?php esc_html_e( 'Description' , 'wpsc' ); ?></option>
175
- <option <?php selected( $key, 2 ); ?> value='column_additional_description'><?php esc_html_e( 'Additional Description', 'wpsc' ); ?></option>
176
- <option <?php selected( $key, 3 ); ?> value='column_price' ><?php esc_html_e( 'Price' , 'wpsc' ); ?></option>
177
- <option <?php selected( $key, 4 ); ?> value='column_sku' ><?php esc_html_e( 'SKU' , 'wpsc' ); ?></option>
178
- <option <?php selected( $key, 5 ); ?> value='column_weight' ><?php esc_html_e( 'Weight' , 'wpsc' ); ?></option>
179
- <option <?php selected( $key, 6 ); ?> value='column_weight_unit' ><?php esc_html_e( 'Weight Unit' , 'wpsc' ); ?></option>
180
- <option <?php selected( $key, 7 ); ?> value='column_quantity' ><?php esc_html_e( 'Stock Quantity' , 'wpsc' ); ?></option>
181
- <option <?php selected( $key, 8 ); ?> value='column_quantity_limited' ><?php esc_html_e( 'Stock Quantity Limit' , 'wpsc' ); ?></option>
182
- </select>
183
- </td>
184
- </tr>
185
- </table>
186
- </div>
187
- </div>
188
- <?php endforeach; ?>
189
- <label for='category'><?php esc_html_e( 'Please select a category you would like to place all products from this CSV into' , 'wpsc' ); ?>:</label>
190
- <select id='category' name='category'>
191
- <?php foreach ( $categories as $category ): ?>
192
- <option value="<?php echo $category->term_id; ?>"><?php echo esc_html( $category->name ); ?></option>
193
  <?php endforeach; ?>
194
- </select>
195
- <input type="hidden" name="step" value="3" />
196
- <input type='submit' value='<?php echo esc_html_x( 'Continue', 'import csv', 'wpsc' ); ?>' class='button-primary'>
197
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  <?php
199
  }
200
 
 
 
 
 
 
 
 
201
  private function display_default() {
202
  extract( $this->display_data );
203
  ?>
204
- <?php _e( '<p>You can import your products from a comma delimited text file.</p><p>An example of a csv import file would look like this: </p><p>Description, Additional Description, Product Name, Price, SKU, weight, weight unit, stock quantity, is limited quantity</p>', 'wpsc' ); ?>
205
- <input type='file' name='csv_file' />
 
 
 
 
 
 
 
 
 
 
206
  <?php submit_button( esc_html_x( 'Upload', 'import csv', 'wpsc' ) ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  <?php
208
  }
209
 
38
  $this->reset_state();
39
  return;
40
  }
41
+ $rows = array();
42
+ while ( count($rows) < 5 && ( $data = fgetcsv($handle) ) !== FALSE ) {
43
+ array_push( $rows, $data );
44
+ }
45
+
46
+ $sample_row_data = array();
47
+ foreach ( $rows as $row => $columns ) {
48
+ foreach ( $columns as $column => $data ) {
49
+ if ( ! isset( $sample_row_data[$column] ) )
50
+ $sample_row_data[$column] = array();
51
+ array_push( $sample_row_data[$column], $data );
52
+ }
53
+ }
54
 
 
55
  $categories = get_terms( 'wpsc_product_category', 'hide_empty=0' );
56
 
57
  $this->display_data = array(
58
+ 'sample_row_data' => $sample_row_data,
59
+ 'categories' => $categories,
60
  );
61
  }
62
 
80
  $column_map = array_flip( $_POST['value_name'] );
81
  extract( $column_map, EXTR_SKIP );
82
 
83
+ $record_count = 0;
84
+
85
  while ( $row = @fgetcsv( $handle, $length, ',' ) ) {
86
  $product = array(
87
  'post_title' => isset( $row[$column_name] ) ? $row[$column_name] : '',
122
  // status needs to be set here because wpsc_sanitise_product_forms overwrites it :/
123
  $product['post_status'] = $_POST['post_status'];
124
  $product_id = wpsc_insert_product( $product );
125
+ if ( (int)$_POST['category'] > 0 ) {
126
+ wp_set_object_terms( $product_id , array( (int)$_POST['category'] ) , 'wpsc_product_category' );
127
+ }
128
+ $record_count += 1;
129
  }
130
 
131
  $this->reset_state();
132
  $this->completed = true;
133
+ add_settings_error( 'wpsc-settings', 'settings_updated', sprintf( __( 'CSV file successfully processed. %s record(s) imported.', 'wpsc' ), $record_count ), 'updated' );
134
  }
135
 
136
  public function callback_submit_options() {
154
  private function display_imported_columns() {
155
  extract( $this->display_data );
156
  ?>
157
+ <h3 class='hndle'><?php esc_html_e( 'Assign CSV Columns to Product Fields', 'wpsc'); ?></h3>
158
+ <p><?php esc_html_e( 'For each column, select the field it corresponds to in \'Product Field\'.', 'wpsc' ); ?></p>
159
+ <p><?php esc_html_e( 'Note: In this view we only show sample data from the first 5 records. All records in the uploaded import file will actually be imported.', 'wpsc' ); ?></p>
160
+ <table class='wp-list-table widefat plugins' id="wpsc_imported_columns">
161
+ <thead>
162
+ <tr>
163
+ <th scope="col" class="manage-column"><?php _e( 'Column', 'wpsc' ); ?></th>
164
+ <th scope="col" class="manage-column"><?php _e( 'Sample Data from Column', 'wpsc' ); ?></th>
165
+ <th scope="col" class="manage-column"><?php _e( 'Product Field', 'wpsc' ); ?></th>
166
+ </tr>
167
+ </thead>
168
+ <tbody>
169
+ <?php foreach ( $sample_row_data as $key => $sample_data ): ?>
170
+ <tr>
171
+ <td>
172
+ <p><?php printf( __('Column %s', 'wpsc' ), $this->num_to_alphacolumn( $key ) ); ?></p>
173
+ </td>
174
+ <td>
175
+ <ol>
176
+ <?php foreach ($sample_data as $datum) : ?>
177
+ <li>
178
+ <?php if ( $datum != "" ): ?>
179
+ <code><?php echo esc_html( $datum ); ?></code>
180
+ <?php else: ?>
181
+ <?php _e( '<em class="empty">empty</em>', 'wpsc' ); ?>
182
+ <?php endif; ?>
183
+ </li>
184
+ <?php endforeach; ?>
185
+ </ol>
186
+ </td>
187
+ <td>
188
+ <p>
189
+ <select name='value_name[<?php echo $key; ?>]'>
190
+ <option <?php selected( $key, 0 ); ?> value='column_name' ><?php esc_html_e( 'Product Name' , 'wpsc' ); ?></option>
191
+ <option <?php selected( $key, 1 ); ?> value='column_description' ><?php esc_html_e( 'Description' , 'wpsc' ); ?></option>
192
+ <option <?php selected( $key, 2 ); ?> value='column_additional_description'><?php esc_html_e( 'Additional Description', 'wpsc' ); ?></option>
193
+ <option <?php selected( $key, 3 ); ?> value='column_price' ><?php esc_html_e( 'Price' , 'wpsc' ); ?></option>
194
+ <option <?php selected( $key, 4 ); ?> value='column_sku' ><?php esc_html_e( 'SKU' , 'wpsc' ); ?></option>
195
+ <option <?php selected( $key, 5 ); ?> value='column_weight' ><?php esc_html_e( 'Weight' , 'wpsc' ); ?></option>
196
+ <option <?php selected( $key, 6 ); ?> value='column_weight_unit' ><?php esc_html_e( 'Weight Unit' , 'wpsc' ); ?></option>
197
+ <option <?php selected( $key, 7 ); ?> value='column_quantity' ><?php esc_html_e( 'Stock Quantity' , 'wpsc' ); ?></option>
198
+ <option <?php selected( $key, 8 ); ?> value='column_quantity_limited' ><?php esc_html_e( 'Stock Quantity Limit' , 'wpsc' ); ?></option>
199
  </select>
200
+ </p>
201
+ </td>
202
+ </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  <?php endforeach; ?>
204
+ </tbody>
205
+ </table>
206
+ <h3><?php esc_html_e( 'Import Options', 'wpsc' ); ?></h3>
207
+ <table class='form-table'>
208
+ <tr>
209
+ <th>
210
+ <label for='post_status'><?php esc_html_e( 'Product Status' , 'wpsc' ); ?>
211
+ </th>
212
+ <td>
213
+ <select name='post_status' id='post_status'>
214
+ <option value='publish'><?php esc_html_e( 'Publish', 'wpsc' ); ?></option>
215
+ <option value='draft' ><?php esc_html_e( 'Draft' , 'wpsc' ); ?></option>
216
+ </select>
217
+ <p class="description">
218
+ <?php esc_html_e( 'Set your imported products as drafts, or publish them right away.' , 'wpsc' ); ?>
219
+ </p>
220
+ </td>
221
+ </tr>
222
+ <tr>
223
+ <th><label for="category"><?php esc_html_e( 'Import to Category', 'wpsc' ); ?></label></th>
224
+ <td>
225
+ <select id='category' name='category'>
226
+ <option value=""><?php esc_html_e( "No Category", 'wpsc' ); ?></option>
227
+ <?php foreach ( $categories as $category ): ?>
228
+ <option value="<?php echo $category->term_id; ?>"><?php echo esc_html( $category->name ); ?></option>
229
+ <?php endforeach; ?>
230
+ </select>
231
+ <p class="description">
232
+ <?php esc_html_e( 'Products imported from this CSV file will be placed in the selected category.', 'wpsc' ); ?></p>
233
+ </p>
234
+ </td>
235
+ </tr>
236
+ </table>
237
+ <input type="hidden" name="step" value="3" />
238
+ <input type='submit' value='<?php echo esc_html_x( 'Import Products', 'import csv', 'wpsc' ); ?>' class='button-primary'>
239
+
240
  <?php
241
  }
242
 
243
+ private function num_to_alphacolumn($n) {
244
+ // from http://stackoverflow.com/questions/3302857/algorithm-to-get-the-excel-like-column-name-of-a-number
245
+ for( $r = ""; $n >= 0; $n = intval( $n / 26 ) - 1 )
246
+ $r = chr( $n % 26 + 0x41) . $r;
247
+ return $r;
248
+ }
249
+
250
  private function display_default() {
251
  extract( $this->display_data );
252
  ?>
253
+ <h3><?php _e( 'Import Products', 'wpsc' ); ?></h3>
254
+ <p><?php _e( 'You can import your products from a <a href="http://en.wikipedia.org/wiki/Comma-separated_values"><abbr title="Comma-separated values">CSV</abbr> (Comma-separated values) file</a>, exportable from most spread-sheet programs or other software.</p>', 'wpsc' ); ?></p>
255
+
256
+ <h4><?php _e( 'Import New Products from CSV', 'wpsc' ); ?></h4>
257
+ <table class='form-table'>
258
+ <tr>
259
+ <th><label for='wpsc_csv_file'><?php _e( 'CSV File', 'wpsc' ); ?><label></th>
260
+ <td>
261
+ <input type='file' name='csv_file' id='wpsc_csv_file' />
262
+ </td>
263
+ </tr>
264
+ </table>
265
  <?php submit_button( esc_html_x( 'Upload', 'import csv', 'wpsc' ) ); ?>
266
+
267
+ <h4><?php _e( 'Useful Information', 'wpsc' ); ?></h4>
268
+ <table class='form-table'>
269
+ <tr>
270
+ <th><?php echo _e( 'Supported Fields', 'wpsc' ); ?></th>
271
+ <td>
272
+ <?php _e( 'Columns supported are, in their default order:', 'wpsc'); ?><br />
273
+ <code>
274
+ <?php _e( 'Product Name, Description, Additional Description, Price, SKU, Weight, Weight Unit, Stock Quantity, Stock Quantity Limited', 'wpsc' ); ?>
275
+ </code>
276
+ </td>
277
+ </tr>
278
+ <tr>
279
+ <th><?php _e( 'Understood Weight Units', 'wpsc' ); ?></th>
280
+ <td>
281
+ <?php _e( 'Metric', 'wpsc' ); ?>: <code>kilogram</code>,<code>kilograms</code>,<code>kg</code>,<code>kgs</code>,<code>gram</code>,<code>grams</code>,<code>g</code>,<code>gs</code><br />
282
+ <?php _e( 'Imperial', 'wpsc' ); ?>: <code>ounce</code>,<code>once</code>,<code>ounces</code>,<code>oz</code>,<code>pound</code>,<code>pounds</code>,<code>lb</code>,<code>lbs</code>
283
+ </td>
284
+ </tr>
285
+ <tr>
286
+ <th><?php _e( 'Stock Fields', 'wpsc' ); ?></th>
287
+ <td>
288
+ <?php _e( '<code>Stock Quantity</code> values are used only when <code>Stock Quantity Limited</code> is blank or <code>""</code>.', 'wpsc' ); ?>
289
+ </td>
290
+ </tr>
291
+ <tr>
292
+ <th><?php _e( 'HTML', 'wpsc' ); ?></th>
293
+ <td>
294
+ <?php _e( 'Supported in <code>Description</code> and <code>Additional Description</code>. Be sure you "quote" the whole description, and slash-escape \"quotes\" inside the description itself.', 'wpsc' ); ?>
295
+ </tr>
296
+ <tr>
297
+ <th><?php _e( 'Example CSV File'); ?></th>
298
+ <td>
299
+ <ol>
300
+ <li><code><?php esc_html_e( 'Banana, The Yellow Fruit, Contains Potassium, 0.67, "BANANA", 150, "g", 0, ""', 'wpsc' ); ?></code></li>
301
+ <li><code><?php esc_html_e( '"Apple, red", "Red, round, juicy. Isn\'t an <a href=\"http://example.com\">orange</a>.", "Red Delicious", 0.25, "RED_DELICIOUS", 5, "oz", 10, true', 'wpsc' ); ?></code></li>
302
+ </ol>
303
+ </td>
304
+ </tr>
305
+ </table>
306
+
307
  <?php
308
  }
309
 
wpsc-admin/includes/settings-tabs/marketing.php CHANGED
@@ -151,7 +151,7 @@ class WPSC_Settings_Tab_Marketing extends WPSC_Settings_Tab {
151
  <?php _e( 'Enable', 'wpsc' ); ?>
152
  </th>
153
  <td>
154
- <label><?php echo get_option( 'wpsc_ga_disable_tracking' ); ?>
155
  <input value='1' type='hidden' name='wpsc_ga_disable_tracking' />
156
  <input value='0' <?php checked( '0', get_option( 'wpsc_ga_disable_tracking' ) ); ?> type='checkbox' name='wpsc_ga_disable_tracking' />
157
  <?php _e( 'Enable Google Analytics tracking', 'wpsc' ); ?>
151
  <?php _e( 'Enable', 'wpsc' ); ?>
152
  </th>
153
  <td>
154
+ <label>
155
  <input value='1' type='hidden' name='wpsc_ga_disable_tracking' />
156
  <input value='0' <?php checked( '0', get_option( 'wpsc_ga_disable_tracking' ) ); ?> type='checkbox' name='wpsc_ga_disable_tracking' />
157
  <?php _e( 'Enable Google Analytics tracking', 'wpsc' ); ?>
wpsc-admin/includes/settings-tabs/presentation.php CHANGED
@@ -179,8 +179,11 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
179
  public function display() {
180
  ?>
181
  <div class='product_and_button_settings'>
 
 
 
182
  <h3 class="form_group"><?php esc_html_e( 'Button Settings', 'wpsc' ); ?></h3>
183
- <table class='wpsc_options form-table'>
184
  <tr>
185
  <th scope="row"><?php esc_html_e( 'Button Type', 'wpsc' ); ?>:</th>
186
  <td>
@@ -375,9 +378,6 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
375
  </table>
376
  </div>
377
 
378
- <?php $this->theme_metabox(); ?>
379
-
380
- <div style='clear:both;'></div>
381
 
382
  <h3 class="form_group"><?php esc_html_e( 'Product Page Settings', 'wpsc' ); ?></h3>
383
  <table class='wpsc_options form-table'>
@@ -470,7 +470,7 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
470
  <tr id="wpsc-grid-settings">
471
  <th scope="row"><?php esc_html_e( 'Grid view settings:', 'wpsc' ) ?></th>
472
  <td>
473
- <input type='text' name='wpsc_options[grid_number_per_row]' id='grid_number_per_row' size='1' value='<?php esc_attr_e( get_option( 'grid_number_per_row' ) ); ?>' />
474
  <label for='grid_number_per_row'><?php esc_html_e( 'Products Per Row', 'wpsc' ); ?></label><br />
475
 
476
  <input type='hidden' value='0' name='wpsc_options[show_images_only]' />
@@ -606,7 +606,7 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
606
  break;
607
  }
608
  ?>
609
- <input type='radio' value='0' name='wpsc_options[catsprods_display_type]' id='catsprods_display_type1' <?php echo $catsprods_display_type1; ?> /> <label for='catsprods_display_type1'><?php _e( 'Product Groups Only (All products displayed)', 'wpsc' ); ?></label> &nbsp;
610
  <input type='radio' value='1' name='wpsc_options[catsprods_display_type]' id='catsprods_display_type2' <?php echo $catsprods_display_type2; ?> /> <label for='catsprods_display_type2'><?php _e( 'Sliding Product Groups (1 product per page)', 'wpsc' ); ?></label>
611
  </td>
612
  </tr>
@@ -959,9 +959,12 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
959
  <tr>
960
  <th scope="row"><?php esc_html_e( 'Default Product Thumbnail Size', 'wpsc' ); ?>:</th>
961
  <td>
962
- <?php esc_html_e( 'Width', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[product_image_width]' class='wpsc_prod_thumb_option' value='<?php esc_attr_e( get_option( 'product_image_width' ) ); ?>' />
963
- <?php esc_html_e( 'Height', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[product_image_height]' class='wpsc_prod_thumb_option' value='<?php esc_attr_e( get_option( 'product_image_height' ) ); ?>' />
964
-
 
 
 
965
  </td>
966
  </tr>
967
  <tr>
@@ -969,17 +972,25 @@ class WPSC_Settings_Tab_Presentation extends WPSC_Settings_Tab {
969
  <?php esc_html_e( 'Default Product Category Thumbnail Size', 'wpsc' ); ?>:
970
  </th>
971
  <td>
972
- <?php esc_html_e( 'Width', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[category_image_width]' value='<?php esc_attr_e( get_option( 'category_image_width' ) ); ?>' />
973
- <?php esc_html_e( 'Height', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[category_image_height]' value='<?php esc_attr_e( get_option( 'category_image_height' ) ); ?>' />
 
 
 
 
974
  </td>
975
  </tr>
976
  <tr>
977
  <th scope="row">
978
- <?php esc_html_e( 'Single Product Image Size', 'wpsc' ); ?>:
979
  </th>
980
  <td>
981
- <?php esc_html_e( 'Width', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[single_view_image_width]' value='<?php esc_attr_e( get_option( 'single_view_image_width' ) ); ?>' />
982
- <?php esc_html_e( 'Height', 'wpsc' ); ?>:<input type='text' size='6' name='wpsc_options[single_view_image_height]' value='<?php esc_attr_e( get_option( 'single_view_image_height' ) ); ?>' />
 
 
 
 
983
  </td>
984
  </tr>
985
  <tr>
179
  public function display() {
180
  ?>
181
  <div class='product_and_button_settings'>
182
+
183
+ <?php $this->theme_metabox(); ?>
184
+
185
  <h3 class="form_group"><?php esc_html_e( 'Button Settings', 'wpsc' ); ?></h3>
186
+ <table class='wpsc_options form-table' style="width:550px">
187
  <tr>
188
  <th scope="row"><?php esc_html_e( 'Button Type', 'wpsc' ); ?>:</th>
189
  <td>
378
  </table>
379
  </div>
380
 
 
 
 
381
 
382
  <h3 class="form_group"><?php esc_html_e( 'Product Page Settings', 'wpsc' ); ?></h3>
383
  <table class='wpsc_options form-table'>
470
  <tr id="wpsc-grid-settings">
471
  <th scope="row"><?php esc_html_e( 'Grid view settings:', 'wpsc' ) ?></th>
472
  <td>
473
+ <input type='number' name='wpsc_options[grid_number_per_row]' id='grid_number_per_row' size='2' value='<?php esc_attr_e( get_option( 'grid_number_per_row' ) ); ?>' />
474
  <label for='grid_number_per_row'><?php esc_html_e( 'Products Per Row', 'wpsc' ); ?></label><br />
475
 
476
  <input type='hidden' value='0' name='wpsc_options[show_images_only]' />
606
  break;
607
  }
608
  ?>
609
+ <input type='radio' value='0' name='wpsc_options[catsprods_display_type]' id='catsprods_display_type1' <?php echo $catsprods_display_type1; ?> /> <label for='catsprods_display_type1'><?php _e( 'Product Groups Only (All products displayed)', 'wpsc' ); ?></label><br/>
610
  <input type='radio' value='1' name='wpsc_options[catsprods_display_type]' id='catsprods_display_type2' <?php echo $catsprods_display_type2; ?> /> <label for='catsprods_display_type2'><?php _e( 'Sliding Product Groups (1 product per page)', 'wpsc' ); ?></label>
611
  </td>
612
  </tr>
959
  <tr>
960
  <th scope="row"><?php esc_html_e( 'Default Product Thumbnail Size', 'wpsc' ); ?>:</th>
961
  <td>
962
+ <fieldset class="wpsc-width-height-fields">
963
+ <label for="image_width"><?php esc_html_e( 'Width', 'wpsc' ); ?></label>
964
+ <input name="wpsc_options[product_image_width]" type="number" step="1" min="0" id="product_image_width" value="<?php esc_attr_e( get_option( 'product_image_width' ) ); ?>" class="small-text">
965
+ <label for="large_size_h"><?php esc_html_e( 'Height', 'wpsc' ); ?></label>
966
+ <input name="wpsc_options[product_image_height]" type="number" step="1" min="0" id="product_image_height" value="<?php esc_attr_e( get_option( 'product_image_height' ) ); ?>" class="small-text">
967
+ </fieldset>
968
  </td>
969
  </tr>
970
  <tr>
972
  <?php esc_html_e( 'Default Product Category Thumbnail Size', 'wpsc' ); ?>:
973
  </th>
974
  <td>
975
+ <fieldset class="wpsc-width-height-fields">
976
+ <label for="image_width"><?php esc_html_e( 'Width', 'wpsc' ); ?></label>
977
+ <input name="wpsc_options[category_image_width]" type="number" step="1" min="0" id="category_image_width" value="<?php esc_attr_e( get_option( 'category_image_width' ) ); ?>" class="small-text">
978
+ <label for="large_size_h"><?php esc_html_e( 'Height', 'wpsc' ); ?></label>
979
+ <input name="wpsc_options[category_image_height]" type="number" step="1" min="0" id="category_image_height" value="<?php esc_attr_e( get_option( 'category_image_height' ) ); ?>" class="small-text">
980
+ </fieldset>
981
  </td>
982
  </tr>
983
  <tr>
984
  <th scope="row">
985
+ <?php esc_html_e( 'Single Product Image Size', 'wpsc' ); ?>:
986
  </th>
987
  <td>
988
+ <fieldset class="wpsc-width-height-fields">
989
+ <label for="image_width"><?php esc_html_e( 'Width', 'wpsc' ); ?></label>
990
+ <input name="wpsc_options[single_view_image_width]" type="number" step="1" min="0" id="single_view_image_width" value="<?php esc_attr_e( get_option( 'single_view_image_width' ) ); ?>" class="small-text">
991
+ <label for="large_size_h"><?php esc_html_e( 'Height', 'wpsc' ); ?></label>
992
+ <input name="wpsc_options[single_view_image_height]" type="number" step="1" min="0" id="single_view_image_height" value="<?php esc_attr_e( get_option( 'single_view_image_height' ) ); ?>" class="small-text">
993
+ </fieldset>
994
  </td>
995
  </tr>
996
  <tr>
wpsc-admin/includes/settings-tabs/shipping.php CHANGED
@@ -46,14 +46,14 @@ class WPSC_Settings_Tab_Shipping extends WPSC_Settings_Tab {
46
 
47
  $shipadd = 0;
48
  foreach ( $wpsc_shipping_modules as $shipping ) {
49
- foreach ( (array)$_POST['custom_shipping_options'] as $shippingoption ) {
50
  if ( $shipping->internal_name == $shippingoption ) {
51
  $shipadd++;
52
  }
53
  }
54
  }
55
 
56
- if ( ! get_option( 'do_not_use_shipping' ) && ! get_option( 'custom_shipping_options' ) ) {
57
  update_option( 'do_not_use_shipping', '1' );
58
  return array( 'shipping_disabled' => 1 );
59
  } else {
@@ -61,37 +61,37 @@ class WPSC_Settings_Tab_Shipping extends WPSC_Settings_Tab {
61
  }
62
  }
63
 
64
- public function display_shipping_module_settings_form() {
65
  global $wpsc_shipping_modules;
66
- $classes = array( 'wpsc-module-settings' );
67
- $selected_module_id = (string) get_user_option( 'wpsc_settings_selected_shipping_module', get_current_user_id() );
 
 
68
  $found_selected_module = array_key_exists( $selected_module_id, $wpsc_shipping_modules );
 
69
  if ( $found_selected_module ) {
70
  $selected_module = $wpsc_shipping_modules[$selected_module_id];
71
  $title = $selected_module->name;
72
  $content = apply_filters( 'wpsc_shipping_module_settings_form', $selected_module->getForm(), $selected_module );
73
- $classes[] = 'wpsc-shipping-module-settings-' . $selected_module_id;
74
  } else {
75
  $title = __( 'Edit Shipping Module Settings', 'wpsc' );
76
  $content = __( 'To configure a shipping module select one on the left.', 'wpsc' );
77
  }
78
- $classes = implode( ' ', $classes );
79
  ?>
80
- <td id="wpsc-shipping-module-settings" class="<?php echo esc_attr( $classes ); ?>" rowspan='2'>
81
- <div class='postbox'>
82
- <h3 class='hndle'><?php echo esc_html( $title ); ?></h3>
83
- <div class='inside'>
84
- <table class='form-table'>
85
- <?php echo $content; ?>
86
- </table>
87
- <?php if ( $found_selected_module ): ?>
88
- <p class="submit">
89
- <input type="submit" value="<?php _e( 'Update &raquo;', 'wpsc' ); ?>" />
90
- </p>
91
- <?php endif; ?>
92
- </div>
93
- </div>
94
- </td>
95
  <?php
96
  }
97
 
@@ -114,218 +114,229 @@ class WPSC_Settings_Tab_Shipping extends WPSC_Settings_Tab {
114
  if ( empty( $module ) )
115
  continue;
116
 
117
- if ( isset( $module->is_external ) && $module->is_external )
118
  $external_shipping_modules[$key] = $module;
119
- else
120
  $internal_shipping_modules[$key] = $module;
 
121
  }
122
 
123
- $currency_data = $wpdb->get_row( $wpdb->prepare( "SELECT `symbol`,`symbol_html`,`code` FROM `" . WPSC_TABLE_CURRENCY_LIST . "` WHERE `id` = %d LIMIT 1", get_option( 'currency_type' ) ), ARRAY_A );
124
- if ( $currency_data['symbol'] != '' ) {
125
- $currency_sign = $currency_data['symbol_html'];
126
- } else {
127
- $currency_sign = $currency_data['code'];
128
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  //get shipping options that are selected
130
  $selected_shippings = get_option( 'custom_shipping_options' );
131
- ?>
132
- <div class="metabox-holder">
133
- <input type='hidden' name='shipping_submits' value='true' />
134
- <?php wp_nonce_field( 'update-options', 'wpsc-update-options' ); ?>
135
- <input type='hidden' name='wpsc_admin_action' value='submit_options' />
136
 
137
- <?php
 
 
 
138
 
139
- if ( get_option( 'custom_gateway' ) == 1 ) {
140
- $custom_gateway_hide = "style='display:block;'";
141
- $custom_gateway1 = 'checked="checked"';
142
- } else {
143
- $custom_gateway_hide = "style='display:none;'";
144
- $custom_gateway2 = 'checked="checked"';
145
- }
146
- /* wpsc_setting_page_update_notification displays the wordpress styled notifications */
147
- wpsc_settings_page_update_notification(); ?>
148
- <div class='postbox'>
149
- <h3 class='hndle'><?php esc_html_e( 'General Settings', 'wpsc' ); ?></h3>
150
- <div class='inside'>
151
-
152
- <table class='wpsc_options form-table'>
153
- <tr>
154
- <th scope="row">
155
- <?php _e( 'Use Shipping', 'wpsc' ); ?>:
156
- </th>
157
- <td>
158
- <?php
159
- $do_not_use_shipping = get_option( 'do_not_use_shipping' );
160
- $do_not_use_shipping1 = "";
161
- $do_not_use_shipping2 = "";
162
- if( $do_not_use_shipping )
163
- $do_not_use_shipping1 = "checked ='checked'";
164
- else
165
- $do_not_use_shipping2 = "checked ='checked'";
166
- ?>
167
- <input type='radio' value='0' name='wpsc_options[do_not_use_shipping]' id='do_not_use_shipping2' <?php echo $do_not_use_shipping2; ?> /> <label for='do_not_use_shipping2'><?php _e( 'Yes', 'wpsc' ); ?></label>&nbsp;
168
- <input type='radio' value='1' name='wpsc_options[do_not_use_shipping]' id='do_not_use_shipping1' <?php echo $do_not_use_shipping1; ?> /> <label for='do_not_use_shipping1'><?php _e( 'No', 'wpsc' ); ?></label><br />
169
- <?php esc_html_e( 'If you are only selling digital downloads, you should select no to disable the shipping on your site.', 'wpsc' ); ?>
170
- </td>
171
- </tr>
172
-
173
- <tr>
174
- <th><?php esc_html_e( 'Base City:', 'wpsc' ); ?></th>
175
- <td>
176
- <input type='text' name='wpsc_options[base_city]' value='<?php esc_attr_e( get_option( 'base_city' ) ); ?>' />
177
- <br /><?php esc_html_e( 'Please provide for more accurate rates', 'wpsc' ); ?>
178
- </td>
179
- </tr>
180
- <tr>
181
- <th><?php esc_html_e( 'Base Zipcode/Postcode:', 'wpsc' ); ?></th>
182
- <td>
183
- <input type='text' name='wpsc_options[base_zipcode]' value='<?php esc_attr_e( get_option( 'base_zipcode' ) ); ?>' />
184
- <br /><?php esc_html_e( 'If you are based in America then you need to set your own Zipcode for UPS and USPS to work. This should be the Zipcode for your Base of Operations.', 'wpsc' ); ?>
185
- </td>
186
- </tr>
187
- <tr>
188
- <th scope="row">
189
- <?php _e( 'Shipwire Settings', 'wpsc' ); ?><span style='color: red;'></span> :
190
- </th>
191
- <?php
192
- switch ( get_option( 'shipwire' ) ) {
193
- case 1:
194
- $shipwire_settings = 'style=\'display: block;\'';
195
- break;
196
-
197
- case 0:
198
- default:
199
- $shipwire_settings = '';
200
- break;
201
- }
202
- ?>
203
- <td>
204
- <input type='radio' onclick='jQuery("#wpsc_shipwire_setting").show()' value='1' name='wpsc_options[shipwire]' id='shipwire1' <?php checked( '1', get_option( 'shipwire' ) ); ?> /> <label for='shipwire1'><?php _e( 'Yes', 'wpsc' ); ?></label> &nbsp;
205
- <input type='radio' onclick='jQuery("#wpsc_shipwire_setting").hide()' value='0' name='wpsc_options[shipwire]' id='shipwire2' <?php checked( '0', get_option( 'shipwire' ) ); ?> /> <label for='shipwire2'><?php _e( 'No', 'wpsc' ); ?></label>
206
- <div id='wpsc_shipwire_setting' <?php echo $shipwire_settings; ?>>
207
- <table>
208
- <tr><td><?php esc_html_e( 'Shipwire Email', 'wpsc' ); ?> :</td><td> <input type="text" name='wpsc_options[shipwireemail]' value="<?php esc_attr_e( get_option( 'shipwireemail' ) ); ?>" /></td></tr>
209
- <tr><td><?php esc_html_e( 'Shipwire Password', 'wpsc' ); ?> :</td><td><input type="text" name='wpsc_options[shipwirepassword]' value="<?php esc_attr_e( get_option( 'shipwirepassword' ) ); ?>" /></td></tr>
210
- <tr><td>
211
- <a class="shipwire_sync button"><?php esc_html_e( 'Update Tracking and Inventory', 'wpsc' ); ?></a>
212
- <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
213
- </td></tr>
214
- </table>
215
- </div>
216
- </td>
217
- </tr>
218
- <tr>
219
- <th scope="row">
220
- <?php _e( 'Enable Free Shipping Discount', 'wpsc' ); ?>
221
- </th>
222
- <td>
223
- <?php
224
- if ( get_option( 'shipping_discount' ) == 1 ) {
225
- $selected2 = '';
226
- $selected1 = 'checked="checked"';
227
- $shipping_discount_settings = 'style=\'display: block;\'';
228
- } else {
229
- $selected2 = 'checked="checked"';
230
- $selected1 = '';
231
- $shipping_discount_settings = '';
232
- }
233
- ?>
234
- <input type='radio' onclick='jQuery("#shipping_discount_value").show()' value='1' name='wpsc_options[shipping_discount]' id='shipping_discount1' <?php echo $selected1; ?> /> <label for='shipping_discount1'><?php _e( 'Yes', 'wpsc' ); ?></label> &nbsp;
235
- <input type='radio' onclick='jQuery("#shipping_discount_value").hide()' value='0' name='wpsc_options[shipping_discount]' id='shipping_discount2' <?php echo $selected2; ?> /> <label for='shipping_discount2'><?php _e( 'No', 'wpsc' ); ?></label>
236
-
237
- </td>
238
- </tr>
239
- <tr>
240
- <td>&nbsp;</td>
241
- <td colspan="2">
242
- <?php
243
- $value = esc_attr( get_option( 'shipping_discount_value' ) );
244
- ?>
245
- <div <?php echo $shipping_discount_settings; ?> id='shipping_discount_value'>
246
-
247
- <?php printf( __( 'Sales over or equal to: %1$s<input type="text" size="6" name="wpsc_options[shipping_discount_value]" value="%2$s" id="shipping_discount_value" /> will receive free shipping.', 'wpsc' ), $currency_sign, $value ); ?>
248
- </div>
249
- </td>
250
- </tr>
251
- </table>
252
- </div>
253
- </div>
254
- <table id='wpsc-shipping-module-options' class='wpsc-edit-module-options'>
255
- <tr>
256
- <td class='select_gateway'>
257
- <a name="gateway_options"></a>
258
- <div class='postbox'>
259
- <h3 class='hndle'><?php _e( 'Shipping Modules', 'wpsc' ) ?></h3>
260
- <div class='inside'>
261
-
262
- <p>
263
- <?php _e( 'To enable shipping in WP e-Commerce you must select which shipping methods you want to enable on your site.<br /> If you want to use fixed-price shipping options like "Pickup - $0, Overnight - $10, Same day - $20, etc." you can download a WordPress plugin from plugins directory for <a href="http://wordpress.org/extend/plugins/wp-e-commerce-fixed-rate-shipping/">Simple shipping</a>. It will appear in the list as "Fixed rate".', 'wpsc' ); ?>
264
- </p>
265
- <br />
266
- <p>
267
- <strong><?php _e( 'Internal Shipping Calculators', 'wpsc' ); ?></strong>
268
- </p>
269
- <?php
270
- foreach ( $internal_shipping_modules as $shipping ) {
271
-
272
- $shipping->checked = '';
273
- if ( is_object( $shipping ) && in_array( $shipping->getInternalName(), (array)$selected_shippings ) )
274
- $shipping->checked = ' checked = "checked" ';
275
- ?>
276
-
277
- <div class='wpsc_shipping_options'>
278
- <div class='wpsc-shipping-actions'>
279
- <span class="edit">
280
- <a class='edit-shipping-module' data-module-id="<?php echo $shipping->internal_name; ?>" title="<?php esc_attr_e( 'Edit this Shipping Module', 'wpsc' ); ?>" href='<?php echo esc_url( $this->get_shipping_module_url( $shipping ) ); ?>' style="cursor:pointer;"><?php _ex( 'Edit', 'Shipping modules link to individual settings', 'wpsc' ); ?></a>
281
- <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
282
- </span>
283
- </div>
284
-
285
- <p><input name='custom_shipping_options[]' <?php echo $shipping->checked; ?> type='checkbox' value='<?php echo $shipping->internal_name; ?>' id='<?php echo $shipping->internal_name; ?>_id' /><label for='<?php echo $shipping->internal_name; ?>_id'> <?php echo $shipping->name; ?></label></p>
286
- </div>
287
- <?php } ?>
288
- <br />
289
- <p>
290
- <strong><?php _e( 'External Shipping Calculators', 'wpsc' ); ?></strong>
291
- <?php if ( ! function_exists( 'curl_init' ) ) {
292
- ?>
293
- <br /><span style='color: red; font-size:8pt; line-height:10pt;'><?php _e( 'The following shipping modules all need cURL which is not installed on this server, you may need to contact your web hosting provider to get it set up. ', 'wpsc' ); ?></span>
294
- <?php } ?>
295
- </p>
296
- <?php
297
- // print the internal shipping methods
298
- foreach ( $external_shipping_modules as $shipping ) {
299
- $disabled = '';
300
- if ( isset( $shipping->requires_curl ) && $shipping->requires_curl && ! function_exists( 'curl_init' ) ) {
301
- $disabled = "disabled='disabled'";
302
- }
303
- $shipping->checked = '';
304
- if ( in_array( $shipping->getInternalName(), (array)$selected_shippings ) )
305
- $shipping->checked = " checked='checked' ";
306
- ?>
307
- <div class='wpsc_shipping_options'>
308
- <div class="wpsc-shipping-actions">
309
- <span class="edit">
310
- <a class='edit-shipping-module' data-module-id="<?php echo $shipping->internal_name; ?>" title="<?php esc_attr_e( 'Edit this Shipping Module', 'wpsc' ); ?>" href='<?php echo esc_url( $this->get_shipping_module_url( $shipping ) ); ?>' style="cursor:pointer;"><?php _ex( 'Edit', 'Shipping modules link to individual settings', 'wpsc' ); ?></a>
311
- <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
312
- </span>
313
- </div>
314
- <p><input <?php echo $disabled; ?> name='custom_shipping_options[]' <?php echo $shipping->checked; ?> type='checkbox' value='<?php echo $shipping->internal_name; ?>' id='<?php echo $shipping->internal_name; ?>_id' /><label for='<?php echo $shipping->internal_name; ?>_id'> <?php echo $shipping->name; ?></label></p>
315
- </div>
316
- <?php } ?>
317
- <p class="submit">
318
- <input type='hidden' value='true' name='update_gateways' />
319
- <input type="submit" value="<?php _e( 'Update &raquo;', 'wpsc' ); ?>" />
320
- </p>
321
- </div>
322
- </div>
323
- </td>
324
-
325
- <?php $this->display_shipping_module_settings_form(); ?>
326
- </tr>
327
- </table>
328
- </div>
329
  <?php
330
  }
331
  }
46
 
47
  $shipadd = 0;
48
  foreach ( $wpsc_shipping_modules as $shipping ) {
49
+ foreach ( (array) $_POST['custom_shipping_options'] as $shippingoption ) {
50
  if ( $shipping->internal_name == $shippingoption ) {
51
  $shipadd++;
52
  }
53
  }
54
  }
55
 
56
+ if ( ! get_option( 'do_not_use_shipping' ) && ! get_option( 'custom_shipping_options' ) && ! ( bool ) get_option( 'shipwire' ) ) {
57
  update_option( 'do_not_use_shipping', '1' );
58
  return array( 'shipping_disabled' => 1 );
59
  } else {
61
  }
62
  }
63
 
64
+ public function display_shipping_module_settings_form( $selected_module_id = null ) {
65
  global $wpsc_shipping_modules;
66
+ if ( ! $selected_module_id ) {
67
+ $selected_module_id = (string) get_user_option( 'wpsc_settings_selected_shipping_module', get_current_user_id() );
68
+ }
69
+
70
  $found_selected_module = array_key_exists( $selected_module_id, $wpsc_shipping_modules );
71
+
72
  if ( $found_selected_module ) {
73
  $selected_module = $wpsc_shipping_modules[$selected_module_id];
74
  $title = $selected_module->name;
75
  $content = apply_filters( 'wpsc_shipping_module_settings_form', $selected_module->getForm(), $selected_module );
 
76
  } else {
77
  $title = __( 'Edit Shipping Module Settings', 'wpsc' );
78
  $content = __( 'To configure a shipping module select one on the left.', 'wpsc' );
79
  }
80
+
81
  ?>
82
+ <div id='wpsc_shipping_settings_<?php esc_attr_e( $selected_module_id ); ?>_form' class='shipping-module-settings-form'>
83
+ <table class='form-table'>
84
+ <?php echo $content; ?>
85
+ </table>
86
+ <table class='form-table'>
87
+ <tr><td colspan='2'>
88
+ <p class="submit inline-edit-save">
89
+ <a class="button edit-shipping-module-cancel" title="<?php esc_attr_e( "Cancel editing this shipping calculator's settings", 'wpsc' ) ?>"><?php esc_html_e( "Cancel", 'wpsc' ); ?></a>
90
+ <input type="submit" name="submit" class="button button-primary edit-shipping-module-update" value='<?php _e( "Update &raquo;", 'wpsc' ); ?>'>
91
+ </p>
92
+ </td></tr>
93
+ </table>
94
+ </div>
 
 
95
  <?php
96
  }
97
 
114
  if ( empty( $module ) )
115
  continue;
116
 
117
+ if ( isset( $module->is_external ) && $module->is_external ) {
118
  $external_shipping_modules[$key] = $module;
119
+ } else {
120
  $internal_shipping_modules[$key] = $module;
121
+ }
122
  }
123
 
124
+ ?>
125
+
126
+ <h3><?php esc_html_e( 'Shipping Settings', 'wpsc'); ?></h3>
127
+ <input type='hidden' name='shipping_submits' value='true' />
128
+ <?php wp_nonce_field( 'update-options', 'wpsc-update-options' ); ?>
129
+ <input type='hidden' name='wpsc_admin_action' value='submit_options' />
130
+ <table class='form-table'>
131
+ <?php
132
+ /* wpsc_setting_page_update_notification displays the wordpress styled notifications */
133
+ wpsc_settings_page_update_notification();
134
+ ?>
135
+ <tr>
136
+ <th scope="row"><?php _e( 'Use Shipping', 'wpsc' ); ?></th>
137
+ <td>
138
+ <input type='hidden' value='1' name='wpsc_options[do_not_use_shipping]' />
139
+ <input type='checkbox' value='0' name='wpsc_options[do_not_use_shipping]' id='do_not_use_shipping' <?php checked( '0', get_option( 'do_not_use_shipping' ) ); ?> /> <label for='do_not_use_shipping'><?php _e( 'Enable Shipping settings', 'wpsc' ); ?></label>
140
+ <p class='description'><?php esc_html_e( 'If you are only selling digital downloads, you should turn this off.', 'wpsc' ); ?></p>
141
+ </td>
142
+ </tr>
143
+
144
+ <tr>
145
+ <th><?php esc_html_e( 'Shipping Origin City', 'wpsc' ); ?></th>
146
+ <td>
147
+ <input type='text' name='wpsc_options[base_city]' value='<?php esc_attr_e( get_option( 'base_city' ) ); ?>' />
148
+ <p class='description'><?php esc_html_e( 'The name of the city where you fulfill and ship orders from. This enables us to give your customers more accurate shipping pricing.', 'wpsc' ); ?></p>
149
+ </td>
150
+ </tr>
151
+ <tr>
152
+ <th><?php esc_html_e( 'Shipping Origin Zipcode/Postcode', 'wpsc' ); ?></th>
153
+ <td>
154
+ <input type='text' name='wpsc_options[base_zipcode]' value='<?php esc_attr_e( get_option( 'base_zipcode' ) ); ?>' />
155
+ <p class='description'>
156
+ <?php esc_html_e( 'The zipcode/postcode for where you fulfill and ship orders from.', 'wpsc' ); ?><br />
157
+ <?php esc_html_e( 'If you are based in the United States then this field is required in order for the UPS and USPS Shipping Calculators to work.', 'wpsc' ); ?>
158
+ </p>
159
+ </td>
160
+ </tr>
161
+ <tr>
162
+ <th scope="row"><?php _e( 'Shipwire', 'wpsc' ); ?><span style='color: red;'></span></th>
163
+ <td>
164
+ <input type='hidden' value='0' name='wpsc_options[shipwire]' />
165
+ <input type='checkbox' onclick='jQuery("#wpsc_shipwire_setting").toggle( jQuery(this).prop("checked") );' value='1' name='wpsc_options[shipwire]' id='shipwire' <?php checked( '1', get_option( 'shipwire' ) ); ?> />
166
+ <label for='shipwire'><?php _e( 'Enable Shipwire Integration', 'wpsc' ); ?></label>
167
+ <p class='description'><?php printf( __( '<a href="%1$s" target="_blank">Shipwire</a> provide e-commerce fulfillment warehouses. WP e-Commerce can integrate stock inventory and shipping tracking with their service.', 'wpsc' ), 'http://www.shipwire.com/' ); ?></p>
168
+ </td>
169
+ </tr>
170
+ <?php
171
+ switch ( get_option( 'shipwire' ) ) {
172
+ case 1:
173
+ $shipwire_settings = '';
174
+ break;
175
+
176
+ case 0:
177
+ default:
178
+ $shipwire_settings = 'style="display: none;"';
179
+ break;
180
+ }
181
+ ?>
182
+ <tr id='wpsc_shipwire_setting' <?php echo $shipwire_settings; ?>>
183
+ <th>&nbsp;</th>
184
+ <td>
185
+ <table>
186
+ <tr>
187
+ <th><?php esc_html_e( 'Shipwire Email', 'wpsc' ); ?></th>
188
+ <td><input type="text" name='wpsc_options[shipwireemail]' value="<?php esc_attr_e( get_option( 'shipwireemail' ) ); ?>" /></td>
189
+ </tr>
190
+ <tr>
191
+ <th><?php esc_html_e( 'Shipwire Password', 'wpsc' ); ?></th>
192
+ <td><input type="text" name='wpsc_options[shipwirepassword]' value="<?php esc_attr_e( get_option( 'shipwirepassword' ) ); ?>" /></td>
193
+ </tr>
194
+ <tr>
195
+ <th><?php esc_html_e( 'Use Test Server?', 'wpsc' ); ?></th>
196
+ <td><input type="checkbox" name='wpsc_options[shipwire_test_server]' value="0" <?php checked( '1', get_option( 'shipwire_test_server', '0' ) ); ?> /></td>
197
+ </tr>
198
+ <tr>
199
+ <th><?php esc_html_e( 'Force Sync with Shipwire', 'wpsc' ); ?></th>
200
+ <td>
201
+ <a class="shipwire_sync button"><?php esc_html_e( 'Update Tracking and Inventory', 'wpsc' ); ?></a>
202
+ <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
203
+ </td>
204
+ </tr>
205
+ </table>
206
+ </td>
207
+ </tr>
208
+ <?php
209
+ $currency_data = $wpdb->get_row( $wpdb->prepare( "SELECT `symbol`,`symbol_html`,`code` FROM `" . WPSC_TABLE_CURRENCY_LIST . "` WHERE `id` = %d LIMIT 1", get_option( 'currency_type' ) ), ARRAY_A );
210
+ if ( $currency_data['symbol'] != '' ) {
211
+ $currency_sign = $currency_data['symbol_html'];
212
+ } else {
213
+ $currency_sign = $currency_data['code'];
214
+ }
215
+ ?>
216
+ <tr>
217
+ <th><?php _e( 'Free Shipping Discount', 'wpsc' ); ?></th>
218
+ <td>
219
+ <?php
220
+ if ( get_option( 'shipping_discount' ) == 1 ) {
221
+ $shipping_discount_settings = 'style=\'display: block;\'';
222
+ } else {
223
+ $shipping_discount_settings = '';
224
+ }
225
+ ?>
226
+ <input type='hidden' value='0' name='wpsc_options[shipping_discount]' />
227
+ <input type='checkbox' onclick='jQuery("#shipping_discount_value").toggle( jQuery(this).prop("checked") );' value='1' name='wpsc_options[shipping_discount]' id='shipping_discount' <?php checked( '1', get_option( 'shipping_discount' ) ); ?> />
228
+ <label for='shipping_discount'><?php _e( 'Enable Free Shipping Discount', 'wpsc' ); ?></label>
229
+
230
+ </td>
231
+ </tr>
232
+ <tr>
233
+ <td>&nbsp;</td>
234
+ <td colspan="2">
235
+ <?php
236
+ $value = esc_attr( get_option( 'shipping_discount_value' ) );
237
+ ?>
238
+ <div <?php echo $shipping_discount_settings; ?> id='shipping_discount_value'>
239
+
240
+ <?php printf( __( 'Sales over or equal to %1$s<input type="text" size="6" name="wpsc_options[shipping_discount_value]" value="%2$s" id="shipping_discount_value" /> will receive free shipping.', 'wpsc' ), $currency_sign, $value ); ?>
241
+ </div>
242
+ </td>
243
+ </tr>
244
+ </table>
245
+
246
+ <?php submit_button( __( 'Save Changes' ) ); ?>
247
+
248
+ <h3><?php _e( 'Shipping Modules', 'wpsc' ) ?></h3>
249
+ <p class='description'><?php _e( 'To enable shipping in WP e-Commerce you must select which shipping methods you want to enable on your site.', 'wpsc' ); ?></p>
250
+ <p class='description'>
251
+ <strong><?php _e( 'Tip', 'wpsc' ); ?></strong>:
252
+ <?php printf( __( 'For fixed-price shipping options such as "Pickup - $0, Overnight - $10, Same day - $20, etc.", install our free <a href="%1$s">Fixed Rate Shipping</a> plugin.', 'wpsc' ), 'http://wordpress.org/extend/plugins/wp-e-commerce-fixed-rate-shipping/' ); ?>
253
+ </p>
254
+
255
+ <h4><?php _e( 'Internal Shipping Calculators', 'wpsc' ); ?></h4>
256
+ <table id='wpsc-shipping-options-internal' class='wpsc-edit-module-options wp-list-table widefat plugins'>
257
+ <thead>
258
+ <tr>
259
+ <th scope="col" id="wpsc-shipping-options-internal-active" class="manage-column"><?php _e( 'Active', 'wpsc' ); ?></th>
260
+ <th scope="col" id="wpsc-shipping-options-internal-name" class="manage-column column-name"><?php _e( 'Shipping Calculator', 'wpsc' ); ?></th>
261
+ </tr>
262
+ </thead>
263
+ <tfoot>
264
+ <tr>
265
+ <th scope="col" id="wpsc-shipping-options-internal-active" class="manage-column"><?php _e( 'Active', 'wpsc' ); ?></th>
266
+ <th scope="col" id="wpsc-shipping-options-internal-name" class="manage-column column-name"><?php _e( 'Shipping Calculator', 'wpsc' ); ?></th>
267
+ </tr>
268
+ </tfoot>
269
+ <tbody>
270
+ <?php
271
+ foreach ( $internal_shipping_modules as $shipping ) {
272
+ $force = ( $shipping->internal_name === (string) get_user_option( 'wpsc_settings_selected_shipping_module', get_current_user_id() ) );
273
+ $this->shipping_list_item( $shipping, $force );
274
+ }
275
+ ?>
276
+ </tbody>
277
+ </table>
278
+ <?php submit_button( __( 'Save Changes' ) ); ?>
279
+
280
+ <h4><?php _e( 'External Shipping Calculators', 'wpsc' ); ?></h4>
281
+ <?php if ( ! function_exists( 'curl_init' ) ) : ?>
282
+ <p style='color: red; font-size:8pt; line-height:10pt;'>
283
+ <?php _e( 'The following shipping modules all need cURL which is not installed on this server, you may need to contact your web hosting provider to get it set up. ', 'wpsc' ); ?>
284
+ </p>
285
+ <?php endif; ?>
286
+ <table id='wpsc-shipping-options-external' class='wpsc-edit-module-options wp-list-table widefat plugins'>
287
+ <thead>
288
+ <tr>
289
+ <th scope="col" id="wpsc-shipping-options-external-active" class="manage-column"><?php _e( 'Active', 'wpsc' ); ?></th>
290
+ <th scope="col" id="wpsc-shipping-options-external-name" class="manage-column column-name"><?php _e( 'Shipping Calculator', 'wpsc' ); ?></th>
291
+ </tr>
292
+ </thead>
293
+ <tfoot>
294
+ <tr>
295
+ <th scope="col" id="wpsc-shipping-options-external-active" class="manage-column"><?php _e( 'Active', 'wpsc' ); ?></th>
296
+ <th scope="col" id="wpsc-shipping-options-external-name" class="manage-column column-name"><?php _e( 'Shipping Calculator', 'wpsc' ); ?></th>
297
+ </tr>
298
+ </tfoot>
299
+ <tbody>
300
+ <?php
301
+ foreach ( $external_shipping_modules as $shipping ) {
302
+ $force = ( $shipping->internal_name === (string) get_user_option( 'wpsc_settings_selected_shipping_module', get_current_user_id() ) );
303
+ $this->shipping_list_item( $shipping, $force );
304
+ }
305
+ ?>
306
+ </tbody>
307
+ </table>
308
+ <?php
309
+ }
310
+
311
+ private function shipping_list_item ( $shipping, $force ) {
312
  //get shipping options that are selected
313
  $selected_shippings = get_option( 'custom_shipping_options' );
 
 
 
 
 
314
 
315
+ $shipping->checked = is_object( $shipping ) && in_array( $shipping->getInternalName(), (array) $selected_shippings );
316
+ $shipping->active = $shipping->checked ? 'active' : 'inactive';
317
+ $shipping->hidden = $force ? '' : "style='display: none;'";
318
+ $shipping->disabled = isset( $shipping->requires_curl ) && $shipping->requires_curl && ! function_exists( 'curl_init' ) ;
319
 
320
+ ?>
321
+ <tr class="wpsc-select-shipping <?php echo $shipping->active; ?>" data-shipping-id="<?php echo esc_attr( $shipping->internal_name ); ?>" id="shipping_list_item_<?php echo $shipping->internal_name;?>">
322
+ <th scope="row" class="check-column">
323
+ <input name='custom_shipping_options[]' <?php disabled( $shipping->disabled ); ?> <?php checked( $shipping->checked ); ?> type='checkbox' value='<?php echo $shipping->internal_name; ?>' id='<?php echo $shipping->internal_name; ?>_id' />
324
+ </th>
325
+ <td class="plugin-title">
326
+ <label for='<?php echo $shipping->internal_name; ?>_id'><strong><?php echo $shipping->name; ?></strong></label>
327
+ <div class="row-actions-visible">
328
+ <span class="edit">
329
+ <a class='edit-shipping-module' data-module-id="<?php echo $shipping->internal_name; ?>" title="<?php esc_attr_e( 'Edit this Shipping Module', 'wpsc' ); ?>" href='<?php echo esc_url( $this->get_shipping_module_url( $shipping ) ); ?>'><?php _ex( 'Settings', 'Shipping modules link to individual settings', 'wpsc' ); ?>
330
+ <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
331
+ </span>
332
+ </div>
333
+ </td>
334
+ </tr>
335
+ <tr id="wpsc_shipping_settings_<?php echo esc_attr( $shipping->internal_name ); ?>" data-shipping-id="<?php echo esc_attr( $shipping->internal_name ); ?>" class='wpsc-select-shipping <?php echo $shipping->active; ?>' <?php echo $shipping->hidden; ?> >
336
+ <td colspan="3" id="wpsc_shipping_settings_<?php echo esc_attr( $shipping->internal_name ); ?>_container">
337
+ <?php $this->display_shipping_module_settings_form( $shipping->internal_name ); ?>
338
+ </td>
339
+ </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  <?php
341
  }
342
  }
wpsc-admin/includes/settings-tabs/taxes.php CHANGED
@@ -74,174 +74,144 @@ class WPSC_Settings_Tab_Taxes extends WPSC_Settings_Tab {
74
  $wpec_taxes_controller = new wpec_taxes_controller;
75
  $wpec_taxes_options = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_options();
76
 
77
- ?>
78
- <h3><?php esc_html_e( 'Tax Settings', 'wpsc' ); ?></h3>
79
- <p>
 
 
 
 
80
  <label for='wpec_taxes_enabled'>
81
- <input <?php if ( $wpec_taxes_options['wpec_taxes_enabled'] ) {
82
- echo 'checked="checked"';
83
- } ?> type="checkbox" id='wpec_taxes_enabled' name='wpsc_options[wpec_taxes_enabled]' />
84
- <?php esc_html_e( 'Turn tax on', 'wpsc' ); ?>
85
- </label>
86
- </p>
87
- <p>
88
- <label for='wpec_taxes_inprice1'>
89
- <input <?php if ( $wpec_taxes_options['wpec_taxes_inprice'] == 'exclusive' ) {
90
- echo 'checked="checked"';
91
- } ?> type="radio" value='exclusive' id='wpec_taxes_inprice1' name='wpsc_options[wpec_taxes_inprice]' />
92
- <?php esc_html_e( 'Product prices are tax exclusive - add tax to the price during checkout', 'wpsc' ); ?>
93
- </label>
94
- </p>
95
- <p>
96
- <label for='wpec_taxes_inprice2'>
97
- <input <?php if ( $wpec_taxes_options['wpec_taxes_inprice'] == 'inclusive' ) {
98
- echo 'checked="checked"';
99
- } ?> type="radio" value='inclusive' id='wpec_taxes_inprice2' name='wpsc_options[wpec_taxes_inprice]' />
100
- <?php esc_html_e( "Product prices are tax inclusive - during checkout the total price doesn't increase but tax is shown as a line item", 'wpsc' ); ?>
101
- </label>
102
- </p>
103
- <h4><?php esc_html_e( 'Product Specific Tax', 'wpsc' ); ?></h4>
104
- <p>
105
- <label for='wpec_taxes_product_1'>
106
- <input <?php if ( $wpec_taxes_options['wpec_taxes_product'] == 'add' ) {
107
- echo 'checked="checked"';
108
- } ?> type="radio" value='add' id='wpec_taxes_product_1' name='wpsc_options[wpec_taxes_product]' />
109
- <?php esc_html_e( 'Add per product tax to tax percentage if product has a specific tax rate', 'wpsc' ); ?>
110
- </label>
111
- </p>
112
- <p>
113
- <label for='wpec_taxes_product_2'>
114
- <input <?php if ( $wpec_taxes_options['wpec_taxes_product'] == 'replace' ) {
115
- echo 'checked="checked"';
116
- } ?> type="radio" value='replace' id='wpec_taxes_product_2' name='wpsc_options[wpec_taxes_product]' />
117
- <?php esc_html_e( 'Replace tax percentage with product specific tax rate', 'wpsc' ); ?>
118
- </label>
119
- </p>
120
-
121
- <h4><?php _e( 'Tax Logic', 'wpsc' ); ?></h4>
122
- <p>
123
- <label for='wpec_taxes_logic_1'>
124
- <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' ) {
125
- echo 'checked="checked"';
126
- } ?> type="radio" value='billing_shipping' id='wpec_taxes_logic_1' name='wpsc_options[wpec_taxes_logic]' />
127
  <?php esc_html_e( 'Apply tax when Billing and Shipping Country is the same as Tax Rate', 'wpsc' ); ?>
128
- </label>
129
- <div id='billing_shipping_preference_container' style='margin-left: 20px;'>
130
- <p>
131
- <label for='wpec_billing_preference'>
132
- <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' && $wpec_taxes_options['wpec_billing_shipping_preference'] == 'billing_address' ) {
133
- echo 'checked="checked"';
134
- } ?> type="radio" value='billing_address' id='wpec_billing_preference' name='wpsc_options[wpec_billing_shipping_preference]' />
135
- <?php esc_html_e( 'Apply tax to Billing Address', 'wpsc' ); ?>
136
- </label>
137
- </p>
138
- <p>
 
 
139
  <label for='wpec_shipping_preference'>
140
- <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' && $wpec_taxes_options['wpec_billing_shipping_preference'] == 'shipping_address' ) {
141
- echo 'checked="checked"';
142
- } ?> type="radio" value='shipping_address' id='wpec_shipping_preference' name='wpsc_options[wpec_billing_shipping_preference]' />
143
- <?php esc_html_e( 'Apply tax to Shipping Address', 'wpsc' ); ?>
144
  </label>
145
- </p>
146
- </div>
147
- </p>
148
- <p>
149
  <label for='wpec_taxes_logic_2'>
150
- <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing' ) {
151
- echo 'checked="checked"';
152
- } ?> type="radio" value='billing' id='wpec_taxes_logic_2' name='wpsc_options[wpec_taxes_logic]' />
153
  <?php esc_html_e( 'Apply tax when Billing Country is the same as Tax Rate', 'wpsc' ); ?>
154
- </label>
155
- </p>
156
- <p>
157
- <label for='wpec_taxes_logic_3'>
158
- <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'shipping' ) {
159
- echo 'checked="checked"';
160
- } ?> type="radio" value='shipping' id='wpec_taxes_logic_3' name='wpsc_options[wpec_taxes_logic]' />
161
  <?php esc_html_e( 'Apply tax when Shipping Country is the same as Tax Rate', 'wpsc' ); ?>
162
- </label>
163
- </p>
164
- <div id='metabox-holder' class="metabox-holder">
165
- <div id='wpec-taxes-rates-container' class='postbox'>
166
- <h3 class='hndle' style='cursor: default'><?php esc_html_e( 'Tax Rates', 'wpsc' ); ?></h3>
167
- <div id='wpec-taxes-rates' class='inside'>
168
- <!--Start Taxes Output-->
169
- <?php
170
- /**
171
- * Add New Tax Rate - should add another paragraph with the
172
- * another key specified for the input array
173
- * Delete - Should remove the given paragraph from the page
174
- * and either ajax delete it from the DB or mark it for
175
- * deletion and process it after the changes are made.
176
- * Selecting a Country - should automatically populate the
177
- * regions select box. Selecting a different country should
178
- * remove the region select box. If the user selects a
179
- * different country with regions it shouldn't matter because
180
- * the code should automatically add the region select in.
181
- * - Allow users to define tax for entire country even if regions exist.
182
- * Shipping Tax - needs to be per region or per tax rate.
183
- * Remove the setting from the main Tax Settings area.
184
- * Constraints -
185
- * 1. Should not allow a user to add more than one
186
- * tax rate for the same area.
187
- * 2. If a country tax rate is specified and then a region tax
188
- * rate, the region tax rate takes precedence.
189
- * */
190
-
191
- /**
192
- * Removed Shipping Restriction on Included tax - 01-20-2011
193
- * //if tax is included warn about shipping
194
- * if ( $wpec_taxes_controller->wpec_taxes_isincluded() ) {
195
- * echo '<p>' . __( 'Note: Tax is not applied to shipping when product prices are tax inclusive.' ) . '</p>';
196
- * }// if
197
- **/
198
-
199
- //get current tax rates
200
- // TODO: Refactor to get rid of the need for wpec_taxes_build_form(). It's a horribly written function.
201
  $tax_rates = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_rates();
 
 
 
 
202
  $tax_rate_count = 0;
203
- if ( !empty( $tax_rates ) ) {
204
  foreach ( $tax_rates as $tax_rate ) {
205
- echo $wpec_taxes_controller->wpec_taxes_build_form( $tax_rate_count, $tax_rate );
 
206
  $tax_rate_count++;
207
- }// foreach
208
- }// if
209
- ?>
210
- <!--End Taxes Output-->
211
- <p id="wpsc-add-tax-rates">
212
- <a href="#"><?php esc_html_e( 'Add New Tax Rate', 'wpsc' ); ?></a>
213
- <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
214
- </p>
215
- </div>
216
- </div>
217
- <div id='wpec-taxes-bands-container' class='postbox'>
218
- <h3 class='hndle' style='cursor: default'><?php esc_html_e( 'Tax Bands', 'wpsc' ); ?></h3>
219
- <div id='wpec-taxes-bands' class='inside'>
220
-
221
- <?php
222
- echo '<p>' . __( 'Note: Tax Bands are special tax rules you can create and apply on a per-product basis. <br /> Please visit the product page to apply your Tax Band.', 'wpsc' ) . '</p>';
223
-
224
- //echo message regarding inclusive tax
225
- if ( !$wpec_taxes_controller->wpec_taxes_isincluded() ) {
226
- echo '<p>' . __( 'Note: Tax Bands do not take affect when product prices are tax exclusive.', 'wpsc' ) . '</p>';
227
- }// if
228
-
229
- $tax_bands = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_bands();
230
- $tax_band_count = 0;
231
- if ( !empty( $tax_bands ) ) {
232
- foreach ( $tax_bands as $tax_band ) {
233
- echo $wpec_taxes_controller->wpec_taxes_build_form( $tax_band_count, $tax_band, 'bands' );
234
- $tax_band_count++;
235
- }// foreach
236
- }// if
237
- ?>
238
- <p id="wpsc-add-tax-bands">
239
- <a href="#"><?php _e( 'Add New Tax Band', 'wpsc' ); ?></a>
240
- <img src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" class="ajax-feedback" title="" alt="" />
241
- </p>
242
- </div>
243
- </div><!--wpec-taxes-bands-container-->
244
- </div><!--metabox-holder-->
 
 
 
 
245
  <?php
246
  }
247
  }
74
  $wpec_taxes_controller = new wpec_taxes_controller;
75
  $wpec_taxes_options = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_options();
76
 
77
+ ?>
78
+ <h3><?php esc_html_e( 'Tax Settings', 'wpsc' ); ?></h3>
79
+ <table class='form-table'>
80
+ <tr>
81
+ <th><?php esc_html_e( "Enable Tax", 'wpsc' ); ?></th>
82
+ <td>
83
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_enabled'] ) echo 'checked="checked"'; ?> type="checkbox" id='wpec_taxes_enabled' name='wpsc_options[wpec_taxes_enabled]' />
84
  <label for='wpec_taxes_enabled'>
85
+ <?php esc_html_e( 'Turn tax on', 'wpsc' ); ?>
86
+ </label>
87
+ </td>
88
+ </tr>
89
+ <tr>
90
+ <th><?php esc_html_e( "Product Prices", 'wpsc' ); ?></th>
91
+ <td>
92
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_inprice'] == 'exclusive' ) echo 'checked="checked"'; ?> type="radio" value='exclusive' id='wpec_taxes_inprice1' name='wpsc_options[wpec_taxes_inprice]' />
93
+ <label for='wpec_taxes_inprice1'>
94
+ <?php esc_html_e( 'Product prices are tax exclusive - add tax to the price during checkout', 'wpsc' ); ?>
95
+ </label><br />
96
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_inprice'] == 'inclusive' ) echo 'checked="checked"'; ?> type="radio" value='inclusive' id='wpec_taxes_inprice2' name='wpsc_options[wpec_taxes_inprice]' />
97
+ <label for='wpec_taxes_inprice2'>
98
+ <?php esc_html_e( "Product prices are tax inclusive - during checkout the total price doesn't increase but tax is shown as a line item", 'wpsc' ); ?>
99
+ </label>
100
+ </td>
101
+ </tr>
102
+ <tr>
103
+ <th><?php esc_html_e( 'Product Specific Tax', 'wpsc' ); ?></th>
104
+ <td>
105
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_product'] == 'add' ) echo 'checked="checked"'; ?> type="radio" value='add' id='wpec_taxes_product_1' name='wpsc_options[wpec_taxes_product]' />
106
+ <label for='wpec_taxes_product_1'>
107
+ <?php esc_html_e( 'Add per product tax to tax percentage if product has a specific tax rate', 'wpsc' ); ?>
108
+ </label><br />
109
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_product'] == 'replace' ) echo 'checked="checked"'; ?> type="radio" value='replace' id='wpec_taxes_product_2' name='wpsc_options[wpec_taxes_product]' />
110
+ <label for='wpec_taxes_product_2'>
111
+ <?php esc_html_e( 'Replace tax percentage with product specific tax rate', 'wpsc' ); ?>
112
+ </label>
113
+ </td>
114
+ </tr>
115
+ <tr>
116
+ <th><?php _e( 'Tax Logic', 'wpsc' ); ?></th>
117
+ <td>
118
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' ) echo 'checked="checked"'; ?> type="radio" value='billing_shipping' id='wpec_taxes_logic_1' name='wpsc_options[wpec_taxes_logic]' />
119
+ <label for='wpec_taxes_logic_1'>
 
 
 
 
 
 
 
 
 
 
 
120
  <?php esc_html_e( 'Apply tax when Billing and Shipping Country is the same as Tax Rate', 'wpsc' ); ?>
121
+ </label>
122
+ <div id='billing_shipping_preference_container' style='margin-left: 20px;'>
123
+ <?php
124
+ $checked = ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' && $wpec_taxes_options['wpec_billing_shipping_preference'] == 'billing_address' ? 'checked="checked"' : '' );
125
+ ?>
126
+ <input <?php echo $checked;?> type="radio" value='billing_address' id='wpec_billing_preference' name='wpsc_options[wpec_billing_shipping_preference]' />
127
+ <label for='wpec_billing_preference'>
128
+ <?php esc_html_e( 'Apply tax to Billing Address', 'wpsc' ); ?>
129
+ </label><br />
130
+ <?php
131
+ $checked = ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing_shipping' && $wpec_taxes_options['wpec_billing_shipping_preference'] == 'shipping_address' ? 'checked="checked"' : '' );
132
+ ?>
133
+ <input <?php echo $checked; ?>type="radio" value='shipping_address' id='wpec_shipping_preference' name='wpsc_options[wpec_billing_shipping_preference]' />
134
  <label for='wpec_shipping_preference'>
135
+ <?php esc_html_e( 'Apply tax to Shipping Address', 'wpsc' ); ?>
 
 
 
136
  </label>
137
+ </div>
138
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'billing' ) echo 'checked="checked"'; ?> type="radio" value='billing' id='wpec_taxes_logic_2' name='wpsc_options[wpec_taxes_logic]' />
 
 
139
  <label for='wpec_taxes_logic_2'>
 
 
 
140
  <?php esc_html_e( 'Apply tax when Billing Country is the same as Tax Rate', 'wpsc' ); ?>
141
+ </label><br />
142
+ <input <?php if ( $wpec_taxes_options['wpec_taxes_logic'] == 'shipping' ) echo 'checked="checked"'; ?> type="radio" value='shipping' id='wpec_taxes_logic_3' name='wpsc_options[wpec_taxes_logic]' />
143
+ <label for='wpec_taxes_logic_3'>
 
 
 
 
144
  <?php esc_html_e( 'Apply tax when Shipping Country is the same as Tax Rate', 'wpsc' ); ?>
145
+ </label>
146
+ </td>
147
+ </tr>
148
+ </table>
149
+
150
+ <h3><?php esc_html_e( 'Tax Rates', 'wpsc' ); ?></h3>
151
+ <div id='wpec-taxes-rates'>
152
+ <!--Start Taxes Output-->
153
+ <table class='widefat page fixed ui-sortable'>
154
+ <thead>
155
+ <th scope='col' width='60%'><?php _e( 'Market', 'wpsc' ); ?></th>
156
+ <th scope='col' width='10%'><?php _e( 'Tax Rate', 'wpsc' ); ?></th>
157
+ <th scope='col'><?php _e( 'Tax Shipping?', 'wpsc' ); ?></th>
158
+ <th scope='col' style='width: 60px'><?php _e( 'Actions', 'wpsc' ); ?></th>
159
+ </thead>
160
+ <tbody>
161
+ <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  $tax_rates = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_rates();
163
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'rates', 'prototype', array( 'row_class' => 'prototype' ) );
164
+ if ( count( $tax_rates ) === 0 ) {
165
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'rates', 0, null );
166
+ }
167
  $tax_rate_count = 0;
168
+ if ( ! empty( $tax_rates ) ) {
169
  foreach ( $tax_rates as $tax_rate ) {
170
+ // OLD: echo $wpec_taxes_controller->wpec_taxes_build_form( $tax_rate_count, $tax_rate );
171
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'rates', $tax_rate_count, $tax_rate );
172
  $tax_rate_count++;
173
+ }
174
+ }
175
+ ?>
176
+ </tbody>
177
+ </table>
178
+ <!--End Taxes Output-->
179
+ </div>
180
+ <div id='wpec-taxes-bands-container'>
181
+ <h3><?php esc_html_e( 'Tax Bands', 'wpsc' ); ?></h3>
182
+ <div id='wpec-taxes-bands'>
183
+ <p><?php _e( 'Note: Tax Bands are special tax rules you can create and apply on a per-product basis. Please visit the product page to apply your Tax Band.', 'wpsc' ); ?></p>
184
+ <?php if ( !$wpec_taxes_controller->wpec_taxes_isincluded() ) : ?>
185
+ <p class="form-invalid"><?php _e( 'Warning: Tax Bands do not take affect when product prices are tax exclusive.', 'wpsc' ); ?></p>
186
+ <?php endif; ?>
187
+ <table class='widefat page fixed ui-sortable'>
188
+ <thead>
189
+ <th scope='col'><?php _e( 'Band Name', 'wpsc' ); ?></th>
190
+ <th scope='col' width="50%"><?php _e( 'Market', 'wpsc' ); ?></th>
191
+ <th scope='col' width='20%'><?php _e( 'Tax Rate', 'wpsc' ); ?></th>
192
+ <th scope='col' style='width: 60px'><?php _e( 'Actions', 'wpsc' ); ?></th>
193
+ </thead>
194
+ <tbody>
195
+ <?php
196
+ $tax_bands = $wpec_taxes_controller->wpec_taxes->wpec_taxes_get_bands();
197
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'bands', 'prototype', array( 'row_class' => 'prototype' ) );
198
+ if ( count( $tax_bands ) === 0 ) {
199
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'bands', 0, null );
200
+ }
201
+ $tax_band_count = 0;
202
+ if ( ! empty( $tax_bands ) ) {
203
+ foreach ( $tax_bands as $tax_band ) {
204
+ // OLD: echo $wpec_taxes_controller->wpec_taxes_build_form( $tax_band_count, $tax_band, 'bands' );
205
+ echo $wpec_taxes_controller->wpsc_build_taxes_row( 'bands', $tax_band_count, $tax_band );
206
+ $tax_band_count++;
207
+ }
208
+ }
209
+ ?>
210
+
211
+ </tbody>
212
+ </table>
213
+ </div>
214
+ </div><!--wpec-taxes-bands-container-->
215
  <?php
216
  }
217
  }
wpsc-admin/init.php CHANGED
@@ -402,16 +402,12 @@ if ( isset( $_REQUEST['wpsc_admin_action'] ) && ($_REQUEST['wpsc_admin_action']
402
  function wpsc_delete_purchlog( $purchlog_id='' ) {
403
  global $wpdb;
404
  $deleted = 0;
 
405
  if ( $purchlog_id == '' ) {
406
  $purchlog_id = absint( $_GET['purchlog_id'] );
407
  check_admin_referer( 'delete_purchlog_' . $purchlog_id );
408
  }
409
 
410
- if ( is_numeric( $purchlog_id ) ) {
411
- $delete_log_form_sql = "SELECT * FROM `" . WPSC_TABLE_CART_CONTENTS . "` WHERE `purchaseid`='$purchlog_id'";
412
- $cart_content = $wpdb->get_results( $delete_log_form_sql, ARRAY_A );
413
- }
414
-
415
  $purchlog_status = $wpdb->get_var( $wpdb->prepare( "SELECT `processed` FROM `" . WPSC_TABLE_PURCHASE_LOGS . "` WHERE `id`= %d", $purchlog_id ) );
416
  if ( $purchlog_status == 5 || $purchlog_status == 1 ) {
417
  $wpdb->query( $wpdb->prepare( "DELETE FROM `" . WPSC_TABLE_CLAIMED_STOCK . "` WHERE `cart_id` = %d AND `cart_submitted` = '1'", $purchlog_id ) );
402
  function wpsc_delete_purchlog( $purchlog_id='' ) {
403
  global $wpdb;
404
  $deleted = 0;
405
+
406
  if ( $purchlog_id == '' ) {
407
  $purchlog_id = absint( $_GET['purchlog_id'] );
408
  check_admin_referer( 'delete_purchlog_' . $purchlog_id );
409
  }
410
 
 
 
 
 
 
411
  $purchlog_status = $wpdb->get_var( $wpdb->prepare( "SELECT `processed` FROM `" . WPSC_TABLE_PURCHASE_LOGS . "` WHERE `id`= %d", $purchlog_id ) );
412
  if ( $purchlog_status == 5 || $purchlog_status == 1 ) {
413
  $wpdb->query( $wpdb->prepare( "DELETE FROM `" . WPSC_TABLE_CLAIMED_STOCK . "` WHERE `cart_id` = %d AND `cart_submitted` = '1'", $purchlog_id ) );
wpsc-admin/js/admin.js CHANGED
@@ -296,7 +296,7 @@ jQuery(document).ready(function(){
296
  };
297
 
298
  jQuery.post( ajaxurl, post_values, function( response ) {
299
- jQuery( '.featured_toggle_' + response.product_id ).html( "<img class='" + response.class + "' src='" + response.image + "' alt='" + response.text + "' title='" + response.text + "' />" );
300
  }, 'json' );
301
 
302
  return false;
296
  };
297
 
298
  jQuery.post( ajaxurl, post_values, function( response ) {
299
+ jQuery( '.featured_toggle_' + response.product_id ).html( "<img class='" + response.color + "' src='" + response.image + "' alt='" + response.text + "' title='" + response.text + "' />" );
300
  }, 'json' );
301
 
302
  return false;
wpsc-admin/js/ajax.js DELETED
@@ -1,48 +0,0 @@
1
- // Copyright (c) 2005 Timothy R. Morgan
2
- //
3
- // Permission is hereby granted, free of charge, to any person obtaining a copy
4
- // of this software and associated documentation files (the "Software"), to deal
5
- // in the Software without restriction, including without limitation the rights
6
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- // copies of the Software, and to permit persons to whom the Software is
8
- // furnished to do so, subject to the following conditions:
9
- //
10
- // The above copyright notice and this permission notice shall be included in
11
- // all copies or substantial portions of the Software.
12
- //
13
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
- // IN THE SOFTWARE.
20
- // mini/ajax.js - http://timmorgan.org/mini
21
- // var fvd = 0;
22
- function ajax_item(e){if(typeof e=='string')e=document.getElementById(e);return e};
23
- function collect(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};
24
-
25
- ajax={};
26
- ajax.x=function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}};
27
- ajax.serialize=function(f)
28
- {
29
- var g=function(n)
30
- {
31
- return f.getElementsByTagName(n)
32
- };
33
- var nv=function(e)
34
- {
35
- if(e.name)
36
- {
37
- return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);
38
- } else {return '';}
39
- };
40
- var i=collect(g('input'),function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)});var s=collect(g('select'),nv);var t=collect(g('textarea'),nv);return i.concat(s).concat(t).join('&');
41
- };
42
-
43
- ajax.send=function(u,f,m,a){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText)};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a)};
44
- ajax.get=function(url,func){ajax.send(url,func,'GET')};
45
- ajax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};
46
- ajax.post=function(url,func,args){ajax.send(url,func,'POST',args)};
47
- ajax.update=function(url,elm){var e=ajax_item(elm);var f=function(r){e.innerHTML=r};ajax.get(url,f)};
48
- ajax.submit=function(url,elm,frm){var e=ajax_item(elm);var f=function(r){e.innerHTML=r};ajax.post(url,f,ajax.serialize(frm))};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-admin/js/dimensions.js DELETED
@@ -1,325 +0,0 @@
1
- /*
2
- * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
3
- * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
4
- *
5
- * $LastChangedDate$
6
- * $Rev$
7
- */
8
-
9
- jQuery.fn._height = jQuery.fn.height;
10
- jQuery.fn._width = jQuery.fn.width;
11
-
12
- /**
13
- * If used on document, returns the document's height (innerHeight)
14
- * If used on window, returns the viewport's (window) height
15
- * See core docs on height() to see what happens when used on an element.
16
- *
17
- * @example $("#testdiv").height()
18
- * @result 200
19
- *
20
- * @example $(document).height()
21
- * @result 800
22
- *
23
- * @example $(window).height()
24
- * @result 400
25
- *
26
- * @name height
27
- * @type Object
28
- * @cat Plugins/Dimensions
29
- */
30
- jQuery.fn.height = function() {
31
- if ( this[0] == window )
32
- return self.innerHeight ||
33
- jQuery.boxModel && document.documentElement.clientHeight ||
34
- document.body.clientHeight;
35
-
36
- if ( this[0] == document )
37
- return Math.max( document.body.scrollHeight, document.body.offsetHeight );
38
-
39
- return this._height(arguments[0]);
40
- };
41
-
42
- /**
43
- * If used on document, returns the document's width (innerWidth)
44
- * If used on window, returns the viewport's (window) width
45
- * See core docs on height() to see what happens when used on an element.
46
- *
47
- * @example $("#testdiv").width()
48
- * @result 200
49
- *
50
- * @example $(document).width()
51
- * @result 800
52
- *
53
- * @example $(window).width()
54
- * @result 400
55
- *
56
- * @name width
57
- * @type Object
58
- * @cat Plugins/Dimensions
59
- */
60
- jQuery.fn.width = function() {
61
- if ( this[0] == window )
62
- return self.innerWidth ||
63
- jQuery.boxModel && document.documentElement.clientWidth ||
64
- document.body.clientWidth;
65
-
66
- if ( this[0] == document )
67
- return Math.max( document.body.scrollWidth, document.body.offsetWidth );
68
-
69
- return this._width(arguments[0]);
70
- };
71
-
72
- /**
73
- * Returns the inner height value (without border) for the first matched element.
74
- * If used on document, returns the document's height (innerHeight)
75
- * If used on window, returns the viewport's (window) height
76
- *
77
- * @example $("#testdiv").innerHeight()
78
- * @result 800
79
- *
80
- * @name innerHeight
81
- * @type Number
82
- * @cat Plugins/Dimensions
83
- */
84
- jQuery.fn.innerHeight = function() {
85
- return this[0] == window || this[0] == document ?
86
- this.height() :
87
- this.css('display') != 'none' ?
88
- this[0].offsetHeight - (parseInt(this.css("borderTopWidth")) || 0) - (parseInt(this.css("borderBottomWidth")) || 0) :
89
- this.height() + (parseInt(this.css("paddingTop")) || 0) + (parseInt(this.css("paddingBottom")) || 0);
90
- };
91
-
92
- /**
93
- * Returns the inner width value (without border) for the first matched element.
94
- * If used on document, returns the document's Width (innerWidth)
95
- * If used on window, returns the viewport's (window) width
96
- *
97
- * @example $("#testdiv").innerWidth()
98
- * @result 1000
99
- *
100
- * @name innerWidth
101
- * @type Number
102
- * @cat Plugins/Dimensions
103
- */
104
- jQuery.fn.innerWidth = function() {
105
- return this[0] == window || this[0] == document ?
106
- this.width() :
107
- this.css('display') != 'none' ?
108
- this[0].offsetWidth - (parseInt(this.css("borderLeftWidth")) || 0) - (parseInt(this.css("borderRightWidth")) || 0) :
109
- this.height() + (parseInt(this.css("paddingLeft")) || 0) + (parseInt(this.css("paddingRight")) || 0);
110
- };
111
-
112
- /**
113
- * Returns the outer height value (including border) for the first matched element.
114
- * Cannot be used on document or window.
115
- *
116
- * @example $("#testdiv").outerHeight()
117
- * @result 1000
118
- *
119
- * @name outerHeight
120
- * @type Number
121
- * @cat Plugins/Dimensions
122
- */
123
- jQuery.fn.outerHeight = function() {
124
- return this[0] == window || this[0] == document ?
125
- this.height() :
126
- this.css('display') != 'none' ?
127
- this[0].offsetHeight :
128
- this.height() + (parseInt(this.css("borderTopWidth")) || 0) + (parseInt(this.css("borderBottomWidth")) || 0)
129
- + (parseInt(this.css("paddingTop")) || 0) + (parseInt(this.css("paddingBottom")) || 0);
130
- };
131
-
132
- /**
133
- * Returns the outer width value (including border) for the first matched element.
134
- * Cannot be used on document or window.
135
- *
136
- * @example $("#testdiv").outerWidth()
137
- * @result 1000
138
- *
139
- * @name outerWidth
140
- * @type Number
141
- * @cat Plugins/Dimensions
142
- */
143
- jQuery.fn.outerWidth = function() {
144
- return this[0] == window || this[0] == document ?
145
- this.width() :
146
- this.css('display') != 'none' ?
147
- this[0].offsetWidth :
148
- this.height() + (parseInt(this.css("borderLeftWidth")) || 0) + (parseInt(this.css("borderRightWidth")) || 0)
149
- + (parseInt(this.css("paddingLeft")) || 0) + (parseInt(this.css("paddingRight")) || 0);
150
- };
151
-
152
- /**
153
- * Returns how many pixels the user has scrolled to the right (scrollLeft).
154
- * Works on containers with overflow: auto and window/document.
155
- *
156
- * @example $("#testdiv").scrollLeft()
157
- * @result 100
158
- *
159
- * @name scrollLeft
160
- * @type Number
161
- * @cat Plugins/Dimensions
162
- */
163
- jQuery.fn.scrollLeft = function() {
164
- if ( this[0] == window || this[0] == document )
165
- return self.pageXOffset ||
166
- jQuery.boxModel && document.documentElement.scrollLeft ||
167
- document.body.scrollLeft;
168
-
169
- return this[0].scrollLeft;
170
- };
171
-
172
- /**
173
- * Returns how many pixels the user has scrolled to the bottom (scrollTop).
174
- * Works on containers with overflow: auto and window/document.
175
- *
176
- * @example $("#testdiv").scrollTop()
177
- * @result 100
178
- *
179
- * @name scrollTop
180
- * @type Number
181
- * @cat Plugins/Dimensions
182
- */
183
- jQuery.fn.scrollTop = function() {
184
- if ( this[0] == window || this[0] == document )
185
- return self.pageYOffset ||
186
- jQuery.boxModel && document.documentElement.scrollTop ||
187
- document.body.scrollTop;
188
-
189
- return this[0].scrollTop;
190
- };
191
-
192
- /**
193
- * Returns the location of the element in pixels from the top left corner of the viewport.
194
- *
195
- * For accurate readings make sure to use pixel values for margins, borders and padding.
196
- *
197
- * @example $("#testdiv").offset()
198
- * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
199
- *
200
- * @example $("#testdiv").offset({ scroll: false })
201
- * @result { top: 90, left: 90 }
202
- *
203
- * @example var offset = {}
204
- * $("#testdiv").offset({ scroll: false }, offset)
205
- * @result offset = { top: 90, left: 90 }
206
- *
207
- * @name offset
208
- * @param Object options A hash of options describing what should be included in the final calculations of the offset.
209
- * The options include:
210
- * margin: Should the margin of the element be included in the calculations? True by default.
211
- * If set to false the margin of the element is subtracted from the total offset.
212
- * border: Should the border of the element be included in the calculations? True by default.
213
- * If set to false the border of the element is subtracted from the total offset.
214
- * padding: Should the padding of the element be included in the calculations? False by default.
215
- * If set to true the padding of the element is added to the total offset.
216
- * scroll: Should the scroll offsets of the parent elements be included in the calculations?
217
- * True by default. When true, it adds the total scroll offsets of all parents to the
218
- * total offset and also adds two properties to the returned object, scrollTop and
219
- * scrollLeft. If set to false the scroll offsets of parent elements are ignored.
220
- * If scroll offsets are not needed, set to false to get a performance boost.
221
- * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
222
- * chain will not be broken and the result will be assigned to this object.
223
- * @type Object
224
- * @cat Plugins/Dimensions
225
- * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
226
- */
227
- jQuery.fn.offset = function(options, returnObject) {
228
- var x = 0, y = 0, elem = this[0], parent = this[0], absparent=false, relparent=false, op, sl = 0, st = 0, options = jQuery.extend({ margin: true, border: true, padding: false, scroll: true }, options || {});
229
- do {
230
- if(parent == null)
231
- {
232
- // fix by Thomas Howard , stops some javascript errors with an unknown original cause, somehow parent sometimes ends up empty
233
- return null;
234
- }
235
- x += parent.offsetLeft || 0;
236
- y += parent.offsetTop || 0;
237
-
238
- // Mozilla and IE do not add the border
239
- if (jQuery.browser.mozilla || jQuery.browser.msie) {
240
- // get borders
241
- var bt = parseInt(jQuery.css(parent, 'borderTopWidth')) || 0;
242
- var bl = parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;
243
-
244
- // add borders to offset
245
- x += bl;
246
- y += bt;
247
-
248
- // Mozilla removes the border if the parent has overflow property other than visible
249
- if (jQuery.browser.mozilla && parent != elem && jQuery.css(parent, 'overflow') != 'visible') {
250
- x += bl;
251
- y += bt;
252
- }
253
-
254
- // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
255
- if (jQuery.css(parent, 'position') == 'absolute') absparent = true;
256
- // IE does not include the border on the body if an element is position static and without an absolute or relative parent
257
- if (jQuery.css(parent, 'position') == 'relative') relparent = true;
258
- }
259
-
260
- if (options.scroll) {
261
- // Need to get scroll offsets in-between offsetParents
262
- op = parent.offsetParent;
263
- do {
264
- sl += parent.scrollLeft || 0;
265
- st += parent.scrollTop || 0;
266
-
267
- parent = parent.parentNode;
268
-
269
- // Mozilla removes the border if the parent has overflow property other than visible
270
- if (jQuery.browser.mozilla && parent != elem && parent != op && jQuery.css(parent, 'overflow') != 'visible') {
271
- x += parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;
272
- y += parseInt(jQuery.css(parent, 'borderTopWidth')) || 0;
273
- }
274
- } while (op && parent != op);
275
- } else
276
- parent = parent.offsetParent;
277
-
278
- if (parent && (parent.tagName.toLowerCase() == 'body' || parent.tagName.toLowerCase() == 'html')) {
279
- // Safari and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
280
- if ((jQuery.browser.safari || (jQuery.browser.msie && jQuery.boxModel)) && jQuery.css(elem, 'position') != 'absolute') {
281
- x += parseInt(jQuery.css(parent, 'marginLeft')) || 0;
282
- y += parseInt(jQuery.css(parent, 'marginTop')) || 0;
283
- }
284
- // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
285
- // IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
286
- if ( (jQuery.browser.mozilla && !absparent) ||
287
- (jQuery.browser.msie && jQuery.css(elem, 'position') == 'static' && (!relparent || !absparent)) ) {
288
- x += parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;
289
- y += parseInt(jQuery.css(parent, 'borderTopWidth')) || 0;
290
- }
291
- break; // Exit the loop
292
- }
293
- } while (parent);
294
-
295
- if ( !options.margin) {
296
- x -= parseInt(jQuery.css(elem, 'marginLeft')) || 0;
297
- y -= parseInt(jQuery.css(elem, 'marginTop')) || 0;
298
- }
299
-
300
- // Safari and Opera do not add the border for the element
301
- if ( options.border && (jQuery.browser.safari || jQuery.browser.opera) ) {
302
- x += parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0;
303
- y += parseInt(jQuery.css(elem, 'borderTopWidth')) || 0;
304
- } else if ( !options.border && !(jQuery.browser.safari || jQuery.browser.opera) ) {
305
- x -= parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0;
306
- y -= parseInt(jQuery.css(elem, 'borderTopWidth')) || 0;
307
- }
308
-
309
- if ( options.padding ) {
310
- x += parseInt(jQuery.css(elem, 'paddingLeft')) || 0;
311
- y += parseInt(jQuery.css(elem, 'paddingTop')) || 0;
312
- }
313
-
314
- // Opera thinks offset is scroll offset for display: inline elements
315
- if (options.scroll && jQuery.browser.opera && jQuery.css(elem, 'display') == 'inline') {
316
- sl -= elem.scrollLeft || 0;
317
- st -= elem.scrollTop || 0;
318
- }
319
-
320
- var returnValue = options.scroll ? { top: y - st, left: x - sl, scrollTop: st, scrollLeft: sl }
321
- : { top: y, left: x };
322
-
323
- if (returnObject) { jQuery.extend(returnObject, returnValue); return this; }
324
- else { return returnValue; }
325
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-admin/js/jquery-ui.js DELETED
@@ -1 +0,0 @@
1
- eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('(6(C){C.f={1w:{1l:6(E,F,H){8 G=C.f[E].2N;1z(8 D 6J H){G.2K[D]=G.2K[D]||[];G.2K[D].25([F,H[D]])}},1F:6(D,F,E){8 H=D.2K[F];5(!H){e}1z(8 G=0;G<H.U;G++){5(D.b[H[G][0]]){H[G][1].2E(D.i,E)}}}},3t:{},h:6(D){5(C.f.3t[D]){e C.f.3t[D]}8 E=C(\'<2m 52="f-6I">\').1b(D).h({W:"1r",7:"-4S",c:"-4S",3m:"43"}).1T("1e");C.f.3t[D]=!!((!(/2f|6F/).1h(E.h("1R"))||(/^[1-9]/).1h(E.h("q"))||(/^[1-9]/).1h(E.h("r"))||!(/4O/).1h(E.h("6K"))||!(/6L|6P\\(0, 0, 0, 0\\)/).1h(E.h("6O"))));6u{C("1e").4R(0).53(E.4R(0))}7f(F){}e C.f.3t[D]},74:6(D){C(D).1P("3v","54").h("4N","4O")},71:6(D){C(D).1P("3v","6Q").h("4N","")},5P:6(G,E){8 D=/7/.1h(E||"7")?"14":"13",F=o;5(G[D]>0){e z}G[D]=1;F=G[D]>0?z:o;G[D]=0;e F}};8 B=C.4a.1y;C.4a.1y=6(){C("*",4).1l(4).1N("1y");e B.2E(4,5n)};6 A(E,F,G){8 D=C[E][F].4C||[];D=(3s D=="41"?D.49(/,?\\s+/):D);e(C.3q(G,D)!=-1)}C.2k=6(E,D){8 F=E.49(".")[0];E=E.49(".")[1];C.4a[E]=6(J){8 H=(3s J=="41"),I=5I.2N.5N.1F(5n,1);5(H&&A(F,E,J)){8 G=C.v(4[0],E);e(G?G[J].2E(G,I):1U)}e 4.1n(6(){8 K=C.v(4,E);5(H&&K&&C.32(K[J])){K[J].2E(K,I)}11{5(!H){C.v(4,E,6g C[F][E](4,J))}}})};C[F][E]=6(I,H){8 G=4;4.2o=E;4.5k=F+"-"+E;4.b=C.2c({},C.2k.2v,C[F][E].2v,H);4.i=C(I).1X("2Y."+E,6(L,J,K){e G.2Y(J,K)}).1X("45."+E,6(K,J){e G.45(J)}).1X("1y",6(){e G.2i()});4.3f()};C[F][E].2N=C.2c({},C.2k.2N,D)};C.2k.2N={3f:6(){},2i:6(){4.i.2n(4.2o)},45:6(D){e 4.b[D]},2Y:6(D,E){4.b[D]=E;5(D=="12"){4.i[E?"1b":"1B"](4.5k+"-12")}},4z:6(){4.2Y("12",o)},4u:6(){4.2Y("12",z)}};C.2k.2v={12:o};C.f.3C={4b:6(){8 D=4;4.i.1X("6e."+4.2o,6(E){e D.58(E)});5(C.1O.2u){4.57=4.i.1P("3v");4.i.1P("3v","54")}4.68=o},44:6(){4.i.21("."+4.2o);(C.1O.2u&&4.i.1P("3v",4.57))},58:6(F){(4.27&&4.3k(F));4.3L=F;8 E=4,G=(F.6a==1),D=(3s 4.b.38=="41"?C(F.26).3w().1l(F.26).28(4.b.38).U:o);5(!G||D||!4.42(F)){e z}4.3J=!4.b.39;5(!4.3J){4.6b=3p(6(){E.3J=z},4.b.39)}5(4.4k(F)&&4.4i(F)){4.27=(4.33(F)!==o);5(!4.27){F.6c();e z}}4.4c=6(H){e E.5h(H)};4.4j=6(H){e E.3k(H)};C(l).1X("59."+4.2o,4.4c).1X("5a."+4.2o,4.4j);e o},5h:6(D){5(C.1O.2u&&!D.6d){e 4.3k(D)}5(4.27){4.2p(D);e o}5(4.4k(D)&&4.4i(D)){4.27=(4.33(4.3L,D)!==o);(4.27?4.2p(D):4.3k(D))}e!4.27},3k:6(D){C(l).21("59."+4.2o,4.4c).21("5a."+4.2o,4.4j);5(4.27){4.27=o;4.2O(D)}e o},4k:6(D){e(1m.3u(1m.1V(4.3L.1G-D.1G),1m.1V(4.3L.1L-D.1L))>=4.b.3y)},4i:6(D){e 4.3J},33:6(D){},2p:6(D){},2O:6(D){},42:6(D){e z}};C.f.3C.2v={38:1k,3y:1,39:0}})(3h);(6(A){A.2k("f.17",A.2c({},A.f.3C,{3f:6(){8 B=4.b;5(B.k=="4g"&&!(/(18|1r|1Z)/).1h(4.i.h("W"))){4.i.h("W","18")}4.i.1b("f-17");(B.12&&4.i.1b("f-17-12"));4.4b()},33:6(F){8 H=4.b;5(4.k||H.12||A(F.26).5e(".f-6f-30")){e o}8 C=!4.b.30||!A(4.b.30,4.i).U?z:o;A(4.b.30,4.i).3l("*").4M().1n(6(){5(4==F.26){C=z}});5(!C){e o}5(A.f.1A){A.f.1A.4P=4}4.k=A.32(H.k)?A(H.k.2E(4.i[0],[F])):(H.k=="2W"?4.i.2W():4.i);5(!4.k.3w("1e").U){4.k.1T((H.1T=="n"?4.i[0].1J:H.1T))}5(4.k[0]!=4.i[0]&&!(/(1Z|1r)/).1h(4.k.h("W"))){4.k.h("W","1r")}4.1c={c:(Z(4.i.h("4W"),10)||0),7:(Z(4.i.h("4X"),10)||0)};4.1K=4.k.h("W");4.d=4.i.d();4.d={7:4.d.7-4.1c.7,c:4.d.c-4.1c.c};4.d.t={c:F.1G-4.d.c,7:F.1L-4.d.7};4.X=4.k.X();8 B=4.X.d();5(4.X[0]==l.1e&&A.1O.6m){B={7:0,c:0}}4.d.n={7:B.7+(Z(4.X.h("2I"),10)||0),c:B.c+(Z(4.X.h("2H"),10)||0)};8 E=4.i.W();4.d.18=4.1K=="18"?{7:E.7-(Z(4.k.h("7"),10)||0)+4.X[0].14,c:E.c-(Z(4.k.h("c"),10)||0)+4.X[0].13}:{7:0,c:0};4.1D=4.2D(F);4.V={r:4.k.2C(),q:4.k.2B()};5(H.1s){5(H.1s.c!=1U){4.d.t.c=H.1s.c+4.1c.c}5(H.1s.3r!=1U){4.d.t.c=4.V.r-H.1s.3r+4.1c.c}5(H.1s.7!=1U){4.d.t.7=H.1s.7+4.1c.7}5(H.1s.3T!=1U){4.d.t.7=4.V.q-H.1s.3T+4.1c.7}}5(H.m){5(H.m=="n"){H.m=4.k[0].1J}5(H.m=="l"||H.m=="1H"){4.m=[0-4.d.18.c-4.d.n.c,0-4.d.18.7-4.d.n.7,A(H.m=="l"?l:1H).r()-4.d.18.c-4.d.n.c-4.V.r-4.1c.c-(Z(4.i.h("3X"),10)||0),(A(H.m=="l"?l:1H).q()||l.1e.1J.3W)-4.d.18.7-4.d.n.7-4.V.q-4.1c.7-(Z(4.i.h("3V"),10)||0)]}5(!(/^(l|1H|n)$/).1h(H.m)){8 D=A(H.m)[0];8 G=A(H.m).d();4.m=[G.c+(Z(A(D).h("2H"),10)||0)-4.d.18.c-4.d.n.c,G.7+(Z(A(D).h("2I"),10)||0)-4.d.18.7-4.d.n.7,G.c+1m.3u(D.4U,D.2M)-(Z(A(D).h("2H"),10)||0)-4.d.18.c-4.d.n.c-4.V.r-4.1c.c-(Z(4.i.h("3X"),10)||0),G.7+1m.3u(D.3W,D.2R)-(Z(A(D).h("2I"),10)||0)-4.d.18.7-4.d.n.7-4.V.q-4.1c.7-(Z(4.i.h("3V"),10)||0)]}}4.19("1M",F);4.V={r:4.k.2C(),q:4.k.2B()};5(A.f.1A&&!H.3Q){A.f.1A.4Q(4,F)}4.k.1b("f-17-40");4.2p(F);e z},1I:6(C,D){5(!D){D=4.W}8 B=C=="1r"?1:-1;e{7:(D.7+4.d.18.7*B+4.d.n.7*B-(4.1K=="1Z"||(4.1K=="1r"&&4.X[0]==l.1e)?0:4.X[0].14)*B+(4.1K=="1Z"?A(l).14():0)*B+4.1c.7*B),c:(D.c+4.d.18.c*B+4.d.n.c*B-(4.1K=="1Z"||(4.1K=="1r"&&4.X[0]==l.1e)?0:4.X[0].13)*B+(4.1K=="1Z"?A(l).13():0)*B+4.1c.c*B)}},2D:6(E){8 F=4.b;8 B={7:(E.1L-4.d.t.7-4.d.18.7-4.d.n.7+(4.1K=="1Z"||(4.1K=="1r"&&4.X[0]==l.1e)?0:4.X[0].14)-(4.1K=="1Z"?A(l).14():0)),c:(E.1G-4.d.t.c-4.d.18.c-4.d.n.c+(4.1K=="1Z"||(4.1K=="1r"&&4.X[0]==l.1e)?0:4.X[0].13)-(4.1K=="1Z"?A(l).13():0))};5(!4.1D){e B}5(4.m){5(B.c<4.m[0]){B.c=4.m[0]}5(B.7<4.m[1]){B.7=4.m[1]}5(B.c>4.m[2]){B.c=4.m[2]}5(B.7>4.m[3]){B.7=4.m[3]}}5(F.1q){8 D=4.1D.7+1m.3U((B.7-4.1D.7)/F.1q[1])*F.1q[1];B.7=4.m?(!(D<4.m[1]||D>4.m[3])?D:(!(D<4.m[1])?D-F.1q[1]:D+F.1q[1])):D;8 C=4.1D.c+1m.3U((B.c-4.1D.c)/F.1q[0])*F.1q[0];B.c=4.m?(!(C<4.m[0]||C>4.m[2])?C:(!(C<4.m[0])?C-F.1q[0]:C+F.1q[0])):C}e B},2p:6(B){4.W=4.2D(B);4.1C=4.1I("1r");4.W=4.19("29",B)||4.W;5(!4.b.2t||4.b.2t!="y"){4.k[0].2h.c=4.W.c+"2F"}5(!4.b.2t||4.b.2t!="x"){4.k[0].2h.7=4.W.7+"2F"}5(A.f.1A){A.f.1A.29(4,B)}e o},2O:6(C){8 D=o;5(A.f.1A&&!4.b.3Q){8 D=A.f.1A.5A(4,C)}5((4.b.24=="6o"&&!D)||(4.b.24=="6p"&&D)||4.b.24===z){8 B=4;A(4.k).3b(4.1D,Z(4.b.24,10)||3Z,6(){B.19("1E",C);B.2w()})}11{4.19("1E",C);4.2w()}e o},2w:6(){4.k.1B("f-17-40");5(4.b.k!="4g"&&!4.2Z){4.k.1y()}4.k=1k;4.2Z=o},2K:{},4f:6(B){e{k:4.k,W:4.W,3N:4.1C,b:4.b}},19:6(C,B){A.f.1w.1F(4,C,[B,4.4f()]);5(C=="29"){4.1C=4.1I("1r")}e 4.i.1N(C=="29"?C:"29"+C,[B,4.4f()],4.b[C])},2i:6(){5(!4.i.v("17")){e}4.i.2n("17").21(".17").1B("f-17");4.44()}}));A.2c(A.f.17,{2v:{1T:"n",2t:o,38:":5s",39:0,3y:1,k:"4g"}});A.f.1w.1l("17","1R",{1M:6(D,C){8 B=A("1e");5(B.h("1R")){C.b.2G=B.h("1R")}B.h("1R",C.b.1R)},1E:6(C,B){5(B.b.2G){A("1e").h("1R",B.b.2G)}}});A.f.1w.1l("17","1t",{1M:6(D,C){8 B=A(C.k);5(B.h("1t")){C.b.2S=B.h("1t")}B.h("1t",C.b.1t)},1E:6(C,B){5(B.b.2S){A(B.k).h("1t",B.b.2S)}}});A.f.1w.1l("17","1v",{1M:6(D,C){8 B=A(C.k);5(B.h("1v")){C.b.2U=B.h("1v")}B.h("1v",C.b.1v)},1E:6(C,B){5(B.b.2U){A(B.k).h("1v",B.b.2U)}}});A.f.1w.1l("17","3M",{1M:6(C,B){A(B.b.3M===z?"6k":B.b.3M).1n(6(){A(\'<2m 52="f-17-3M" 2h="6i: #62;"></2m>\').h({r:4.2M+"2F",q:4.2R+"2F",W:"1r",1v:"0.6j",1t:5w}).h(A(4).d()).1T("1e")})},1E:6(C,B){A("2m.6q").1n(6(){4.1J.53(4)})}});A.f.1w.1l("17","1Y",{1M:6(D,C){8 E=C.b;8 B=A(4).v("17");E.1p=E.1p||20;E.1o=E.1o||20;B.1j=6(F){3E{5(/2f|1Y/.1h(F.h("2e"))||(/2f|1Y/).1h(F.h("2e-y"))){e F}F=F.n()}35(F[0].1J);e A(l)}(4);B.1f=6(F){3E{5(/2f|1Y/.1h(F.h("2e"))||(/2f|1Y/).1h(F.h("2e-x"))){e F}F=F.n()}35(F[0].1J);e A(l)}(4);5(B.1j[0]!=l&&B.1j[0].2s!="2r"){B.2Q=B.1j.d()}5(B.1f[0]!=l&&B.1f[0].2s!="2r"){B.2L=B.1f.d()}},29:6(D,C){8 E=C.b;8 B=A(4).v("17");5(B.1j[0]!=l&&B.1j[0].2s!="2r"){5((B.2Q.7+B.1j[0].2R)-D.1L<E.1p){B.1j[0].14=B.1j[0].14+E.1o}5(D.1L-B.2Q.7<E.1p){B.1j[0].14=B.1j[0].14-E.1o}}11{5(D.1L-A(l).14()<E.1p){A(l).14(A(l).14()-E.1o)}5(A(1H).q()-(D.1L-A(l).14())<E.1p){A(l).14(A(l).14()+E.1o)}}5(B.1f[0]!=l&&B.1f[0].2s!="2r"){5((B.2L.c+B.1f[0].2M)-D.1G<E.1p){B.1f[0].13=B.1f[0].13+E.1o}5(D.1G-B.2L.c<E.1p){B.1f[0].13=B.1f[0].13-E.1o}}11{5(D.1G-A(l).13()<E.1p){A(l).13(A(l).13()-E.1o)}5(A(1H).r()-(D.1G-A(l).13())<E.1p){A(l).13(A(l).13()+E.1o)}}}});A.f.1w.1l("17","4m",{1M:6(D,C){8 B=A(4).v("17");B.2A=[];A(C.b.4m===z?".f-17":C.b.4m).1n(6(){8 F=A(4);8 E=F.d();5(4!=B.i[0]){B.2A.25({1g:4,r:F.2C(),q:F.2B(),7:E.7,c:E.c})}})},29:6(J,N){8 I=A(4).v("17");8 L=N.b.5Z||20;8 D=N.3N.c,C=D+I.V.r,P=N.3N.7,O=P+I.V.q;1z(8 H=I.2A.U-1;H>=0;H--){8 E=I.2A[H].c,B=E+I.2A[H].r,R=I.2A[H].7,M=R+I.2A[H].q;5(!((E-L<D&&D<B+L&&R-L<P&&P<M+L)||(E-L<D&&D<B+L&&R-L<O&&O<M+L)||(E-L<C&&C<B+L&&R-L<P&&P<M+L)||(E-L<C&&C<B+L&&R-L<O&&O<M+L))){3g}5(N.b.5c!="5M"){8 K=1m.1V(R-O)<=20;8 Q=1m.1V(M-P)<=20;8 G=1m.1V(E-C)<=20;8 F=1m.1V(B-D)<=20;5(K){N.W.7=I.1I("18",{7:R-I.V.q,c:0}).7}5(Q){N.W.7=I.1I("18",{7:M,c:0}).7}5(G){N.W.c=I.1I("18",{7:0,c:E-I.V.r}).c}5(F){N.W.c=I.1I("18",{7:0,c:B}).c}}5(N.b.5c!="5K"){8 K=1m.1V(R-P)<=20;8 Q=1m.1V(M-O)<=20;8 G=1m.1V(E-D)<=20;8 F=1m.1V(B-C)<=20;5(K){N.W.7=I.1I("18",{7:R,c:0}).7}5(Q){N.W.7=I.1I("18",{7:M-I.V.q,c:0}).7}5(G){N.W.c=I.1I("18",{7:0,c:E}).c}5(F){N.W.c=I.1I("18",{7:0,c:B-I.V.r}).c}}}}});A.f.1w.1l("17","5d",{1M:6(D,C){8 B=A(4).v("17");B.3x=[];A(C.b.5d).1n(6(){5(A.v(4,"15")){8 E=A.v(4,"15");B.3x.25({p:E,5l:E.b.24});E.3Y();E.19("4T",D,B)}})},1E:6(D,C){8 B=A(4).v("17");A.1n(B.3x,6(){5(4.p.2X){4.p.2X=0;B.2Z=z;4.p.2Z=o;5(4.5l){4.p.b.24=z}4.p.2O(D);4.p.i.1N("5X",[D,A.2c(4.p.f(),{5f:B.i})],4.p.b.5H);4.p.b.k=4.p.b.4l}11{4.p.19("5D",D,B)}})},29:6(F,E){8 D=A(4).v("17"),B=4;8 C=6(K){8 H=K.c,J=H+K.r,I=K.7,G=I+K.q;e(H<(4.1C.c+4.d.t.c)&&(4.1C.c+4.d.t.c)<J&&I<(4.1C.7+4.d.t.7)&&(4.1C.7+4.d.t.7)<G)};A.1n(D.3x,6(G){5(C.1F(D,4.p.1S)){5(!4.p.2X){4.p.2X=1;4.p.Y=A(B).2W().1T(4.p.i).v("15-1g",z);4.p.b.4l=4.p.b.k;4.p.b.k=6(){e E.k[0]};F.26=4.p.Y[0];4.p.42(F,z);4.p.33(F,z,z);4.p.d.t.7=D.d.t.7;4.p.d.t.c=D.d.t.c;4.p.d.n.c-=D.d.n.c-4.p.d.n.c;4.p.d.n.7-=D.d.n.7-4.p.d.n.7;D.19("5Y",F)}5(4.p.Y){4.p.2p(F)}}11{5(4.p.2X){4.p.2X=0;4.p.2Z=z;4.p.b.24=o;4.p.2O(F,z);4.p.b.k=4.p.b.4l;4.p.Y.1y();5(4.p.1d){4.p.1d.1y()}D.19("60",F)}}})}});A.f.1w.1l("17","2P",{1M:6(D,B){8 C=A.5U(A(B.b.2P.5Q)).22(6(F,E){e(Z(A(F).h("1t"),10)||B.b.2P.3d)-(Z(A(E).h("1t"),10)||B.b.2P.3d)});A(C).1n(6(E){4.2h.1t=B.b.2P.3d+E});4[0].2h.1t=B.b.2P.3d+C.U}})})(3h);(6(B){6 A(E,D){8 C=B.1O.4F&&B.1O.5R<5S;5(E.5j&&!C){e E.5j(D)}5(E.5i){e!!(E.5i(D)&16)}35(D=D.1J){5(D==E){e z}}e o}B.2k("f.15",B.2c({},B.f.3C,{3f:6(){8 C=4.b;4.1S={};4.i.1b("f-15");4.4J();4.2a=4.u.U?(/c|3r/).1h(4.u[0].1g.h("70")):o;5(!(/(18|1r|1Z)/).1h(4.i.h("W"))){4.i.h("W","18")}4.d=4.i.d();4.4b()},2K:{},f:6(C){e{k:(C||4)["k"],1d:(C||4)["1d"]||B([]),W:(C||4)["W"],3N:(C||4)["1C"],b:4.b,i:4.i,1g:(C||4)["Y"],5f:C?C.i:1k}},19:6(F,E,C,D){B.f.1w.1F(4,F,[E,4.f(C)]);5(!D){4.i.1N(F=="22"?F:"22"+F,[E,4.f(C)],4.b[F])}},5G:6(E){8 C=(B.32(4.b.u)?4.b.u.1F(4.i):B(4.b.u,4.i)).3B(".f-15-k");8 D=[];E=E||{};C.1n(6(){8 F=(B(4).1P(E.6S||"2y")||"").6U(E.5o||(/(.+)[-=4o](.+)/));5(F){D.25((E.51||F[1])+"[]="+(E.51&&E.5o?F[1]:F[2]))}});e D.5b("&")},5E:6(C){8 D=(B.32(4.b.u)?4.b.u.1F(4.i):B(4.b.u,4.i)).3B(".f-15-k");8 E=[];D.1n(6(){E.25(B(4).1P(C||"2y"))});e E},4E:6(J){8 E=4.1C.c,D=E+4.V.r,I=4.1C.7,H=I+4.V.q;8 F=J.c,C=F+J.r,K=J.7,G=K+J.q;5(4.b.3c=="4V"||4.b.6W||(4.b.3c=="4n"&&4.V[4.2a?"r":"q"]>J[4.2a?"r":"q"])){e(I+4.d.t.7>K&&I+4.d.t.7<G&&E+4.d.t.c>F&&E+4.d.t.c<C)}11{e(F<E+(4.V.r/2)&&D-(4.V.r/2)<C&&K<I+(4.V.q/2)&&H-(4.V.q/2)<G)}},5u:6(J){8 E=4.1C.c,D=E+4.V.r,I=4.1C.7,H=I+4.V.q;8 F=J.c,C=F+J.r,K=J.7,G=K+J.q;5(4.b.3c=="4V"||(4.b.3c=="4n"&&4.V[4.2a?"r":"q"]>J[4.2a?"r":"q"])){5(!(I+4.d.t.7>K&&I+4.d.t.7<G&&E+4.d.t.c>F&&E+4.d.t.c<C)){e o}5(4.2a){5(E+4.d.t.c>F&&E+4.d.t.c<F+J.r/2){e 2}5(E+4.d.t.c>F+J.r/2&&E+4.d.t.c<C){e 1}}11{5(I+4.d.t.7>K&&I+4.d.t.7<K+J.q/2){e 2}5(I+4.d.t.7>K+J.q/2&&I+4.d.t.7<G){e 1}}}11{5(!(F<E+(4.V.r/2)&&D-(4.V.r/2)<C&&K<I+(4.V.q/2)&&H-(4.V.q/2)<G)){e o}5(4.2a){5(D>F&&E<F){e 2}5(E<C&&D>C){e 1}}11{5(H>K&&I<K){e 1}5(I<G&&H>G){e 2}}}e o},4J:6(){4.3Y();4.3P()},3Y:6(){4.u=[];4.w=[4];8 D=4.u;8 C=4;8 F=[[B.32(4.b.u)?4.b.u.1F(4.i,1k,{b:4.b,1g:4.Y}):B(4.b.u,4.i),4]];5(4.b.4d){1z(8 G=4.b.4d.U-1;G>=0;G--){8 I=B(4.b.4d[G]);1z(8 E=I.U-1;E>=0;E--){8 H=B.v(I[E],"15");5(H&&!H.b.12){F.25([B.32(H.b.u)?H.b.u.1F(H.i):B(H.b.u,H.i),H]);4.w.25(H)}}}}1z(8 G=F.U-1;G>=0;G--){F[G][0].1n(6(){B.v(4,"15-1g",F[G][1]);D.25({1g:B(4),p:F[G][1],r:0,q:0,c:0,7:0})})}},3P:6(D){5(4.X){8 C=4.X.d();4.d.n={7:C.7+4.3i.7,c:C.c+4.3i.c}}1z(8 F=4.u.U-1;F>=0;F--){5(4.u[F].p!=4.3n&&4.3n&&4.u[F].1g[0]!=4.Y[0]){3g}8 E=4.b.4I?B(4.b.4I,4.u[F].1g):4.u[F].1g;5(!D){4.u[F].r=E[0].2M;4.u[F].q=E[0].2R}8 G=E.d();4.u[F].c=G.c;4.u[F].7=G.7}5(4.b.48&&4.b.48.5p){4.b.48.5p.1F(4)}11{1z(8 F=4.w.U-1;F>=0;F--){8 G=4.w[F].i.d();4.w[F].1S.c=G.c;4.w[F].1S.7=G.7;4.w[F].1S.r=4.w[F].i.2C();4.w[F].1S.q=4.w[F].i.2B()}}},2i:6(){4.i.1B("f-15 f-15-12").2n("15").21(".15");4.44();1z(8 C=4.u.U-1;C>=0;C--){4.u[C].1g.2n("15-1g")}},4h:6(E){8 C=E||4,F=C.b;5(F.1d.5J==7c){8 D=F.1d;F.1d={i:6(){e B("<2m></2m>").1b(D)[0]},34:6(G,H){H.h(G.d()).h({r:G.2C(),q:G.2B()})}}}C.1d=B(F.1d.i.1F(C.i,C.Y)).1T("1e").h({W:"1r"});F.1d.34.1F(C.i,C.Y,C.1d)},5B:6(F){1z(8 D=4.w.U-1;D>=0;D--){5(4.4E(4.w[D].1S)){5(!4.w[D].1S.2z){5(4.3n!=4.w[D]){8 I=76;8 H=1k;8 E=4.1C[4.w[D].2a?"c":"7"];1z(8 C=4.u.U-1;C>=0;C--){5(!A(4.w[D].i[0],4.u[C].1g[0])){3g}8 G=4.u[C][4.w[D].2a?"c":"7"];5(1m.1V(G-E)<I){I=1m.1V(G-E);H=4.u[C]}}5(!H&&!4.b.5z){3g}5(4.1d){4.1d.1y()}5(4.w[D].b.1d){4.w[D].4h(4)}11{4.1d=1k}4.3n=4.w[D];H?4.3O(F,H,1k,z):4.3O(F,1k,4.w[D].i,z);4.19("46",F);4.w[D].19("46",F,4)}4.w[D].19("2z",F,4);4.w[D].1S.2z=1}}11{5(4.w[D].1S.2z){4.w[D].19("5C",F,4);4.w[D].1S.2z=0}}}},42:6(G,F){5(4.b.12||4.b.4s=="78"){e o}4.3Y();8 E=1k,D=4,C=B(G.26).3w().1n(6(){5(B.v(4,"15-1g")==D){E=B(4);e o}});5(B.v(G.26,"15-1g")==D){E=B(G.26)}5(!E){e o}5(4.b.30&&!F){8 H=o;B(4.b.30,E).3l("*").4M().1n(6(){5(4==G.26){H=z}});5(!H){e o}}4.Y=E;e z},33:6(H,F,C){8 J=4.b;4.3n=4;4.3P();4.k=3s J.k=="6"?B(J.k.2E(4.i[0],[H,4.Y])):4.Y.2W();5(!4.k.3w("1e").U){B(J.1T!="n"?J.1T:4.Y[0].1J)[0].5q(4.k[0])}4.k.h({W:"1r",2w:"6B"}).1b("f-15-k");4.1c={c:(Z(4.Y.h("4W"),10)||0),7:(Z(4.Y.h("4X"),10)||0)};4.d=4.Y.d();4.d={7:4.d.7-4.1c.7,c:4.d.c-4.1c.c};4.d.t={c:H.1G-4.d.c,7:H.1L-4.d.7};4.X=4.k.X();8 D=4.X.d();4.3i={7:(Z(4.X.h("2I"),10)||0),c:(Z(4.X.h("2H"),10)||0)};4.d.n={7:D.7+4.3i.7,c:D.c+4.3i.c};4.1D=4.2D(H);4.4e={37:4.Y.37()[0],n:4.Y.n()[0]};4.V={r:4.k.2C(),q:4.k.2B()};5(J.1d){4.4h()}4.19("1M",H);4.V={r:4.k.2C(),q:4.k.2B()};5(J.1s){5(J.1s.c!=1U){4.d.t.c=J.1s.c}5(J.1s.3r!=1U){4.d.t.c=4.V.r-J.1s.3r}5(J.1s.7!=1U){4.d.t.7=J.1s.7}5(J.1s.3T!=1U){4.d.t.7=4.V.q-J.1s.3T}}5(J.m){5(J.m=="n"){J.m=4.k[0].1J}5(J.m=="l"||J.m=="1H"){4.m=[0-4.d.n.c,0-4.d.n.7,B(J.m=="l"?l:1H).r()-4.d.n.c-4.V.r-4.1c.c-(Z(4.i.h("3X"),10)||0),(B(J.m=="l"?l:1H).q()||l.1e.1J.3W)-4.d.n.7-4.V.q-4.1c.7-(Z(4.i.h("3V"),10)||0)]}5(!(/^(l|1H|n)$/).1h(J.m)){8 G=B(J.m)[0];8 I=B(J.m).d();4.m=[I.c+(Z(B(G).h("2H"),10)||0)-4.d.n.c,I.7+(Z(B(G).h("2I"),10)||0)-4.d.n.7,I.c+1m.3u(G.4U,G.2M)-(Z(B(G).h("2H"),10)||0)-4.d.n.c-4.V.r-4.1c.c-(Z(4.Y.h("3X"),10)||0),I.7+1m.3u(G.3W,G.2R)-(Z(B(G).h("2I"),10)||0)-4.d.n.7-4.V.q-4.1c.7-(Z(4.Y.h("3V"),10)||0)]}}5(4.b.1d!="2W"){4.Y.h("5t","6G")}5(!C){1z(8 E=4.w.U-1;E>=0;E--){4.w[E].19("4T",H,4)}}5(B.f.1A){B.f.1A.4P=4}5(B.f.1A&&!J.3Q){B.f.1A.4Q(4,H)}4.40=z;4.2p(H);e z},1I:6(D,E){5(!E){E=4.W}8 C=D=="1r"?1:-1;e{7:(E.7+4.d.n.7*C-(4.X[0]==l.1e?0:4.X[0].14)*C+4.1c.7*C),c:(E.c+4.d.n.c*C-(4.X[0]==l.1e?0:4.X[0].13)*C+4.1c.c*C)}},2D:6(F){8 G=4.b;8 C={7:(F.1L-4.d.t.7-4.d.n.7+(4.X[0]==l.1e?0:4.X[0].14)),c:(F.1G-4.d.t.c-4.d.n.c+(4.X[0]==l.1e?0:4.X[0].13))};5(!4.1D){e C}5(4.m){5(C.c<4.m[0]){C.c=4.m[0]}5(C.7<4.m[1]){C.7=4.m[1]}5(C.c>4.m[2]){C.c=4.m[2]}5(C.7>4.m[3]){C.7=4.m[3]}}5(G.1q){8 E=4.1D.7+1m.3U((C.7-4.1D.7)/G.1q[1])*G.1q[1];C.7=4.m?(!(E<4.m[1]||E>4.m[3])?E:(!(E<4.m[1])?E-G.1q[1]:E+G.1q[1])):E;8 D=4.1D.c+1m.3U((C.c-4.1D.c)/G.1q[0])*G.1q[0];C.c=4.m?(!(D<4.m[0]||D>4.m[2])?D:(!(D<4.m[0])?D-G.1q[0]:D+G.1q[0])):D}e C},2p:6(D){4.W=4.2D(D);4.1C=4.1I("1r");B.f.1w.1F(4,"22",[D,4.f()]);4.1C=4.1I("1r");4.k[0].2h.c=4.W.c+"2F";4.k[0].2h.7=4.W.7+"2F";1z(8 C=4.u.U-1;C>=0;C--){8 E=4.5u(4.u[C]);5(!E){3g}5(4.u[C].1g[0]!=4.Y[0]&&4.Y[E==1?"6y":"37"]()[0]!=4.u[C].1g[0]&&!A(4.Y[0],4.u[C].1g[0])&&(4.b.4s=="6C-6z"?!A(4.i[0],4.u[C].1g[0]):z)){4.5v=E==1?"5x":"6R";4.3O(D,4.u[C]);4.19("46",D);79}}4.5B(D);5(B.f.1A){B.f.1A.29(4,D)}4.i.1N("22",[D,4.f()],4.b.22);e o},3O:6(H,G,D,F){D?D[0].5q(4.Y[0]):G.1g[0].1J.4y(4.Y[0],(4.5v=="5x"?G.1g[0]:G.1g[0].7d));4.3a=4.3a?++4.3a:1;8 E=4,C=4.3a;1H.3p(6(){5(C==E.3a){E.3P(!F)}},0);5(4.b.1d){4.b.1d.34.1F(4.i,4.Y,4.1d)}},2O:6(E,D){5(B.f.1A&&!4.b.3Q){B.f.1A.5A(4,E)}5(4.b.24){8 C=4;8 F=C.Y.d();5(C.1d){C.1d.3b({1v:"5y"},(Z(4.b.24,10)||3Z)-50)}B(4.k).3b({c:F.c-4.d.n.c-C.1c.c+(4.X[0]==l.1e?0:4.X[0].13),7:F.7-4.d.n.7-C.1c.7+(4.X[0]==l.1e?0:4.X[0].14)},Z(4.b.24,10)||3Z,6(){C.2w(E)})}11{4.2w(E,D)}e o},2w:6(E,D){5(4.4e.37!=4.Y.37().3B(".f-15-k")[0]||4.4e.n!=4.Y.n()[0]){4.19("34",E,1k,D)}5(!A(4.i[0],4.Y[0])){4.19("1y",E,1k,D);1z(8 C=4.w.U-1;C>=0;C--){5(A(4.w[C].i[0],4.Y[0])){4.w[C].19("34",E,4,D);4.w[C].19("5H",E,4,D)}}}1z(8 C=4.w.U-1;C>=0;C--){4.w[C].19("5D",E,4,D);5(4.w[C].1S.2z){4.w[C].19("5C",E,4);4.w[C].1S.2z=0}}4.40=o;5(4.2Z){4.19("1E",E,1k,D);e o}B(4.Y).h("5t","");5(4.1d){4.1d.1y()}4.k.1y();4.k=1k;4.19("1E",E,1k,D);e z}}));B.2c(B.f.15,{4C:"5G 5E",2v:{k:"2W",3c:"4n",3y:1,39:0,1Y:z,1p:20,1o:20,38:":5s",u:"> *",1t:5w,5z:z,1T:"n"}});B.f.1w.1l("15","1R",{1M:6(E,D){8 C=B("1e");5(C.h("1R")){D.b.2G=C.h("1R")}C.h("1R",D.b.1R)},1E:6(D,C){5(C.b.2G){B("1e").h("1R",C.b.2G)}}});B.f.1w.1l("15","1t",{1M:6(E,D){8 C=D.k;5(C.h("1t")){D.b.2S=C.h("1t")}C.h("1t",D.b.1t)},1E:6(D,C){5(C.b.2S){B(C.k).h("1t",C.b.2S)}}});B.f.1w.1l("15","1v",{1M:6(E,D){8 C=D.k;5(C.h("1v")){D.b.2U=C.h("1v")}C.h("1v",D.b.1v)},1E:6(D,C){5(C.b.2U){B(C.k).h("1v",C.b.2U)}}});B.f.1w.1l("15","1Y",{1M:6(E,D){8 F=D.b;8 C=B(4).v("15");C.1j=6(G){3E{5(/2f|1Y/.1h(G.h("2e"))||(/2f|1Y/).1h(G.h("2e-y"))){e G}G=G.n()}35(G[0].1J);e B(l)}(C.Y);C.1f=6(G){3E{5(/2f|1Y/.1h(G.h("2e"))||(/2f|1Y/).1h(G.h("2e-x"))){e G}G=G.n()}35(G[0].1J);e B(l)}(C.Y);5(C.1j[0]!=l&&C.1j[0].2s!="2r"){C.2Q=C.1j.d()}5(C.1f[0]!=l&&C.1f[0].2s!="2r"){C.2L=C.1f.d()}},22:6(E,D){8 F=D.b;8 C=B(4).v("15");5(C.1j[0]!=l&&C.1j[0].2s!="2r"){5((C.2Q.7+C.1j[0].2R)-E.1L<F.1p){C.1j[0].14=C.1j[0].14+F.1o}5(E.1L-C.2Q.7<F.1p){C.1j[0].14=C.1j[0].14-F.1o}}11{5(E.1L-B(l).14()<F.1p){B(l).14(B(l).14()-F.1o)}5(B(1H).q()-(E.1L-B(l).14())<F.1p){B(l).14(B(l).14()+F.1o)}}5(C.1f[0]!=l&&C.1f[0].2s!="2r"){5((C.2L.c+C.1f[0].2M)-E.1G<F.1p){C.1f[0].13=C.1f[0].13+F.1o}5(E.1G-C.2L.c<F.1p){C.1f[0].13=C.1f[0].13-F.1o}}11{5(E.1G-B(l).13()<F.1p){B(l).13(B(l).13()-F.1o)}5(B(1H).r()-(E.1G-B(l).13())<F.1p){B(l).13(B(l).13()+F.1o)}}}});B.f.1w.1l("15","2t",{22:6(E,D){8 C=B(4).v("15");5(D.b.2t=="y"){C.W.c=C.1D.c}5(D.b.2t=="x"){C.W.7=C.1D.7}}})})(3h);(6(A){A.2k("f.j",{3f:6(){4.b.2b+=".j";4.3o(z)},2Y:6(B,C){5((/^1a/).1h(B)){4.36(C)}11{4.b[B]=C;4.3o()}},U:6(){e 4.$j.U},4x:6(B){e B.5r&&B.5r.2J(/\\s/g,"4o").2J(/[^A-66-5L-9\\-4o:\\.]/g,"")||4.b.5g+A.v(B)},f:6(C,B){e{b:4.b,61:C,5F:B,2j:4.$j.2j(C)}},3o:6(O){4.$1u=A("3I:5W(a[1Q])",4.i);4.$j=4.$1u.3R(6(){e A("a",4)[0]});4.$1i=A([]);8 P=4,D=4.b;4.$j.1n(6(R,Q){5(Q.2d&&Q.2d.2J("#","")){P.$1i=P.$1i.1l(Q.2d)}11{5(A(Q).1P("1Q")!="#"){A.v(Q,"1Q.j",Q.1Q);A.v(Q,"1W.j",Q.1Q);8 T=P.4x(Q);Q.1Q="#"+T;8 S=A("#"+T);5(!S.U){S=A(D.4A).1P("2y",T).1b(D.3j).5T(P.$1i[R-1]||P.i);S.v("2i.j",z)}P.$1i=P.$1i.1l(S)}11{D.12.25(R+1)}}});5(O){4.i.1b(D.4r);4.$1i.1n(6(){8 Q=A(4);Q.1b(D.3j)});5(D.1a===1U){5(4t.2d){4.$j.1n(6(S,Q){5(Q.2d==4t.2d){D.1a=S;5(A.1O.2u||A.1O.6T){8 R=A(4t.2d),T=R.1P("2y");R.1P("2y","");3p(6(){R.1P("2y",T)},3Z)}6V(0,0);e o}})}11{5(D.2V){8 J=Z(A.2V("f-j"+A.v(P.i)),10);5(J&&P.$j[J]){D.1a=J}}11{5(P.$1u.28("."+D.1x).U){D.1a=P.$1u.2j(P.$1u.28("."+D.1x)[0])}}}}D.1a=D.1a===1k||D.1a!==1U?D.1a:0;D.12=A.7a(D.12.7b(A.3R(4.$1u.28("."+D.2x),6(R,Q){e P.$1u.2j(R)}))).22();5(A.3q(D.1a,D.12)!=-1){D.12.75(A.3q(D.1a,D.12),1)}4.$1i.1b(D.2l);4.$1u.1B(D.1x);5(D.1a!==1k){4.$1i.23(D.1a).4w().1B(D.2l);4.$1u.23(D.1a).1b(D.1x);8 K=6(){A(P.i).1N("3K",[P.2g("3K"),P.f(P.$j[D.1a],P.$1i[D.1a])],D.4w)};5(A.v(4.$j[D.1a],"1W.j")){4.1W(D.1a,K)}11{K()}}A(1H).1X("73",6(){P.$j.21(".j");P.$1u=P.$j=P.$1i=1k})}1z(8 G=0,N;N=4.$1u[G];G++){A(N)[A.3q(G,D.12)!=-1&&!A(N).31(D.1x)?"1b":"1B"](D.2x)}5(D.2q===o){4.$j.2n("2q.j")}8 C,I,B={"3d-r":0,4v:1},E="6t";5(D.2T&&D.2T.5J==5I){C=D.2T[0]||B,I=D.2T[1]||B}11{C=I=D.2T||B}8 H={3m:"",2e:"",q:""};5(!A.1O.2u){H.1v=""}6 M(R,Q,S){Q.3b(C,C.4v||E,6(){Q.1b(D.2l).h(H);5(A.1O.2u&&C.1v){Q[0].2h.28=""}5(S){L(R,S,Q)}})}6 L(R,S,Q){5(I===B){S.h("3m","43")}S.3b(I,I.4v||E,6(){S.1B(D.2l).h(H);5(A.1O.2u&&I.1v){S[0].2h.28=""}A(P.i).1N("3K",[P.2g("3K"),P.f(R,S[0])],D.4w)})}6 F(R,T,Q,S){T.1b(D.1x).6H().1B(D.1x);M(R,Q,S)}4.$j.21(".j").1X(D.2b,6(){8 T=A(4).3w("3I:23(0)"),Q=P.$1i.28(":5O"),S=A(4.2d);5((T.31(D.1x)&&!D.3A)||T.31(D.2x)||A(4).31(D.3e)||A(P.i).1N("5m",[P.2g("5m"),P.f(4,S[0])],D.36)===o){4.3S();e o}P.b.1a=P.$j.2j(4);5(D.3A){5(T.31(D.1x)){P.b.1a=1k;T.1B(D.1x);P.$1i.1E();M(4,Q);4.3S();e o}11{5(!Q.U){P.$1i.1E();8 R=4;P.1W(P.$j.2j(4),6(){T.1b(D.1x).1b(D.4B);L(R,S)});4.3S();e o}}}5(D.2V){A.2V("f-j"+A.v(P.i),P.b.1a,D.2V)}P.$1i.1E();5(S.U){8 R=4;P.1W(P.$j.2j(4),Q.U?6(){F(R,T,Q,S)}:6(){T.1b(D.1x);L(R,S)})}11{6N"3h 6M 6E: 6D 6w 6v."}5(A.1O.2u){4.3S()}e o});5(!(/^t/).1h(D.2b)){4.$j.1X("t.j",6(){e o})}},1l:6(E,D,C){5(C==1U){C=4.$j.U}8 G=4.b;8 I=A(G.4K.2J(/#\\{1Q\\}/g,E).2J(/#\\{3G\\}/g,D));I.v("2i.j",z);8 H=E.6s("#")==0?E.2J("#",""):4.4x(A("a:6x-6A",I)[0]);8 F=A("#"+H);5(!F.U){F=A(G.4A).1P("2y",H).1b(G.2l).v("2i.j",z)}F.1b(G.3j);5(C>=4.$1u.U){I.1T(4.i);F.1T(4.i[0].1J)}11{I.4y(4.$1u[C]);F.4y(4.$1i[C])}G.12=A.3R(G.12,6(K,J){e K>=C?++K:K});4.3o();5(4.$j.U==1){I.1b(G.1x);F.1B(G.2l);8 B=A.v(4.$j[0],"1W.j");5(B){4.1W(C,B)}}4.i.1N("4Z",[4.2g("4Z"),4.f(4.$j[C],4.$1i[C])],G.1l)},1y:6(B){8 D=4.b,E=4.$1u.23(B).1y(),C=4.$1i.23(B).1y();5(E.31(D.1x)&&4.$j.U>1){4.36(B+(B+1<4.$j.U?1:-1))}D.12=A.3R(A.4D(D.12,6(G,F){e G!=B}),6(G,F){e G>=B?--G:G});4.3o();4.i.1N("4G",[4.2g("4G"),4.f(E.3l("a")[0],C[0])],D.1y)},4z:6(B){8 C=4.b;5(A.3q(B,C.12)==-1){e}8 D=4.$1u.23(B).1B(C.2x);5(A.1O.4F){D.h("3m","77-43");3p(6(){D.h("3m","43")},0)}C.12=A.4D(C.12,6(F,E){e F!=B});4.i.1N("4H",[4.2g("4H"),4.f(4.$j[B],4.$1i[B])],C.4z)},4u:6(C){8 B=4,D=4.b;5(C!=D.1a){4.$1u.23(C).1b(D.2x);D.12.25(C);D.12.22();4.i.1N("4L",[4.2g("4L"),4.f(4.$j[C],4.$1i[C])],D.4u)}},36:6(B){5(3s B=="41"){B=4.$j.2j(4.$j.28("[1Q$="+B+"]")[0])}4.$j.23(B).7e(4.b.2b)},1W:6(G,K){8 L=4,D=4.b,E=4.$j.23(G),J=E[0],H=K==1U||K===o,B=E.v("1W.j");K=K||6(){};5(!B||!H&&A.v(J,"2q.j")){K();e}8 M=6(N){8 O=A(N),P=O.3l("*:6X");e P.U&&P.5e(":3B(6r)")&&P||O};8 C=6(){L.$j.28("."+D.3e).1B(D.3e).1n(6(){5(D.3H){M(4).n().3z(M(4).v("3G.j"))}});L.3D=1k};5(D.3H){8 I=M(J).3z();M(J).6Z("<4p></4p>").3l("4p").v("3G.j",I).3z(D.3H)}8 F=A.2c({},D.3F,{56:B,4q:6(O,N){A(J.2d).3z(O);C();5(D.2q){A.v(J,"2q.j",z)}A(L.i).1N("55",[L.2g("55"),L.f(L.$j[G],L.$1i[G])],D.1W);D.3F.4q&&D.3F.4q(O,N);K()}});5(4.3D){4.3D.6n();C()}E.1b(D.3e);3p(6(){L.3D=A.67(F)},0)},56:6(C,B){4.$j.23(C).2n("2q.j").v("1W.j",B)},2i:6(){8 B=4.b;4.i.21(".j").1B(B.4r).2n("j");4.$j.1n(6(){8 C=A.v(4,"1Q.j");5(C){4.1Q=C}8 D=A(4).21(".j");A.1n(["1Q","1W","2q"],6(E,F){D.2n(F+".j")})});4.$1u.1l(4.$1i).1n(6(){5(A.v(4,"2i.j")){A(4).1y()}11{A(4).1B([B.1x,B.4B,B.2x,B.3j,B.2l].5b(" "))}})},2g:6(B){e A.2b.63({4s:B,26:4.i[0]})}});A.f.j.2v={3A:o,2b:"t",12:[],2V:1k,3H:"6Y&#6l;",2q:o,5g:"f-j-",3F:{},2T:1k,4K:\'<3I><a 1Q="#{1Q}"><4Y>#{3G}</4Y></a></3I>\',4A:"<2m></2m>",4r:"f-j-65",1x:"f-j-1a",4B:"f-j-3A",2x:"f-j-12",3j:"f-j-5F",2l:"f-j-5y",3e:"f-j-64"};A.f.j.4C="U";A.2c(A.f.j.2N,{47:1k,6h:6(C,F){F=F||o;8 B=4,E=4.b.1a;6 G(){B.47=5V(6(){E=++E<B.$j.U?E:0;B.36(E)},C)}6 D(H){5(!H||H.72){69(B.47)}}5(C){G();5(!F){4.$j.1X(4.b.2b,D)}11{4.$j.1X(4.b.2b,6(){D();E=B.b.1a;G()})}}11{D();4.$j.21(4.b.2b,D)}}})})(3h);',62,450,'||||this|if|function|top|var|||options|left|offset|return|ui||css|element|tabs|helper|document|containment|parent|false|instance|height|width||click|items|data|containers|||true|||||||||||||||||||||length|helperProportions|position|offsetParent|currentItem|parseInt||else|disabled|scrollLeft|scrollTop|sortable||draggable|relative|propagate|selected|addClass|margins|placeholder|body|overflowX|item|test|panels|overflowY|null|add|Math|each|scrollSpeed|scrollSensitivity|grid|absolute|cursorAt|zIndex|lis|opacity|plugin|selectedClass|remove|for|ddmanager|removeClass|positionAbs|originalPosition|stop|call|pageX|window|convertPositionTo|parentNode|cssPosition|pageY|start|triggerHandler|browser|attr|href|cursor|containerCache|appendTo|undefined|abs|load|bind|scroll|fixed||unbind|sort|eq|revert|push|target|_mouseStarted|filter|drag|floating|event|extend|hash|overflow|auto|fakeEvent|style|destroy|index|widget|hideClass|div|removeData|widgetName|mouseDrag|cache|HTML|tagName|axis|msie|defaults|clear|disabledClass|id|over|snapElements|outerHeight|outerWidth|generatePosition|apply|px|_cursor|borderLeftWidth|borderTopWidth|replace|plugins|overflowXOffset|offsetWidth|prototype|mouseStop|stack|overflowYOffset|offsetHeight|_zIndex|fx|_opacity|cookie|clone|isOver|setData|cancelHelperRemoval|handle|hasClass|isFunction|mouseStart|update|while|select|prev|cancel|delay|counter|animate|tolerance|min|loadingClass|init|continue|jQuery|offsetParentBorders|panelClass|mouseUp|find|display|currentContainer|tabify|setTimeout|inArray|right|typeof|cssCache|max|unselectable|parents|sortables|distance|html|unselect|not|mouse|xhr|do|ajaxOptions|label|spinner|li|_mouseDelayMet|tabsshow|_mouseDownEvent|iframeFix|absolutePosition|rearrange|refreshPositions|dropBehaviour|map|blur|bottom|round|marginBottom|scrollHeight|marginRight|refreshItems|500|dragging|string|mouseCapture|block|mouseDestroy|getData|change|rotation|custom|split|fn|mouseInit|_mouseMoveDelegate|connectWith|domPosition|uiHash|original|createPlaceholder|mouseDelayMet|_mouseUpDelegate|mouseDistanceMet|_helper|snap|guess|_|em|success|navClass|type|location|disable|duration|show|tabId|insertBefore|enable|panelTemplate|unselectClass|getter|grep|intersectsWith|safari|tabsremove|tabsenable|toleranceElement|refresh|tabTemplate|tabsdisable|andSelf|MozUserSelect|none|current|prepareOffsets|get|5000px|activate|scrollWidth|pointer|marginLeft|marginTop|span|tabsadd||key|class|removeChild|on|tabsload|url|_mouseUnselectable|mouseDown|mousemove|mouseup|join|snapMode|connectToSortable|is|sender|idPrefix|mouseMove|compareDocumentPosition|contains|widgetBaseClass|shouldRevert|tabsselect|arguments|expression|refreshContainers|appendChild|title|input|visibility|intersectsWithEdge|direction|1000|down|hide|dropOnEmpty|drop|contactContainers|out|deactivate|toArray|panel|serialize|receive|Array|constructor|outer|z0|inner|slice|visible|hasScroll|group|version|522|insertAfter|makeArray|setInterval|has|sortreceive|toSortable|snapTolerance|fromSortable|tab|fff|fix|loading|nav|Za|ajax|started|clearInterval|which|_mouseDelayTimer|preventDefault|button|mousedown|resizable|new|rotate|background|001|iframe|8230|mozilla|abort|invalid|valid|DragDropIframeFix|img|indexOf|normal|try|identifier|fragment|first|next|dynamic|child|both|semi|Mismatching|Tabs|default|hidden|siblings|gen|in|backgroundImage|transparent|UI|throw|backgroundColor|rgba|off|up|attribute|opera|match|scrollTo|forcePointerForContainers|last|Loading|wrapInner|float|enableSelection|clientX|unload|disableSelection|splice|10000|inline|static|break|unique|concat|String|nextSibling|trigger|catch'.split('|'),0,{}))
 
wpsc-admin/js/product_tagcloud.js DELETED
@@ -1,125 +0,0 @@
1
- //this contains a nearly exact copy of the wordpress product tag editing functions
2
-
3
- function new_tag_remove_tag() {
4
- var id = jQuery( this ).attr( 'id' );
5
- var num = id.substr( 10 );
6
- var current_tags = jQuery( '#tags-input' ).val().split(',');
7
- delete current_tags[num];
8
- var new_tags = [];
9
- jQuery.each( current_tags, function( key, val ) {
10
- if ( val && !val.match(/^\s+$/) && '' != val ) {
11
- new_tags = new_tags.concat( val );
12
- }
13
- });
14
- jQuery( '#tags-input' ).val( new_tags.join( ',' ).replace( /\s*,+\s*/, ',' ).replace( /,+/, ',' ).replace( /,+\s+,+/, ',' ).replace( /,+\s*$/, '' ).replace( /^\s*,+/, '' ) );
15
- tag_update_quickclicks();
16
- jQuery('#newtag').focus();
17
- return false;
18
- }
19
-
20
- function tag_update_quickclicks() {
21
- if ( jQuery( '#tags-input' ).length == 0 )
22
- return;
23
- var current_tags = jQuery( '#tags-input' ).val().split(',');
24
- jQuery( '#tagchecklist' ).empty();
25
- shown = false;
26
- // jQuery.merge( current_tags, current_tags ); // this doesn't work anymore, need something to array_unique
27
- jQuery.each( current_tags, function( key, val ) {
28
- val = val.replace( /^\s+/, '' ).replace( /\s+$/, '' ); // trim
29
- if ( !val.match(/^\s+$/) && '' != val ) {
30
- txt = '<span><a id="tag-check-' + key + '" class="ntdelbutton">X</a>&nbsp;' + val + '</span> ';
31
- jQuery( '#tagchecklist' ).append( txt );
32
- jQuery( '#tag-check-' + key ).click( new_tag_remove_tag );
33
- shown = true;
34
- }
35
- });
36
- if ( shown )
37
- jQuery( '#tagchecklist' ).prepend( '<strong>Tags Used</strong><br />' );
38
- }
39
-
40
- function tag_flush_to_text(e,a) {
41
- a = a || false;
42
- var text = a ? jQuery(a).text() : jQuery('#newtag').val();
43
- var newtags = jQuery('#tags-input').val();
44
-
45
- var t = text.replace( /\s*([^,]+).*/, '$1,' );
46
- newtags += ','
47
-
48
- if ( newtags.indexOf(t) != -1 )
49
- return false;
50
-
51
- newtags += text;
52
-
53
- // massage
54
- newtags = newtags.replace( /\s+,+\s*/g, ',' ).replace( /,+/g, ',' ).replace( /,+\s+,+/g, ',' ).replace( /,+\s*$/g, '' ).replace( /^\s*,+/g, '' );
55
- jQuery('#tags-input').val( newtags );
56
- tag_update_quickclicks();
57
- if ( ! a ) {
58
- jQuery('#newtag').val('');
59
- jQuery('#newtag').focus();
60
- }
61
- return false;
62
- }
63
-
64
- function tag_save_on_publish() {
65
- if ( jQuery('#newtag').val() != postL10n.addTag )
66
- tag_flush_to_text();
67
- }
68
-
69
- function tag_press_key( e ) {
70
- if ( 13 == e.keyCode ) {
71
- tag_flush_to_text();
72
- return false;
73
- }
74
- };
75
-
76
- (function($){
77
- tagCloud = {
78
- init : function() {
79
- $('#tagcloud-link').click(function(){tagCloud.get(); $(this).unbind().click(function(){return false;}); return false;});
80
- },
81
-
82
- get : function() {
83
- $.post('admin-ajax.php', {'action':'get-tagcloud'}, function(r, stat) {
84
- if ( 0 == r || 'success' != stat )
85
- r = wpAjax.broken;
86
-
87
- r = '<p id="the-tagcloud">'+r+'</p>';
88
- $('#tagcloud-link').after($(r));
89
- $('#the-tagcloud a').click(function(){
90
- tag_flush_to_text(0,this);
91
- return false;
92
- });
93
- });
94
- }
95
- }
96
- })(jQuery);
97
-
98
- jQuery(document).ready( function($) {
99
- tagCloud.init();
100
- tag_update_quickclicks();
101
- jQuery('#tags-input').livequery(function(){
102
- jQuery(this).hide();
103
-
104
- })
105
-
106
-
107
-
108
-
109
- // add the quickadd form
110
- jQuery('#jaxtag').livequery(function(){
111
- jQuery(this).prepend('<span id="ajaxtag"><input type="text" name="newtag" id="newtag" class="form-input-tip" size="16" autocomplete="off" value="Add tag" /><input type="button" class="button" id="tagadd" value="Add" tabindex="3" /><input type="hidden"/><input type="hidden"/></span>');
112
- jQuery('#tagadd').click( tag_flush_to_text );
113
- jQuery('#newtag').focus(function() {
114
- // if ( this.value == postL10n.addTag )
115
- jQuery(this).val( '' ).removeClass( 'form-input-tip' );
116
- });
117
- tag_update_quickclicks();
118
- jQuery('#newtag').blur(function() {
119
- if ( this.value == '' )
120
- jQuery(this).val( postL10n.addTag ).addClass( 'form-input-tip' );
121
- });
122
- });
123
-
124
- });
125
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-admin/js/settings-page.js CHANGED
@@ -309,6 +309,7 @@
309
  wrapper.on( 'click', '.field-option-cell-wrapper .wpsc-button-minus', WPSC_Settings_Page.Checkout.event_delete_field_option);
310
  wrapper.on( 'click', '#wpsc-delete-checkout-set', WPSC_Settings_Page.Checkout.event_delete_checkout_set);
311
  wrapper.on( 'change', '#wpsc_form_set', WPSC_Settings_Page.Checkout.event_select_form_set);
 
312
  $('#wpsc-settings-form').on( 'submit', WPSC_Settings_Page.Checkout.event_form_submit);
313
 
314
  wrapper.find('#wpsc_checkout_list').
@@ -326,6 +327,21 @@
326
  });
327
 
328
  WPSC_Settings_Page.Checkout.new_field_count = $('.new-field').length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  },
330
 
331
  event_add_field_option : function() {
@@ -377,6 +393,7 @@
377
  var t = $(this),
378
  target_row = t.closest('tr'),
379
  id = target_row.data('field-id'),
 
380
  link = target_row.find('.edit-options'),
381
  options_row_id = 'wpsc-field-edit-options-' + id;
382
 
@@ -384,7 +401,11 @@
384
  id = target_row.data('new-field-id');
385
  options_row_id = 'wpsc-new-field-edit-options-' + id;
386
  }
387
-
 
 
 
 
388
  if ($.inArray(t.val(), ['select', 'radio', 'checkbox']) !== -1) {
389
  link.show();
390
  } else {
@@ -551,6 +572,21 @@
551
  return false;
552
  },
553
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  /**
555
  * This hack is to make sure the dragged row has 100% width
556
  *
@@ -694,9 +730,10 @@
694
  event_init : function() {
695
  var wrapper = $('#options_taxes');
696
 
697
- wrapper.on( 'click' , '#wpsc-add-tax-rates a' , WPSC_Settings_Page.Taxes.event_add_tax_rate);
 
698
  wrapper.on( 'click' , '.wpsc-taxes-rates-delete' , WPSC_Settings_Page.Taxes.event_delete_tax_rate);
699
- wrapper.on( 'click' , '#wpsc-add-tax-bands a' , WPSC_Settings_Page.Taxes.event_add_tax_band);
700
  wrapper.on( 'click' , '.wpsc-taxes-bands-delete' , WPSC_Settings_Page.Taxes.event_delete_tax_band);
701
  wrapper.on( 'change', '.wpsc-taxes-country-drop-down', WPSC_Settings_Page.Taxes.event_country_drop_down_changed);
702
  },
@@ -710,8 +747,8 @@
710
  post_data = {
711
  action : 'add_tax_rate',
712
  wpec_taxes_action : 'wpec_taxes_get_regions',
713
- current_key : c.data('key'),
714
- taxes_type : c.data('type'),
715
  country_code : c.val(),
716
  nonce : WPSC_Settings_Page.add_tax_rate_nonce
717
  },
@@ -744,6 +781,9 @@
744
  */
745
  event_delete_tax_rate : function() {
746
  $(this).parents('.wpsc-tax-rates-row').remove();
 
 
 
747
  return false;
748
  },
749
 
@@ -762,6 +802,9 @@
762
  */
763
  event_delete_tax_band : function() {
764
  $(this).parents('.wpsc-tax-bands-row').remove();
 
 
 
765
  return false;
766
  },
767
 
@@ -771,24 +814,14 @@
771
  * @since 3.8.8
772
  */
773
  add_field : function(type) {
774
- var button_wrapper = $('#wpsc-add-tax-' + type),
775
  count = $('.wpsc-tax-' + type + '-row').size(),
776
- post_data = {
777
- action : 'add_tax_rate',
778
- wpec_taxes_action : 'wpec_taxes_build_' + type + '_form',
779
- current_key : count,
780
- nonce : WPSC_Settings_Page.add_tax_rate_nonce
781
- },
782
- ajax_callback = function(response) {
783
- if (! response.is_successful) {
784
- alert(response.error.messages.join("\n"));
785
- return;
786
- }
787
- button_wrapper.before(response.obj.content).find('img').toggleClass('ajax-feedback-active');
788
- };
789
-
790
- button_wrapper.find('img').toggleClass('ajax-feedback-active');
791
- $.wpsc_post(post_data, ajax_callback);
792
  }
793
  };
794
  $(WPSC_Settings_Page).on('wpsc_settings_tab_loaded_taxes', WPSC_Settings_Page.Taxes.event_init);
@@ -812,6 +845,7 @@
812
  WPSC_Settings_Page.Shipping.wrapper.on( 'click' , '.table-rate .wpsc-button-minus', WPSC_Settings_Page.Shipping.event_delete_table_rate_layer);
813
  WPSC_Settings_Page.Shipping.wrapper.on( 'keypress', '.table-rate input[type="text"]', WPSC_Settings_Page.Shipping.event_enter_key_pressed);
814
  WPSC_Settings_Page.Shipping.wrapper.on( 'click' , 'a.shipwire_sync' , WPSC_Settings_Page.Shipping.event_sync_shipwire);
 
815
  },
816
 
817
  /**
@@ -885,7 +919,7 @@
885
  */
886
  event_edit_shipping_module : function() {
887
  var element = $(this),
888
- shipping_module_id = element.data('module-id'),
889
  spinner = element.siblings('.ajax-feedback'),
890
  post_data = {
891
  action : 'shipping_module_settings_form',
@@ -903,7 +937,10 @@
903
  history.pushState({url : new_url}, '', new_url);
904
  }
905
  spinner.toggleClass('ajax-feedback-active');
906
- $('#wpsc-shipping-module-settings').replaceWith(response.obj.content);
 
 
 
907
  };
908
 
909
  spinner.toggleClass('ajax-feedback-active');
@@ -911,6 +948,23 @@
911
  return false;
912
  },
913
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
914
  /**
915
  * Syncs with Shipwire's Inventory and Tracking APIs
916
  * @since 3.8.9
@@ -919,8 +973,11 @@
919
  var element = $(this),
920
  spinner = element.siblings('.ajax-feedback'),
921
  post_data = {
922
- action : 'sync_shipwire_products',
923
- nonce : WPSC_Settings_Page.shipping_module_settings_form_nonce
 
 
 
924
  },
925
  ajax_callback = function(response) {
926
  $('<div class="updated shipwire-update"><p><strong>' + response.tracking + '<br />' + response.inventory + '</strong></p></div>').
@@ -994,7 +1051,7 @@
994
  history.pushState({'url' : new_url}, '', new_url);
995
  }
996
  $('#gateway_settings_' + payment_gateway_id + '_form').remove();
997
- $('#wpsc_gateway_settings_'+ payment_gateway_id).hide();
998
  return false;
999
  }
1000
  };
309
  wrapper.on( 'click', '.field-option-cell-wrapper .wpsc-button-minus', WPSC_Settings_Page.Checkout.event_delete_field_option);
310
  wrapper.on( 'click', '#wpsc-delete-checkout-set', WPSC_Settings_Page.Checkout.event_delete_checkout_set);
311
  wrapper.on( 'change', '#wpsc_form_set', WPSC_Settings_Page.Checkout.event_select_form_set);
312
+ wrapper.on( 'click', '.mandatorycol input[type="checkbox"]', WPSC_Settings_Page.Checkout.event_disabled_toggeled);
313
  $('#wpsc-settings-form').on( 'submit', WPSC_Settings_Page.Checkout.event_form_submit);
314
 
315
  wrapper.find('#wpsc_checkout_list').
327
  });
328
 
329
  WPSC_Settings_Page.Checkout.new_field_count = $('.new-field').length;
330
+
331
+ /**
332
+ * Finding checkboxes that are mandatory and disabling the display option.
333
+ * If it's mandatory you no have choice for display.
334
+ */
335
+ wrapper.find( '.mandatorycol input[type="checkbox"]').each( function(){
336
+ var displaycol = $(this).parents('.mandatorycol').siblings('.displaycol');
337
+
338
+ if ( $(this).is(':checked') ){
339
+ $(displaycol).find('input[type="checkbox"]').prop('checked', true ).attr( 'disabled', 'disabled' );
340
+ } else {
341
+ $(displaycol).find('input[type="checkbox"]').attr( 'disabled', this.checked );
342
+ }
343
+ });
344
+
345
  },
346
 
347
  event_add_field_option : function() {
393
  var t = $(this),
394
  target_row = t.closest('tr'),
395
  id = target_row.data('field-id'),
396
+ type = target_row.data('field-type'),
397
  link = target_row.find('.edit-options'),
398
  options_row_id = 'wpsc-field-edit-options-' + id;
399
 
401
  id = target_row.data('new-field-id');
402
  options_row_id = 'wpsc-new-field-edit-options-' + id;
403
  }
404
+ target_row
405
+ .removeClass('field_type_'+type)
406
+ .addClass('field_type_'+t.val())
407
+ .data('field-type', t.val());
408
+ type = t.val();
409
  if ($.inArray(t.val(), ['select', 'radio', 'checkbox']) !== -1) {
410
  link.show();
411
  } else {
572
  return false;
573
  },
574
 
575
+ /**
576
+ * Disables and checks the display option if you make a field mandatory. If you uncheck
577
+ * mandatory then it just enables you to uncheck the display box.
578
+ */
579
+ event_disabled_toggeled : function() {
580
+
581
+ var displaycol = $(this).parents('.mandatorycol').siblings('.displaycol');
582
+
583
+ if ( $(this).is(':checked') ){
584
+ $(displaycol).find('input[type="checkbox"]').prop('checked', true ).attr( 'disabled', 'disabled' );
585
+ } else {
586
+ $(displaycol).find('input[type="checkbox"]').attr( 'disabled', this.checked );
587
+ }
588
+ },
589
+
590
  /**
591
  * This hack is to make sure the dragged row has 100% width
592
  *
730
  event_init : function() {
731
  var wrapper = $('#options_taxes');
732
 
733
+ wrapper.on( 'click' , '.wpsc-button-minus' , function () { return false; } );
734
+ wrapper.on( 'click' , '.wpsc-taxes-rates-add' , WPSC_Settings_Page.Taxes.event_add_tax_rate);
735
  wrapper.on( 'click' , '.wpsc-taxes-rates-delete' , WPSC_Settings_Page.Taxes.event_delete_tax_rate);
736
+ wrapper.on( 'click' , '.wpsc-taxes-bands-add' , WPSC_Settings_Page.Taxes.event_add_tax_band);
737
  wrapper.on( 'click' , '.wpsc-taxes-bands-delete' , WPSC_Settings_Page.Taxes.event_delete_tax_band);
738
  wrapper.on( 'change', '.wpsc-taxes-country-drop-down', WPSC_Settings_Page.Taxes.event_country_drop_down_changed);
739
  },
747
  post_data = {
748
  action : 'add_tax_rate',
749
  wpec_taxes_action : 'wpec_taxes_get_regions',
750
+ current_key : c.data('row-key'),
751
+ taxes_type : c.data('row-mode'),
752
  country_code : c.val(),
753
  nonce : WPSC_Settings_Page.add_tax_rate_nonce
754
  },
781
  */
782
  event_delete_tax_rate : function() {
783
  $(this).parents('.wpsc-tax-rates-row').remove();
784
+ if ($('.wpsc-tax-rates-row').size() === 1) {
785
+ WPSC_Settings_Page.Taxes.add_field('rates');
786
+ }
787
  return false;
788
  },
789
 
802
  */
803
  event_delete_tax_band : function() {
804
  $(this).parents('.wpsc-tax-bands-row').remove();
805
+ if ($('.wpsc-tax-bands-row').size() === 1) {
806
+ WPSC_Settings_Page.Taxes.add_field('bands');
807
+ }
808
  return false;
809
  },
810
 
814
  * @since 3.8.8
815
  */
816
  add_field : function(type) {
817
+ var tbody = $('#wpec-taxes-' + type + ' tbody'),
818
  count = $('.wpsc-tax-' + type + '-row').size(),
819
+ new_prototype_row = $('#wpsc-taxes-' + type + '-row-prototype').clone();
820
+ new_prototype_row.removeClass('prototype');
821
+ new_prototype_row.attr('id', new_prototype_row.attr('id').replace(/prototype/g, count));
822
+ new_prototype_row.attr('data-row-key', new_prototype_row.attr('data-row-key').replace(/prototype/g, count));
823
+ new_prototype_row.html( new_prototype_row.html().replace(/prototype/g, count) );
824
+ tbody.append(new_prototype_row);
 
 
 
 
 
 
 
 
 
 
825
  }
826
  };
827
  $(WPSC_Settings_Page).on('wpsc_settings_tab_loaded_taxes', WPSC_Settings_Page.Taxes.event_init);
845
  WPSC_Settings_Page.Shipping.wrapper.on( 'click' , '.table-rate .wpsc-button-minus', WPSC_Settings_Page.Shipping.event_delete_table_rate_layer);
846
  WPSC_Settings_Page.Shipping.wrapper.on( 'keypress', '.table-rate input[type="text"]', WPSC_Settings_Page.Shipping.event_enter_key_pressed);
847
  WPSC_Settings_Page.Shipping.wrapper.on( 'click' , 'a.shipwire_sync' , WPSC_Settings_Page.Shipping.event_sync_shipwire);
848
+ WPSC_Settings_Page.Shipping.wrapper.on( 'click' , '.edit-shipping-module-cancel' , WPSC_Settings_Page.Shipping.event_edit_shipping_module_cancel);
849
  },
850
 
851
  /**
919
  */
920
  event_edit_shipping_module : function() {
921
  var element = $(this),
922
+ shipping_module_id = element.closest('.wpsc-select-shipping').data('shipping-id'),
923
  spinner = element.siblings('.ajax-feedback'),
924
  post_data = {
925
  action : 'shipping_module_settings_form',
937
  history.pushState({url : new_url}, '', new_url);
938
  }
939
  spinner.toggleClass('ajax-feedback-active');
940
+ $('#wpsc_shipping_settings_' + shipping_module_id + '_form').remove();
941
+ $('#wpsc_shipping_settings_'+ shipping_module_id).show();
942
+ $('#wpsc_shipping_settings_'+ shipping_module_id + '_container').append(response.obj.content);
943
+
944
  };
945
 
946
  spinner.toggleClass('ajax-feedback-active');
948
  return false;
949
  },
950
 
951
+ /**
952
+ * Remove Shipping Module settings from from page when "Cancel" is clicked.
953
+ * @since 3.8.11
954
+ */
955
+ event_edit_shipping_module_cancel : function() {
956
+ var element = $(this),
957
+ shipping_module_id = element.closest('.wpsc-select-shipping').data('shipping-id');
958
+ console.log('cancel', shipping_module_id);
959
+ if (history.pushState) {
960
+ var new_url = '?page=wpsc-settings&tab=' + WPSC_Settings_Page.current_tab;
961
+ history.pushState({'url' : new_url}, '', new_url);
962
+ }
963
+ $('#wpsc_shipping_settings_' + shipping_module_id + '_form').remove();
964
+ $('#wpsc_shipping_settings_' + shipping_module_id).hide();
965
+ return false;
966
+ },
967
+
968
  /**
969
  * Syncs with Shipwire's Inventory and Tracking APIs
970
  * @since 3.8.9
973
  var element = $(this),
974
  spinner = element.siblings('.ajax-feedback'),
975
  post_data = {
976
+ action : 'sync_shipwire_products',
977
+ email : $('input[name="wpsc_options[shipwireemail]"]').val(),
978
+ password : $('input[name="wpsc_options[shipwirepassword]"]').val(),
979
+ server : $('input[name="wpsc_options[shipwire_test_server]"]').val(),
980
+ nonce : WPSC_Settings_Page.shipping_module_settings_form_nonce
981
  },
982
  ajax_callback = function(response) {
983
  $('<div class="updated shipwire-update"><p><strong>' + response.tracking + '<br />' + response.inventory + '</strong></p></div>').
1051
  history.pushState({'url' : new_url}, '', new_url);
1052
  }
1053
  $('#gateway_settings_' + payment_gateway_id + '_form').remove();
1054
+ $('#wpsc_gateway_settings_' + payment_gateway_id).hide();
1055
  return false;
1056
  }
1057
  };
wpsc-admin/js/wpsc-swfupload-handlers.js DELETED
@@ -1,362 +0,0 @@
1
- /**
2
- * This is a nearly exact copy of the corresponding wordpress file, we needed to copy and modify it for our use of swfupoader as the wordpress handler code is specific to posts
3
- */
4
- // define a global variable for swfupload here so that we can later do things to it.
5
- var swfu = null;
6
-
7
-
8
- jQuery().ajaxComplete(function(event, XMLHttpRequest, ajaxOptions) {
9
- // nonces are only regenerated on autosaving when ther product ID is created/changed
10
- // we only want to edit the swfuploader parameters when that happens
11
- if(/autosave-generate-nonces/.test(ajaxOptions.data)) {
12
- window.swfu.removePostParam('product_id');
13
- window.swfu.addPostParam('product_id', parseInt(jQuery('#post_ID').val()));
14
- }
15
- //console.log(jQuery('#post_ID').val());
16
- });
17
-
18
-
19
- function wpsc_fileDialogStart() {
20
- jQuery("#media-upload-error").empty();
21
- }
22
-
23
- // progress and success handlers for media multi uploads
24
- function wpsc_fileQueued(fileObj) {
25
- // Create a progress bar containing the filename
26
- jQuery('#media-items').append('<div id="media-item-' + fileObj.id + '" ><div class="progress"><div class="bar"></div></div></div>');
27
- // Display the progress div
28
- jQuery('#media-item-' + fileObj.id + ' .progress').show();
29
-
30
- // Disable the submit button
31
- //jQuery('#insert-gallery').attr('disabled', 'disabled');
32
- }
33
-
34
- function wpsc_uploadStart(fileObj) {return true; }
35
-
36
- function wpsc_uploadProgress(fileObj, bytesDone, bytesTotal) {
37
- // Lengthen the progress bar
38
- jQuery('#media-item-' + fileObj.id + ' .bar').width(500*bytesDone/bytesTotal);
39
-
40
- if ( bytesDone == bytesTotal ) {
41
- jQuery('#media-item-' + fileObj.id + ' .bar').html('<strong class="crunching"></strong>');
42
- }
43
- }
44
-
45
- function wpsc_prepareMediaItem(fileObj, serverData) {
46
- // Move the progress bar to 100%
47
- jQuery('#media-item-' + fileObj.id + ' .bar').remove();
48
- jQuery('#media-item-' + fileObj.id + ' .progress').hide();
49
-
50
- var f = ( typeof shortform == 'undefined' ) ? 1 : 2;
51
- // Old style: Append the HTML returned by the server -- thumbnail and form inputs
52
- if ( isNaN(serverData) || !serverData ) {
53
- jQuery('#media-item-' + fileObj.id).append(serverData);
54
- prepareMediaItemInit(fileObj);
55
- }
56
- // New style: server data is just the attachment ID, fetch the thumbnail and form html from the server
57
- else {
58
- jQuery('#media-item-' + fileObj.id).load('async-upload.php', {attachment_id:serverData, fetch:f}, function(){prepareMediaItemInit(fileObj);updateMediaForm()});
59
- }
60
- }
61
-
62
- function wpsc_prepareMediaItemInit(fileObj) {
63
-
64
- // Clone the thumbnail as a "pinkynail" -- a tiny image to the left of the filename
65
- jQuery('#media-item-' + fileObj.id + ' .thumbnail').clone().attr('class', 'pinkynail toggle').prependTo('#media-item-' + fileObj.id);
66
-
67
- // Replace the original filename with the new (unique) one assigned during upload
68
- jQuery('#media-item-' + fileObj.id + ' .filename.original').replaceWith(jQuery('#media-item-' + fileObj.id + ' .filename.new'));
69
-
70
- // Also bind toggle to the links
71
- jQuery('#media-item-' + fileObj.id + ' a.toggle').bind('click', function(){jQuery(this).siblings('.slidetoggle').slideToggle(150, function(){var o=jQuery(this).offset();window.scrollTo(0,o.top-36);});jQuery(this).parent().eq(0).children('.toggle').toggle();jQuery(this).siblings('a.toggle').focus();return false;});
72
-
73
- // Bind AJAX to the new Delete button
74
- jQuery('#media-item-' + fileObj.id + ' a.delete').bind('click',function(){
75
- // Tell the server to delete it. TODO: handle exceptions
76
- jQuery.ajax({url:'admin-ajax.php',type:'post',success:deleteSuccess,error:deleteError,id:fileObj.id,data:{
77
- id : this.id.replace(/[^0-9]/g,''),
78
- action : 'delete-post',
79
- _ajax_nonce : this.href.replace(/^.*wpnonce=/,'')}
80
- });
81
- return false;
82
- });
83
-
84
- // Open this item if it says to start open (e.g. to display an error)
85
- jQuery('#media-item-' + fileObj.id + '.startopen')
86
- .removeClass('startopen')
87
- .slideToggle(500)
88
- .parent().eq(0).children('.toggle').toggle();
89
- }
90
-
91
- function wpsc_itemAjaxError(id, html) {
92
- var error = jQuery('#media-item-error' + id);
93
-
94
- error.html('<div class="file-error"><button type="button" id="dismiss-'+id+'" class="button dismiss">'+swfuploadL10n.dismiss+'</button>'+html+'</div>');
95
- jQuery('#dismiss-'+id).click(function(){jQuery(this).parents('.file-error').slideUp(200, function(){jQuery(this).empty();})});
96
- }
97
-
98
- function wpsc_deleteSuccess(data, textStatus) {
99
- if ( data == '-1' )
100
- return itemAjaxError(this.id, 'You do not have permission. Has your session expired?');
101
- if ( data == '0' )
102
- return itemAjaxError(this.id, 'Could not be deleted. Has it been deleted already?');
103
-
104
- var item = jQuery('#media-item-' + this.id);
105
-
106
- // Decrement the counters.
107
- if ( type = jQuery('#type-of-' + this.id).val() )
108
- jQuery('#' + type + '-counter').text(jQuery('#' + type + '-counter').text()-1);
109
- if ( jQuery('.type-form #media-items>*').length == 1 && jQuery('#media-items .hidden').length > 0 ) {
110
- jQuery('.toggle').toggle();
111
- jQuery('.slidetoggle').slideUp(200).siblings().removeClass('hidden');
112
- }
113
-
114
- // Vanish it.
115
- jQuery('#media-item-' + this.id + ' .filename:empty').remove();
116
- jQuery('#media-item-' + this.id + ' .filename').append(' <span class="file-error">'+swfuploadL10n.deleted+'</span>').siblings('a.toggle').remove();
117
- jQuery('#media-item-' + this.id).children('.describe').css({backgroundColor:'#fff'}).end()
118
- .animate({backgroundColor:'#ffc0c0'}, {queue:false,duration:50})
119
- .animate({minHeight:0,height:36}, 400, null, function(){jQuery(this).children('.describe').remove()})
120
- .animate({backgroundColor:'#fff'}, 400)
121
- .animate({height:0}, 800, null, function(){jQuery(this).remove();updateMediaForm();});
122
-
123
- return;
124
- }
125
-
126
- function wpsc_deleteError(X, textStatus, errorThrown) {
127
- // TODO
128
- }
129
-
130
- function wpsc_updateMediaForm() {
131
- storeState();
132
- // Just one file, no need for collapsible part
133
- if ( jQuery('.type-form #media-items>*').length == 1 ) {
134
- jQuery('#media-items .slidetoggle').slideDown(500).parent().eq(0).children('.toggle').toggle();
135
- jQuery('.type-form .slidetoggle').siblings().addClass('hidden');
136
- }
137
-
138
- // Only show Save buttons when there is at least one file.
139
- if ( jQuery('#media-items>*').not('.media-blank').length > 0 )
140
- jQuery('.savebutton').show();
141
- else
142
- jQuery('.savebutton').hide();
143
-
144
- // Only show Gallery button when there are at least two files.
145
- if ( jQuery('#media-items>*').length > 1 )
146
- jQuery('.insert-gallery').show();
147
- else
148
- jQuery('.insert-gallery').hide();
149
- }
150
-
151
- function wpsc_uploadSuccess(fileObj, serverData) {
152
- // if async-upload returned an error message, place it in the media item div and return
153
- if ( serverData.match('media-upload-error') ) {
154
- jQuery('#media-item-' + fileObj.id).html(serverData);
155
- return;
156
- }
157
- //console.log(fileObj);
158
- //console.log(serverData);
159
- eval(serverData);
160
- if(upload_status == 1 ) {
161
- output_html = "";
162
- output_html +="<li class='gallery_image' id='product_image_"+image_id+"'>\n";
163
- output_html += " <input type='hidden' value='"+image_id+"' name='gallery_image_id[]' class='image-id'/>\n";
164
- output_html += " <div id='gallery_image_"+image_id+"' class='previewimage'>\n";
165
- output_html += " <a class='thickbox' rel='product_extra_image_"+image_id+"' href='admin.php?wpsc_admin_action=crop_image&amp;imagename="+image_src+"&amp;imgheight=480&amp;imgwidth=600&amp;product_id=103&amp;width=640&amp;height=342' id='extra_preview_link_"+image_id+"'>\n";
166
- output_html += " <img title='Preview' alt='Preview' src='"+image_src+"' class='previewimage'/>\n";
167
- output_html += " </a>\n";
168
- output_html += " <img src='" + WPSC_CORE_IMAGES_URL + "/cross.png' class='deleteButton' alt='-' style='display: none;'/>\n";
169
- output_html += " </div>\n";
170
- output_html += "</li>\n";
171
-
172
- image_count = jQuery("ul#gallery_list li.gallery_image div a img.previewimage").size();
173
- if(image_count < 1) {
174
- replace_existing = 1;
175
- }
176
- //console.log(jQuery("ul#gallery_list li.gallery_image div a img.previewimage"));
177
- //console.log(image_count);
178
-
179
- if(replace_existing == 1) {
180
- jQuery("ul#gallery_list").html(output_html);
181
-
182
- input_set = jQuery.makeArray(jQuery("#gallery_list li:not(.ui-sortable-helper) input.image-id"));
183
- set = new Array();
184
- for( var i in input_set) {
185
- set[i] = jQuery(input_set[i]).val();
186
- }
187
- //console.log(set);
188
-
189
- img_id = jQuery('#gallery_image_'+set[0]).parent('li').attr('id');
190
-
191
- jQuery('#gallery_image_'+set[0]).children('img.deleteButton').remove();
192
- jQuery('#gallery_image_'+set[0]).append("<a class='editButton'>Edit <img src='" + WPSC_CORE_IMAGES_URL + "/pencil.png' alt ='' /></a>");
193
- // jQuery('#gallery_image_'+set[0]).parent('li').attr('id', 0);
194
-
195
- for(i=1;i<set.length;i++) {
196
- jQuery('#gallery_image_'+set[i]).children('a.editButton').remove();
197
- jQuery('#gallery_image_'+set[i]).append("<img alt='-' class='deleteButton' src='" + WPSC_CORE_IMAGES_URL + "/cross.png'/>");
198
-
199
- element_id = jQuery('#gallery_image_'+set[i]).parent('li').attr('id');
200
- if(element_id == 0) {
201
- // jQuery('#gallery_image_'+set[i]).parent('li').attr('id', img_id);
202
- }
203
- }
204
-
205
- order = set.join(',');
206
- product_id = jQuery('#product_id').val();
207
-
208
-
209
- postVars = "product_id="+product_id+"&order="+order;
210
- jQuery.post( 'index.php?wpsc_admin_action=rearrange_images', postVars, function(returned_data) {
211
- eval(returned_data);
212
- jQuery('#gallery_image_'+image_id).children('a.editButton').remove();
213
- jQuery('#gallery_image_'+image_id).children('div.image_settings_box').remove();
214
- jQuery('#gallery_image_'+image_id).append(image_menu);
215
- });
216
- } else {
217
- jQuery("ul#gallery_list").append(output_html);
218
- ///jQuery("#gallery_list").trigger( 'update' );
219
- }
220
- }
221
-
222
- //jQuery('#media-item-' + fileObj.id + ' .progress').show();
223
- //window.setInterval(function() {
224
- jQuery("#media-item-" + fileObj.id + "").fadeOut("normal");
225
- //}, 5000);
226
-
227
- //prepareMediaItem(fileObj, serverData);
228
- //updateMediaForm();
229
-
230
- }
231
-
232
- function wpsc_uploadComplete(fileObj) {
233
- // If no more uploads queued, enable the submit button
234
- if ( swfu.getStats().files_queued == 0 )
235
- jQuery('#insert-gallery').attr('disabled', '');
236
- }
237
-
238
-
239
- // wp-specific error handlers
240
-
241
- // generic message
242
- function wpsc_wpQueueError(message) {
243
- jQuery('#media-upload-error').show().text(message);
244
- }
245
-
246
- // file-specific message
247
- function wpsc_wpFileError(fileObj, message) {
248
- jQuery('#media-item-' + fileObj.id + ' .filename').after('<div class="file-error"><button type="button" id="dismiss-' + fileObj.id + '" class="button dismiss">'+swfuploadL10n.dismiss+'</button>'+message+'</div>').siblings('.toggle').remove();
249
- jQuery('#dismiss-' + fileObj.id).click(function(){jQuery(this).parents('.media-item').slideUp(200, function(){jQuery(this).remove();})});
250
- }
251
-
252
- function wpsc_fileQueueError(fileObj, error_code, message) {
253
- // Handle this error separately because we don't want to create a FileProgress element for it.
254
- if ( error_code == SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED ) {
255
- wpQueueError(swfuploadL10n.queue_limit_exceeded);
256
- }
257
- else if ( error_code == SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT ) {
258
- fileQueued(fileObj);
259
- wpFileError(fileObj, swfuploadL10n.file_exceeds_size_limit);
260
- }
261
- else if ( error_code == SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE ) {
262
- fileQueued(fileObj);
263
- wpFileError(fileObj, swfuploadL10n.zero_byte_file);
264
- }
265
- else if ( error_code == SWFUpload.QUEUE_ERROR.INVALID_FILETYPE ) {
266
- fileQueued(fileObj);
267
- wpFileError(fileObj, swfuploadL10n.invalid_filetype);
268
- }
269
- else {
270
- wpQueueError(swfuploadL10n.default_error);
271
- }
272
- }
273
-
274
- function wpsc_fileDialogComplete(num_files_queued) {
275
- try {
276
- if (num_files_queued > 0) {
277
- this.startUpload();
278
- }
279
- } catch (ex) {
280
- this.debug(ex);
281
- }
282
- }
283
-
284
- function wpsc_swfuploadPreLoad() {
285
- var swfupload_element = jQuery('#'+swfu.customSettings.swfupload_element_id).get(0);
286
- jQuery('#' + swfu.customSettings.degraded_element_id).hide();
287
- // Doing this directly because jQuery().show() seems to have timing problems
288
- if ( swfupload_element && ! swfupload_element.style.display )
289
- swfupload_element.style.display = 'block';
290
- }
291
-
292
- function wpsc_swfuploadLoadFailed() {
293
- jQuery('#' + swfu.customSettings.swfupload_element_id).hide();
294
- jQuery('#' + swfu.customSettings.degraded_element_id).show();
295
- }
296
-
297
- function wpsc_uploadError(fileObj, error_code, message) {
298
- // first the file specific error
299
- if ( error_code == SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL ) {
300
- wpFileError(fileObj, swfuploadL10n.missing_upload_url);
301
- }
302
- else if ( error_code == SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED ) {
303
- wpFileError(fileObj, swfuploadL10n.upload_limit_exceeded);
304
- }
305
- else {
306
- wpFileError(fileObj, swfuploadL10n.default_error);
307
- }
308
-
309
- // now the general upload status
310
- if ( error_code == SWFUpload.UPLOAD_ERROR.HTTP_ERROR ) {
311
- wpQueueError(swfuploadL10n.http_error);
312
- }
313
- else if ( error_code == SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED ) {
314
- wpQueueError(swfuploadL10n.upload_failed);
315
- }
316
- else if ( error_code == SWFUpload.UPLOAD_ERROR.IO_ERROR ) {
317
- wpQueueError(swfuploadL10n.io_error);
318
- }
319
- else if ( error_code == SWFUpload.UPLOAD_ERROR.SECURITY_ERROR ) {
320
- wpQueueError(swfuploadL10n.security_error);
321
- }
322
- else if ( error_code == SWFUpload.UPLOAD_ERROR.FILE_CANCELLED ) {
323
- wpQueueError(swfuploadL10n.security_error);
324
- }
325
- }
326
-
327
- // remember the last used image size, alignment and url
328
- var storeState;
329
- (function($){
330
-
331
- storeState = function(){
332
- var align = getUserSetting('align') || '', imgsize = getUserSetting('imgsize') || '';
333
-
334
- $('tr.align input[type="radio"]').click(function(){
335
- setUserSetting('align', $(this).val());
336
- }).filter(function(){
337
- if ( $(this).val() == align )
338
- return true;
339
- return false;
340
- }).attr('checked','checked');
341
-
342
- $('tr.image-size input[type="radio"]').click(function(){
343
- setUserSetting('imgsize', $(this).val());
344
- }).filter(function(){
345
- if ( $(this).attr('disabled') || $(this).val() != imgsize )
346
- return false;
347
- return true;
348
- }).attr('checked','checked');
349
-
350
- $('tr.url button').click(function(){
351
- var c = this.className || '';
352
- c = c.replace(/.*?(url[^ '"]+).*/, '$1');
353
- if (c) setUserSetting('urlbutton', c);
354
- $(this).siblings('.urlfield').val( $(this).attr('title') );
355
- });
356
-
357
- $('tr.url .urlfield').each(function(){
358
- var b = getUserSetting('urlbutton');
359
- $(this).val( $(this).siblings('button.'+b).attr('title') );
360
- });
361
- }
362
- })(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-components/merchant-core-v2/helpers/checkout.php CHANGED
@@ -91,11 +91,11 @@ function _wpsc_action_merchant_v2_submit_checkout( $gateway, $purchase_log ) {
91
  $purchase_log->set( 'gateway', $gateway_used );
92
  $purchase_log->save();
93
  $current_gateway_data['function']( $separator, $purchase_log->get( 'sessionid' ) );
94
- } elseif ( ($current_gateway_data['internalname'] == 'google') && ($current_gateway_data['internalname'] == $submitted_gateway) ) {
95
  $gateway_used = $current_gateway_data['internalname'];
96
  $purchase_log->set( 'gateway', $gateway_used );
97
  wpsc_update_customer_meta( 'google_checkout', 'google' );
98
  wp_redirect(get_option( 'shopping_cart_url' ));
99
  exit;
100
  }
101
- }
91
  $purchase_log->set( 'gateway', $gateway_used );
92
  $purchase_log->save();
93
  $current_gateway_data['function']( $separator, $purchase_log->get( 'sessionid' ) );
94
+ } elseif ( $current_gateway_data['internalname'] == 'google' ) {
95
  $gateway_used = $current_gateway_data['internalname'];
96
  $purchase_log->set( 'gateway', $gateway_used );
97
  wpsc_update_customer_meta( 'google_checkout', 'google' );
98
  wp_redirect(get_option( 'shopping_cart_url' ));
99
  exit;
100
  }
101
+ }
wpsc-core/images/black-star.png ADDED
Binary file
wpsc-core/images/core-sprite.png ADDED
Binary file
wpsc-core/images/gold-star.gif DELETED
Binary file
wpsc-core/images/gold-star.png ADDED
Binary file
wpsc-core/images/grey-star.gif DELETED
Binary file
wpsc-core/images/grey-star.png ADDED
Binary file
wpsc-core/images/mobile.png DELETED
Binary file
wpsc-core/js/ajax.js DELETED
@@ -1,48 +0,0 @@
1
- // Copyright (c) 2005 Timothy R. Morgan
2
- //
3
- // Permission is hereby granted, free of charge, to any person obtaining a copy
4
- // of this software and associated documentation files (the "Software"), to deal
5
- // in the Software without restriction, including without limitation the rights
6
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
- // copies of the Software, and to permit persons to whom the Software is
8
- // furnished to do so, subject to the following conditions:
9
- //
10
- // The above copyright notice and this permission notice shall be included in
11
- // all copies or substantial portions of the Software.
12
- //
13
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19
- // IN THE SOFTWARE.
20
- // mini/ajax.js - http://timmorgan.org/mini
21
- // var fvd = 0;
22
- function ajax_item(e){if(typeof e=='string')e=document.getElementById(e);return e};
23
- function collect(a,f){var n=[];for(var i=0;i<a.length;i++){var v=f(a[i]);if(v!=null)n.push(v)}return n};
24
-
25
- ajax={};
26
- ajax.x=function(){try{return new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{return new ActiveXObject('Microsoft.XMLHTTP')}catch(e){return new XMLHttpRequest()}}};
27
- ajax.serialize=function(f)
28
- {
29
- var g=function(n)
30
- {
31
- return f.getElementsByTagName(n)
32
- };
33
- var nv=function(e)
34
- {
35
- if(e.name)
36
- {
37
- return encodeURIComponent(e.name)+'='+encodeURIComponent(e.value);
38
- } else {return '';}
39
- };
40
- var i=collect(g('input'),function(i){if((i.type!='radio'&&i.type!='checkbox')||i.checked)return nv(i)});var s=collect(g('select'),nv);var t=collect(g('textarea'),nv);return i.concat(s).concat(t).join('&');
41
- };
42
-
43
- ajax.send=function(u,f,m,a){var x=ajax.x();x.open(m,u,true);x.onreadystatechange=function(){if(x.readyState==4)f(x.responseText)};if(m=='POST')x.setRequestHeader('Content-type','application/x-www-form-urlencoded');x.send(a)};
44
- ajax.get=function(url,func){ajax.send(url,func,'GET')};
45
- ajax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};
46
- ajax.post=function(url,func,args){ajax.send(url,func,'POST',args)};
47
- ajax.update=function(url,elm){var e=ajax_item(elm);var f=function(r){e.innerHTML=r};ajax.get(url,f)};
48
- ajax.submit=function(url,elm,frm){var e=ajax_item(elm);var f=function(r){e.innerHTML=r};ajax.post(url,f,ajax.serialize(frm))};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/iautocompleter.js DELETED
@@ -1,536 +0,0 @@
1
- /**
2
- * Interface Elements for jQuery
3
- * Autocompleter
4
- *
5
- * http://interface.eyecon.ro
6
- *
7
- * Copyright (c) 2006 Stefan Petre
8
- * Dual licensed under the MIT (MIT-LICENSE.txt)
9
- * and GPL (GPL-LICENSE.txt) licenses.
10
- *
11
- */
12
-
13
- /**
14
- * Attach AJAX driven autocomplete/sugestion box to text input fields.
15
- *
16
- *
17
- *
18
- * @name Autocomplete
19
- * @description Attach AJAX driven autocomplete/sugestion box to text input fields.
20
- * @param Hash hash A hash of parameters
21
- * @option String source the URL to request
22
- * @option Integer delay (optional) the delayed time to start the AJAX request
23
- * @option Boolean autofill (optional) when true the first sugested value fills the input
24
- * @option String helperClass (optional) the CSS class applied to sugestion box
25
- * @option String selectClass (optional) the CSS class applied to selected/hovered item
26
- * @option Integer minchars (optional) the number of characters needed before starting AJAX request
27
- * @option Hash fx (optional) {type:[slide|blind|fade]; duration: integer} the fx type to apply to sugestion box and duration for that fx
28
- * @option Function onSelect (optional) A function to be executed whenever an item it is selected
29
- * @option Function onShow (optional) A function to be executed whenever the suggection box is displayed
30
- * @option Function onHide (optional) A function to be executed whenever the suggection box is hidden
31
- * @option Function onHighlight (optional) A function to be executed whenever an item it is highlighted
32
- *
33
- * @type jQuery
34
- * @cat Plugins/Interface
35
- * @author Stefan Petre
36
- */
37
- jQuery.iAuto = {
38
- helper : null,
39
- content : null,
40
- iframe: null,
41
- timer : null,
42
- lastValue: null,
43
- currentValue: null,
44
- subject: null,
45
- selectedItem : null,
46
- items: null,
47
-
48
- empty : function()
49
- {
50
- jQuery.iAuto.content.empty();
51
- if (jQuery.iAuto.iframe) {
52
- jQuery.iAuto.iframe.hide();
53
- }
54
- },
55
-
56
- clear : function()
57
- {
58
- jQuery.iAuto.items = null;
59
- jQuery.iAuto.selectedItem = null;
60
- jQuery.iAuto.lastValue = jQuery.iAuto.subject.value;
61
- if(jQuery.iAuto.helper.css('display') == 'block') {
62
- if (jQuery.iAuto.subject.autoCFG.fx) {
63
- switch(jQuery.iAuto.subject.autoCFG.fx.type) {
64
- case 'fade':
65
- jQuery.iAuto.helper.fadeOut(jQuery.iAuto.subject.autoCFG.fx.duration, jQuery.iAuto.empty);
66
- break;
67
- case 'slide':
68
- jQuery.iAuto.helper.SlideOutUp(jQuery.iAuto.subject.autoCFG.fx.duration, jQuery.iAuto.empty);
69
- break;
70
- case 'blind':
71
- jQuery.iAuto.helper.BlindUp(jQuery.iAuto.subject.autoCFG.fx.duration, jQuery.iAuto.empty);
72
- break;
73
- }
74
- } else {
75
- jQuery.iAuto.helper.hide();
76
- }
77
- if (jQuery.iAuto.subject.autoCFG.onHide)
78
- jQuery.iAuto.subject.autoCFG.onHide.apply(jQuery.iAuto.subject, [jQuery.iAuto.helper, jQuery.iAuto.iframe]);
79
- } else {
80
- jQuery.iAuto.empty();
81
- }
82
- window.clearTimeout(jQuery.iAuto.timer);
83
- },
84
-
85
- update : function ()
86
- {
87
- var subject = jQuery.iAuto.subject;
88
- var subjectValue = jQuery.iAuto.getFieldValues(subject);
89
- //var selectionStart = jQuery.iAuto.getSelectionStart(subject);
90
- if (subject && subjectValue.item != jQuery.iAuto.lastValue && subjectValue.item.length >= subject.autoCFG.minchars) {
91
- jQuery.iAuto.lastValue = subjectValue.item;
92
- jQuery.iAuto.currentValue = subjectValue.item;
93
-
94
- data = {
95
- field: jQuery(subject).attr('name')||'field',
96
- value: subjectValue.item
97
- };
98
-
99
- jQuery.ajax(
100
- {
101
- type: 'POST',
102
- data: jQuery.param(data),
103
- success: function(xml)
104
- {
105
- subject.autoCFG.lastSuggestion = jQuery('item',xml);
106
- size = subject.autoCFG.lastSuggestion.size();
107
- if (size > 0) {
108
- var toWrite = '';
109
- subject.autoCFG.lastSuggestion.each(
110
- function(nr)
111
- {
112
- toWrite += '<li rel="' + jQuery('value', this).text() + '" dir="' + nr + '" style="cursor: default;">' + jQuery('text', this).text() + '</li>';
113
- }
114
- );
115
- if (subject.autoCFG.autofill) {
116
- var valueToAdd = jQuery('value', subject.autoCFG.lastSuggestion.get(0)).text();
117
- subject.value = subjectValue.pre + valueToAdd + subject.autoCFG.multipleSeparator + subjectValue.post;
118
- jQuery.iAuto.selection(
119
- subject,
120
- subjectValue.item.length != valueToAdd.length ? (subjectValue.pre.length + subjectValue.item.length) : valueToAdd.length,
121
- subjectValue.item.length != valueToAdd.length ? (subjectValue.pre.length + valueToAdd.length) : valueToAdd.length
122
- );
123
- }
124
-
125
- if (size > 0) {
126
- jQuery.iAuto.writeItems(subject, toWrite);
127
- } else {
128
- jQuery.iAuto.clear();
129
- }
130
- } else {
131
- jQuery.iAuto.clear();
132
- }
133
- },
134
- url : subject.autoCFG.source
135
- }
136
- );
137
- }
138
- },
139
-
140
- writeItems : function(subject, toWrite)
141
- {
142
- jQuery.iAuto.content.html(toWrite);
143
- jQuery.iAuto.items = jQuery('li', jQuery.iAuto.content.get(0));
144
- jQuery.iAuto.items
145
- .mouseover(jQuery.iAuto.hoverItem)
146
- .bind('click', jQuery.iAuto.clickItem);
147
- var position = jQuery.iUtil.getPosition(subject);
148
- var size = jQuery.iUtil.getSize(subject);
149
- jQuery.iAuto.helper
150
- .css('top', position.y + size.hb + 'px')
151
- .css('left', position.x + 'px')
152
- .addClass(subject.autoCFG.helperClass);
153
- if (jQuery.iAuto.iframe) {
154
- jQuery.iAuto.iframe
155
- .css('display', 'block')
156
- .css('top', position.y + size.hb + 'px')
157
- .css('left', position.x + 'px')
158
- .css('width', jQuery.iAuto.helper.css('width'))
159
- .css('height', jQuery.iAuto.helper.css('height'));
160
- }
161
- jQuery.iAuto.selectedItem = 0;
162
- jQuery.iAuto.items.get(0).className = subject.autoCFG.selectClass;
163
- jQuery.iAuto.applyOn(subject,subject.autoCFG.lastSuggestion.get(0), 'onHighlight');
164
-
165
- if (jQuery.iAuto.helper.css('display') == 'none') {
166
- if (subject.autoCFG.inputWidth) {
167
- var borders = jQuery.iUtil.getPadding(subject, true);
168
- var paddings = jQuery.iUtil.getBorder(subject, true);
169
- jQuery.iAuto.helper.css('width', subject.offsetWidth - (jQuery.boxModel ? (borders.l + borders.r + paddings.l + paddings.r) : 0 ) + 'px');
170
- }
171
- if (subject.autoCFG.fx) {
172
- switch(subject.autoCFG.fx.type) {
173
- case 'fade':
174
- jQuery.iAuto.helper.fadeIn(subject.autoCFG.fx.duration);
175
- break;
176
- case 'slide':
177
- jQuery.iAuto.helper.SlideInUp(subject.autoCFG.fx.duration);
178
- break;
179
- case 'blind':
180
- jQuery.iAuto.helper.BlindDown(subject.autoCFG.fx.duration);
181
- break;
182
- }
183
- } else {
184
- jQuery.iAuto.helper.show();
185
- }
186
-
187
- if (jQuery.iAuto.subject.autoCFG.onShow)
188
- jQuery.iAuto.subject.autoCFG.onShow.apply(jQuery.iAuto.subject, [jQuery.iAuto.helper, jQuery.iAuto.iframe]);
189
- }
190
- },
191
-
192
- checkCache : function()
193
- {
194
- var subject = this;
195
- if (subject.autoCFG.lastSuggestion) {
196
-
197
- jQuery.iAuto.lastValue = subject.value;
198
- jQuery.iAuto.currentValue = subject.value;
199
-
200
- var toWrite = '';
201
- subject.autoCFG.lastSuggestion.each(
202
- function(nr)
203
- {
204
- value = jQuery('value', this).text().toLowerCase();
205
- inputValue = subject.value.toLowerCase();
206
- if (value.indexOf(inputValue) == 0) {
207
- toWrite += '<li rel="' + jQuery('value', this).text() + '" dir="' + nr + '" style="cursor: default;">' + jQuery('text', this).text() + '</li>';
208
- }
209
- }
210
- );
211
-
212
- if (toWrite != '') {
213
- jQuery.iAuto.writeItems(subject, toWrite);
214
-
215
- this.autoCFG.inCache = true;
216
- return;
217
- }
218
- }
219
- subject.autoCFG.lastSuggestion = null;
220
- this.autoCFG.inCache = false;
221
- },
222
-
223
- selection : function(field, start, end)
224
- {
225
- if (field.createTextRange) {
226
- var selRange = field.createTextRange();
227
- selRange.collapse(true);
228
- selRange.moveStart("character", start);
229
- selRange.moveEnd("character", - end + start);
230
- selRange.select();
231
- } else if (field.setSelectionRange) {
232
- field.setSelectionRange(start, end);
233
- } else {
234
- if (field.selectionStart) {
235
- field.selectionStart = start;
236
- field.selectionEnd = end;
237
- }
238
- }
239
- field.focus();
240
- },
241
-
242
- getSelectionStart : function(field)
243
- {
244
- if (field.selectionStart)
245
- return field.selectionStart;
246
- else if(field.createTextRange) {
247
- var selRange = document.selection.createRange();
248
- var selRange2 = selRange.duplicate();
249
- return 0 - selRange2.moveStart('character', -100000);
250
- //result.end = result.start + range.text.length;
251
- /*var selRange = document.selection.createRange();
252
- var isCollapsed = selRange.compareEndPoints("StartToEnd", selRange) == 0;
253
- if (!isCollapsed)
254
- selRange.collapse(true);
255
- var bookmark = selRange.getBookmark();
256
- return bookmark.charCodeAt(2) - 2;*/
257
- }
258
- },
259
-
260
- getFieldValues : function(field)
261
- {
262
- var fieldData = {
263
- value: field.value,
264
- pre: '',
265
- post: '',
266
- item: ''
267
- };
268
-
269
- if(field.autoCFG.multiple) {
270
- var finishedPre = false;
271
- var selectionStart = jQuery.iAuto.getSelectionStart(field)||0;
272
- var chunks = fieldData.value.split(field.autoCFG.multipleSeparator);
273
- for (var i=0; i<chunks.length; i++) {
274
- if(
275
- (fieldData.pre.length + chunks[i].length >= selectionStart
276
- ||
277
- selectionStart == 0)
278
- &&
279
- !finishedPre
280
- ) {
281
- if (fieldData.pre.length <= selectionStart)
282
- fieldData.item = chunks[i];
283
- else
284
- fieldData.post += chunks[i] + (chunks[i] != '' ? field.autoCFG.multipleSeparator : '');
285
- finishedPre = true;
286
- } else if (finishedPre){
287
- fieldData.post += chunks[i] + (chunks[i] != '' ? field.autoCFG.multipleSeparator : '');
288
- }
289
- if(!finishedPre) {
290
- fieldData.pre += chunks[i] + (chunks.length > 1 ? field.autoCFG.multipleSeparator : '');
291
- }
292
- }
293
- } else {
294
- fieldData.item = fieldData.value;
295
- }
296
- return fieldData;
297
- },
298
-
299
- autocomplete : function(e)
300
- {
301
- window.clearTimeout(jQuery.iAuto.timer);
302
- var subject = jQuery.iAuto.getFieldValues(this);
303
-
304
- var pressedKey = e.charCode || e.keyCode || -1;
305
- if (/13|27|35|36|38|40|9/.test(pressedKey) && jQuery.iAuto.items) {
306
- if (window.event) {
307
- window.event.cancelBubble = true;
308
- window.event.returnValue = false;
309
- } else {
310
- e.preventDefault();
311
- e.stopPropagation();
312
- }
313
- if (jQuery.iAuto.selectedItem != null)
314
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).className = '';
315
- else
316
- jQuery.iAuto.selectedItem = -1;
317
- switch(pressedKey) {
318
- //enter
319
- case 9:
320
- case 13:
321
- if (jQuery.iAuto.selectedItem == -1)
322
- jQuery.iAuto.selectedItem = 0;
323
- var selectedItem = jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0);
324
- var valueToAdd = selectedItem.getAttribute('rel');
325
- this.value = subject.pre + valueToAdd + this.autoCFG.multipleSeparator + subject.post;
326
- jQuery.iAuto.lastValue = subject.item;
327
- jQuery.iAuto.selection(
328
- this,
329
- subject.pre.length + valueToAdd.length + this.autoCFG.multipleSeparator.length,
330
- subject.pre.length + valueToAdd.length + this.autoCFG.multipleSeparator.length
331
- );
332
- jQuery.iAuto.clear();
333
- if (this.autoCFG.onSelect) {
334
- iteration = parseInt(selectedItem.getAttribute('dir'))||0;
335
- jQuery.iAuto.applyOn(this,this.autoCFG.lastSuggestion.get(iteration), 'onSelect');
336
- }
337
- if (this.scrollIntoView)
338
- this.scrollIntoView(false);
339
- return pressedKey != 13;
340
- break;
341
- //escape
342
- case 27:
343
- this.value = subject.pre + jQuery.iAuto.lastValue + this.autoCFG.multipleSeparator + subject.post;
344
- this.autoCFG.lastSuggestion = null;
345
- jQuery.iAuto.clear();
346
- if (this.scrollIntoView)
347
- this.scrollIntoView(false);
348
- return false;
349
- break;
350
- //end
351
- case 35:
352
- jQuery.iAuto.selectedItem = jQuery.iAuto.items.size() - 1;
353
- break;
354
- //home
355
- case 36:
356
- jQuery.iAuto.selectedItem = 0;
357
- break;
358
- //up
359
- case 38:
360
- jQuery.iAuto.selectedItem --;
361
- if (jQuery.iAuto.selectedItem < 0)
362
- jQuery.iAuto.selectedItem = jQuery.iAuto.items.size() - 1;
363
- break;
364
- case 40:
365
- jQuery.iAuto.selectedItem ++;
366
- if (jQuery.iAuto.selectedItem == jQuery.iAuto.items.size())
367
- jQuery.iAuto.selectedItem = 0;
368
- break;
369
- }
370
- jQuery.iAuto.applyOn(this,this.autoCFG.lastSuggestion.get(jQuery.iAuto.selectedItem||0), 'onHighlight');
371
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).className = this.autoCFG.selectClass;
372
- if (jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).scrollIntoView)
373
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).scrollIntoView(false);
374
- if(this.autoCFG.autofill) {
375
- var valToAdd = jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).getAttribute('rel');
376
- this.value = subject.pre + valToAdd + this.autoCFG.multipleSeparator + subject.post;
377
- if(jQuery.iAuto.lastValue.length != valToAdd.length)
378
- jQuery.iAuto.selection(
379
- this,
380
- subject.pre.length + jQuery.iAuto.lastValue.length,
381
- subject.pre.length + valToAdd.length
382
- );
383
- }
384
- return false;
385
- }
386
- jQuery.iAuto.checkCache.apply(this);
387
-
388
- if (this.autoCFG.inCache == false) {
389
- if (subject.item != jQuery.iAuto.lastValue && subject.item.length >= this.autoCFG.minchars)
390
- jQuery.iAuto.timer = window.setTimeout(jQuery.iAuto.update, this.autoCFG.delay);
391
- if (jQuery.iAuto.items) {
392
- jQuery.iAuto.clear();
393
- }
394
- }
395
- return true;
396
- },
397
-
398
- applyOn: function(field, item, type)
399
- {
400
- if (field.autoCFG[type]) {
401
- var data = {};
402
- childs = item.getElementsByTagName('*');
403
- for(i=0; i<childs.length; i++){
404
- data[childs[i].tagName] = childs[i].firstChild.nodeValue;
405
- }
406
- field.autoCFG[type].apply(field,[data]);
407
- }
408
- },
409
-
410
- hoverItem : function(e)
411
- {
412
- if (jQuery.iAuto.items) {
413
- if (jQuery.iAuto.selectedItem != null)
414
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).className = '';
415
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).className = '';
416
- jQuery.iAuto.selectedItem = parseInt(this.getAttribute('dir'))||0;
417
- jQuery.iAuto.items.get(jQuery.iAuto.selectedItem||0).className = jQuery.iAuto.subject.autoCFG.selectClass;
418
- }
419
- },
420
-
421
- clickItem : function(event)
422
- {
423
- window.clearTimeout(jQuery.iAuto.timer);
424
-
425
- event = event || jQuery.event.fix( window.event );
426
- event.preventDefault();
427
- event.stopPropagation();
428
- var subject = jQuery.iAuto.getFieldValues(jQuery.iAuto.subject);
429
- var valueToAdd = this.getAttribute('rel');
430
- jQuery.iAuto.subject.value = subject.pre + valueToAdd + jQuery.iAuto.subject.autoCFG.multipleSeparator + subject.post;
431
- jQuery.iAuto.lastValue = this.getAttribute('rel');
432
- jQuery.iAuto.selection(
433
- jQuery.iAuto.subject,
434
- subject.pre.length + valueToAdd.length + jQuery.iAuto.subject.autoCFG.multipleSeparator.length,
435
- subject.pre.length + valueToAdd.length + jQuery.iAuto.subject.autoCFG.multipleSeparator.length
436
- );
437
- jQuery.iAuto.clear();
438
- if (jQuery.iAuto.subject.autoCFG.onSelect) {
439
- iteration = parseInt(this.getAttribute('dir'))||0;
440
- jQuery.iAuto.applyOn(jQuery.iAuto.subject,jQuery.iAuto.subject.autoCFG.lastSuggestion.get(iteration), 'onSelect');
441
- }
442
-
443
- return false;
444
- },
445
-
446
- protect : function(e)
447
- {
448
- pressedKey = e.charCode || e.keyCode || -1;
449
- if (/13|27|35|36|38|40/.test(pressedKey) && jQuery.iAuto.items) {
450
- if (window.event) {
451
- window.event.cancelBubble = true;
452
- window.event.returnValue = false;
453
- } else {
454
- e.preventDefault();
455
- e.stopPropagation();
456
- }
457
- return false;
458
- }
459
- },
460
-
461
- build : function(options)
462
- {
463
- if (!options.source || !jQuery.iUtil) {
464
- return;
465
- }
466
-
467
- if (!jQuery.iAuto.helper) {
468
- if (jQuery.browser.msie) {
469
- jQuery('body', document).append('<iframe style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" id="autocompleteIframe" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
470
- jQuery.iAuto.iframe = jQuery('#autocompleteIframe');
471
- }
472
- jQuery('body', document).append('<div id="autocompleteHelper" style="position: absolute; top: 0; left: 0; z-index: 30001; display: none;"><ul style="margin: 0;padding: 0; list-style: none; z-index: 30002;">&nbsp;</ul></div>');
473
- jQuery.iAuto.helper = jQuery('#autocompleteHelper');
474
- jQuery.iAuto.content = jQuery('ul', jQuery.iAuto.helper);
475
- }
476
-
477
- return this.each(
478
- function()
479
- {
480
- if (this.tagName != 'INPUT' && this.getAttribute('type') != 'text' )
481
- return;
482
- this.autoCFG = {};
483
- this.autoCFG.source = options.source;
484
- this.autoCFG.minchars = Math.abs(parseInt(options.minchars)||1);
485
- this.autoCFG.helperClass = options.helperClass ? options.helperClass : '';
486
- this.autoCFG.selectClass = options.selectClass ? options.selectClass : '';
487
- this.autoCFG.onSelect = options.onSelect && options.onSelect.constructor == Function ? options.onSelect : null;
488
- this.autoCFG.onShow = options.onShow && options.onShow.constructor == Function ? options.onShow : null;
489
- this.autoCFG.onHide = options.onHide && options.onHide.constructor == Function ? options.onHide : null;
490
- this.autoCFG.onHighlight = options.onHighlight && options.onHighlight.constructor == Function ? options.onHighlight : null;
491
- this.autoCFG.inputWidth = options.inputWidth||false;
492
- this.autoCFG.multiple = options.multiple||false;
493
- this.autoCFG.multipleSeparator = this.autoCFG.multiple ? (options.multipleSeparator||', '):'';
494
- this.autoCFG.autofill = options.autofill ? true : false;
495
- this.autoCFG.delay = Math.abs(parseInt(options.delay)||1000);
496
- if (options.fx && options.fx.constructor == Object) {
497
- if (!options.fx.type || !/fade|slide|blind/.test(options.fx.type)) {
498
- options.fx.type = 'slide';
499
- }
500
- if (options.fx.type == 'slide' && !jQuery.fx.slide)
501
- return;
502
- if (options.fx.type == 'blind' && !jQuery.fx.BlindDirection)
503
- return;
504
-
505
- options.fx.duration = Math.abs(parseInt(options.fx.duration)||400);
506
- if (options.fx.duration > this.autoCFG.delay) {
507
- options.fx.duration = this.autoCFG.delay - 100;
508
- }
509
- this.autoCFG.fx = options.fx;
510
- }
511
- this.autoCFG.lastSuggestion = null;
512
- this.autoCFG.inCache = false;
513
-
514
- jQuery(this)
515
- .attr('autocomplete', 'off')
516
- .focus(
517
- function()
518
- {
519
- jQuery.iAuto.subject = this;
520
- jQuery.iAuto.lastValue = this.value;
521
- }
522
- )
523
- .keypress(jQuery.iAuto.protect)
524
- .keyup(jQuery.iAuto.autocomplete)
525
-
526
- .blur(
527
- function()
528
- {
529
- jQuery.iAuto.timer = window.setTimeout(jQuery.iAuto.clear, 200);
530
- }
531
- );
532
- }
533
- );
534
- }
535
- };
536
- jQuery.fn.Autocomplete = jQuery.iAuto.build;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/interface.js DELETED
@@ -1,8 +0,0 @@
1
- /*
2
- * Interface elements for jQuery - http://interface.eyecon.ro
3
- *
4
- * Copyright (c) 2006 Stefan Petre
5
- * Dual licensed under the MIT (MIT-LICENSE.txt)
6
- * and GPL (GPL-LICENSE.txt) licenses.
7
- */
8
- eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('6.Q={2x:D(e){B x=0;B y=0;B 4N=F;B 1w=e.1j;k(6(e).K(\'1k\')==\'1t\'){4C=1w.3z;6F=1w.11;1w.3z=\'43\';1w.1k=\'2V\';1w.11=\'2G\';4N=O}B C=e;6o(C){x+=C.5w+(C.34&&!6.2K.4J?I(C.34.5X)||0:0);y+=C.5l+(C.34&&!6.2K.4J?I(C.34.5E)||0:0);C=C.8o}C=e;6o(C&&C.5v&&C.5v.6d()!=\'1O\'){x-=C.24||0;y-=C.1X||0;C=C.3d}k(4N){1w.1k=\'1t\';1w.11=6F;1w.3z=4C}G{x:x,y:y}},78:D(C){B x=0,y=0;6o(C){x+=C.5w||0;y+=C.5l||0;C=C.8o}G{x:x,y:y}},2e:D(e){B w=6.K(e,\'1d\');B h=6.K(e,\'1a\');B 1p=0;B 1m=0;B 1w=e.1j;k(6(e).K(\'1k\')!=\'1t\'){1p=e.5u;1m=e.5p}N{4C=1w.3z;6F=1w.11;1w.3z=\'43\';1w.1k=\'2V\';1w.11=\'2G\';1p=e.5u;1m=e.5p;1w.1k=\'1t\';1w.11=6F;1w.3z=4C}G{w:w,h:h,1p:1p,1m:1m}},4Q:D(C){G{1p:C.5u||0,1m:C.5p||0}},8B:D(e){B h,w,58;k(e){w=e.5x;h=e.5n}N{58=1i.2R;w=3c.7f||6p.7f||(58&&58.5x)||1i.1O.5x;h=3c.72||6p.72||(58&&58.5n)||1i.1O.5n}G{w:w,h:h}},5r:D(e){B t,l,w,h,4F,4D;k(e&&e.6n.6d()!=\'1O\'){t=e.1X;l=e.24;w=e.77;h=e.74;4F=0;4D=0}N{k(1i.2R&&1i.2R.1X){t=1i.2R.1X;l=1i.2R.24;w=1i.2R.77;h=1i.2R.74}N k(1i.1O){t=1i.1O.1X;l=1i.1O.24;w=1i.1O.77;h=1i.1O.74}4F=6p.7f||1i.2R.5x||1i.1O.5x||0;4D=6p.72||1i.2R.5n||1i.1O.5n||0}G{t:t,l:l,w:w,h:h,4F:4F,4D:4D}},8f:D(e,4U){B C=6(e);B t=C.K(\'3s\')||\'\';B r=C.K(\'3I\')||\'\';B b=C.K(\'3F\')||\'\';B l=C.K(\'3G\')||\'\';k(4U)G{t:I(t)||0,r:I(r)||0,b:I(b)||0,l:I(l)};N G{t:t,r:r,b:b,l:l}},aG:D(e,4U){B C=6(e);B t=C.K(\'84\')||\'\';B r=C.K(\'7Z\')||\'\';B b=C.K(\'83\')||\'\';B l=C.K(\'7U\')||\'\';k(4U)G{t:I(t)||0,r:I(r)||0,b:I(b)||0,l:I(l)};N G{t:t,r:r,b:b,l:l}},5G:D(e,4U){B C=6(e);B t=C.K(\'5E\')||\'\';B r=C.K(\'7W\')||\'\';B b=C.K(\'86\')||\'\';B l=C.K(\'5X\')||\'\';k(4U)G{t:I(t)||0,r:I(r)||0,b:I(b)||0,l:I(l)||0};N G{t:t,r:r,b:b,l:l}},2T:D(3m){B x=3m.a4||(3m.9X+(1i.2R.24||1i.1O.24))||0;B y=3m.bC||(3m.bj+(1i.2R.1X||1i.1O.1X))||0;G{x:x,y:y}},79:D(3e,6Z){6Z(3e);3e=3e.5Z;6o(3e){6.Q.79(3e,6Z);3e=3e.aK}},bd:D(3e){6.Q.79(3e,D(C){1C(B 1y 27 C){k(2S C[1y]===\'D\'){C[1y]=P}}})},aT:D(C,1E){B 3i=$.Q.5r();B 8h=$.Q.2e(C);k(!1E||1E==\'4l\')$(C).K({U:3i.t+((R.3x(3i.h,3i.4D)-3i.t-8h.1m)/2)+\'1c\'});k(!1E||1E==\'4o\')$(C).K({S:3i.l+((R.3x(3i.w,3i.4F)-3i.l-8h.1p)/2)+\'1c\'})},aX:D(C,8J){B 8I=$(\'8D[@6e*="6f"]\',C||1i),6f;8I.1v(D(){6f=q.6e;q.6e=8J;q.1j.7d="aZ:b2.bm.b3(6e=\'"+6f+"\')"})}};[].7X||(60.b1.7X=D(v,n){n=(n==P)?0:n;B m=q.1F;1C(B i=n;i<m;i++)k(q[i]==v)G i;G-1});6.8E=D(e){k(/^b4$|^b5$|^b9$|^b7$|^b6$|^aY$|^aP$|^aO$|^aN$|^1O$|^aL$|^aQ$|^aR$|^aW$|^aV$|^aU$|^aS$/i.4h(e.6n))G F;N G O};6.V.ba=D(e,3X){B c=e.5Z;B cs=c.1j;cs.11=3X.11;cs.3s=3X.2f.t;cs.3G=3X.2f.l;cs.3F=3X.2f.b;cs.3I=3X.2f.r;cs.U=3X.U+\'1c\';cs.S=3X.S+\'1c\';e.3d.8A(c,e);e.3d.bb(e)};6.V.bv=D(e){k(!6.8E(e))G F;B t=6(e);B 1w=e.1j;B 4N=F;B 1U={};1U.11=t.K(\'11\');k(t.K(\'1k\')==\'1t\'){4C=t.K(\'3z\');1w.3z=\'43\';1w.1k=\'\';4N=O}1U.1T=6.Q.2e(e);1U.2f=6.Q.8f(e);B 7z=e.34?e.34.8y:t.K(\'bu\');1U.U=I(t.K(\'U\'))||0;1U.S=I(t.K(\'S\'))||0;B 8z=\'bt\'+I(R.9T()*71);B 4j=1i.9G(/^8D$|^br$|^bs$|^bw$|^68$|^bx$|^7D$|^bB$|^bA$|^bz$|^by$|^bp$|^bo$|^bg$/i.4h(e.6n)?\'2o\':e.6n);6.1y(4j,\'1u\',8z);4j.2J=\'bf\';B 2h=4j.1j;B U=0;B S=0;k(1U.11==\'3u\'||1U.11==\'2G\'){U=1U.U;S=1U.S}2h.1k=\'1t\';2h.U=U+\'1c\';2h.S=S+\'1c\';2h.11=1U.11!=\'3u\'&&1U.11!=\'2G\'?\'3u\':1U.11;2h.5F=\'43\';2h.1a=1U.1T.1m+\'1c\';2h.1d=1U.1T.1p+\'1c\';2h.3s=1U.2f.t;2h.3I=1U.2f.r;2h.3F=1U.2f.b;2h.3G=1U.2f.l;k(6.2K.57){2h.8y=7z}N{2h.be=7z}e.3d.8A(4j,e);1w.3s=\'2a\';1w.3I=\'2a\';1w.3F=\'2a\';1w.3G=\'2a\';1w.11=\'2G\';1w.8r=\'1t\';1w.U=\'2a\';1w.S=\'2a\';k(4N){1w.1k=\'1t\';1w.3z=4C}4j.a1(e);2h.1k=\'2V\';G{1U:1U,9W:6(4j)}};6.V.5R={a3:[0,1x,1x],af:[8x,1x,1x],ab:[8K,8K,ad],a9:[0,0,0],a7:[0,0,1x],a6:[8P,42,42],ag:[0,1x,1x],ae:[0,0,4u],a5:[0,4u,4u],ah:[7u,7u,7u],a2:[0,3h,0],9Z:[a0,aa,8T],aJ:[4u,0,4u],aB:[85,8T,47],az:[1x,8S,0],ai:[ay,50,aC],aD:[4u,0,0],aH:[aE,aF,aw],av:[an,0,6K],am:[1x,0,1x],al:[1x,aj,0],ak:[0,4m,0],ao:[75,0,ap],au:[8x,8N,8S],aq:[ar,bq,8N],cT:[8O,1x,1x],cN:[8M,cz,8M],cA:[6K,6K,6K],cO:[1x,cy,cx],cu:[1x,1x,8O],bD:[0,1x,0],cL:[1x,0,1x],cJ:[4m,0,0],cE:[0,0,4m],cG:[4m,4m,0],cH:[1x,8P,0],cF:[1x,6z,cI],cM:[4m,0,4m],cD:[1x,0,0],cw:[6z,6z,6z],cv:[1x,1x,1x],ct:[1x,1x,0]};6.V.4a=D(31,8w){k(6.V.5R[31])G{r:6.V.5R[31][0],g:6.V.5R[31][1],b:6.V.5R[31][2]};N k(1W=/^4R\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)$/.6L(31))G{r:I(1W[1]),g:I(1W[2]),b:I(1W[3])};N k(1W=/4R\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*\\)$/.6L(31))G{r:2d(1W[1])*2.55,g:2d(1W[2])*2.55,b:2d(1W[3])*2.55};N k(1W=/^#([a-4X-4Z-9])([a-4X-4Z-9])([a-4X-4Z-9])$/.6L(31))G{r:I("56"+1W[1]+1W[1]),g:I("56"+1W[2]+1W[2]),b:I("56"+1W[3]+1W[3])};N k(1W=/^#([a-4X-4Z-9]{2})([a-4X-4Z-9]{2})([a-4X-4Z-9]{2})$/.6L(31))G{r:I("56"+1W[1]),g:I("56"+1W[2]),b:I("56"+1W[3])};N G 8w==O?F:{r:1x,g:1x,b:1x}};6.V.8v={86:1,5X:1,7W:1,5E:1,4g:1,cZ:1,1a:1,S:1,cY:1,d1:1,3F:1,3G:1,3I:1,3s:1,5a:1,6g:1,5d:1,6i:1,1B:1,cW:1,cS:1,83:1,7U:1,7Z:1,84:1,53:1,cU:1,U:1,1d:1,2Z:1};6.V.8m={cQ:1,cR:1,cP:1,cV:1,cX:1,31:1,d0:1};6.V.5L=[\'cq\',\'bU\',\'bT\',\'bS\'];6.V.7A={\'7J\':[\'5T\',\'8t\'],\'6C\':[\'5T\',\'7V\'],\'6P\':[\'6P\',\'\'],\'6U\':[\'6U\',\'\']};6.3j.1R({7a:D(3T,51,1S,5P){G q.5O(D(){B 6h=6.51(51,1S,5P);B e=3W 6.8n(q,6h,3T)})},8j:D(51,5P){G q.5O(D(){B 6h=6.51(51,5P);B e=3W 6.8j(q,6h)})},5h:D(23){G q.1v(D(){k(q.3Y)6.7r(q,23)})},bR:D(23){G q.1v(D(){k(q.3Y)6.7r(q,23);k(q.5O&&q.5O[\'V\'])q.5O.V=[]})}});6.1R({8j:D(1z,12){B z=q,29;z.23=D(){k(6.8C(12.33))12.33.1H(1z)};z.3U=7n(D(){z.23()},12.1g);1z.3Y=z},1S:{7L:D(p,n,1l,1h,1g){G((-R.9o(p*R.3k)/2)+0.5)*1h+1l}},8n:D(1z,12,3T){B z=q,29;B y=1z.1j;B 8L=6.K(1z,"5F");B 4p=6.K(1z,"1k");B 1A={};z.6k=(3W 8V()).8U();12.1S=12.1S&&6.1S[12.1S]?12.1S:\'7L\';z.6X=D(1P,2y){k(6.V.8v[1P]){k(2y==\'41\'||2y==\'3q\'||2y==\'8u\'){k(!1z.46)1z.46={};B r=2d(6.2m(1z,1P));1z.46[1P]=r&&r>-71?r:(2d(6.K(1z,1P))||0);2y=2y==\'8u\'?(4p==\'1t\'?\'41\':\'3q\'):2y;12[2y]=O;1A[1P]=2y==\'41\'?[0,1z.46[1P]]:[1z.46[1P],0];k(1P!=\'1B\')y[1P]=1A[1P][0]+(1P!=\'2Z\'&&1P!=\'8e\'?\'1c\':\'\');N 6.1y(y,"1B",1A[1P][0])}N{1A[1P]=[2d(6.2m(1z,1P)),2d(2y)||0]}}N k(6.V.8m[1P])1A[1P]=[6.V.4a(6.2m(1z,1P)),6.V.4a(2y)];N k(/^6P$|6U$|5T$|6C$|7J$/i.4h(1P)){B m=2y.3V(/\\s+/g,\' \').3V(/4R\\s*\\(\\s*/g,\'4R(\').3V(/\\s*,\\s*/g,\',\').3V(/\\s*\\)/g,\')\').9F(/([^\\s]+)/g);3O(1P){1n\'6P\':1n\'6U\':1n\'7J\':1n\'6C\':m[3]=m[3]||m[1]||m[0];m[2]=m[2]||m[0];m[1]=m[1]||m[0];1C(B i=0;i<6.V.5L.1F;i++){B 3S=6.V.7A[1P][0]+6.V.5L[i]+6.V.7A[1P][1];1A[3S]=1P==\'6C\'?[6.V.4a(6.2m(1z,3S)),6.V.4a(m[i])]:[2d(6.2m(1z,3S)),2d(m[i])]}1K;1n\'5T\':1C(B i=0;i<m.1F;i++){B 8b=2d(m[i]);B 6J=!c0(8b)?\'8t\':(!/bY|1t|43|bX|bQ|bP|cr|bH|bG|bE|bF/i.4h(m[i])?\'7V\':F);k(6J){1C(B j=0;j<6.V.5L.1F;j++){3S=\'5T\'+6.V.5L[j]+6J;1A[3S]=6J==\'7V\'?[6.V.4a(6.2m(1z,3S)),6.V.4a(m[i])]:[2d(6.2m(1z,3S)),8b]}}N{y[\'bN\']=m[i]}}1K}}N{y[1P]=2y}G F};1C(p 27 3T){k(p==\'1j\'){B 3r=6.8i(3T[p]);1C(4B 27 3r){q.6X(4B,3r[4B])}}N k(p==\'2J\'){k(1i.6x)1C(B i=0;i<1i.6x.1F;i++){B 4z=1i.6x[i].4z||1i.6x[i].bL||P;k(4z){1C(B j=0;j<4z.1F;j++){k(4z[j].c1==\'.\'+3T[p]){B 4K=3W c2(\'\\.\'+3T[p]+\' {\');B 3P=4z[j].1j.cj;B 3r=6.8i(3P.3V(4K,\'\').3V(/}/g,\'\'));1C(4B 27 3r){q.6X(4B,3r[4B])}}}}}}N{q.6X(p,3T[p])}}y.1k=4p==\'1t\'?\'2V\':4p;y.5F=\'43\';z.23=D(){B t=(3W 8V()).8U();k(t>12.1g+z.6k){7i(z.3U);z.3U=P;1C(p 27 1A){k(p=="1B")6.1y(y,"1B",1A[p][1]);N k(2S 1A[p][1]==\'7D\')y[p]=\'4R(\'+1A[p][1].r+\',\'+1A[p][1].g+\',\'+1A[p][1].b+\')\';N y[p]=1A[p][1]+(p!=\'2Z\'&&p!=\'8e\'?\'1c\':\'\')}k(12.3q||12.41)1C(B p 27 1z.46)k(p=="1B")6.1y(y,p,1z.46[p]);N y[p]="";y.1k=12.3q?\'1t\':(4p!=\'1t\'?4p:\'2V\');y.5F=8L;1z.3Y=P;k(6.8C(12.33))12.33.1H(1z)}N{B n=t-q.6k;B 5q=n/12.1g;1C(p 27 1A){k(2S 1A[p][1]==\'7D\'){y[p]=\'4R(\'+I(6.1S[12.1S](5q,n,1A[p][0].r,(1A[p][1].r-1A[p][0].r),12.1g))+\',\'+I(6.1S[12.1S](5q,n,1A[p][0].g,(1A[p][1].g-1A[p][0].g),12.1g))+\',\'+I(6.1S[12.1S](5q,n,1A[p][0].b,(1A[p][1].b-1A[p][0].b),12.1g))+\')\'}N{B 89=6.1S[12.1S](5q,n,1A[p][0],(1A[p][1]-1A[p][0]),12.1g);k(p=="1B")6.1y(y,"1B",89);N y[p]=89+(p!=\'2Z\'&&p!=\'8e\'?\'1c\':\'\')}}}};z.3U=7n(D(){z.23()},13);1z.3Y=z},7r:D(1z,23){k(23)1z.3Y.6k-=ck;N{3c.7i(1z.3Y.3U);1z.3Y=P;6.cl(1z,"V")}}});6.8i=D(3P){B 3r={};k(2S 3P==\'7m\'){3P=3P.6d().8H(\';\');1C(B i=0;i<3P.1F;i++){4K=3P[i].8H(\':\');k(4K.1F==2){3r[6.8G(4K[0].3V(/\\-(\\w)/g,D(m,c){G c.co()}))]=6.8G(4K[1])}}}G 3r};6.H={W:P,A:P,3R:D(){G q.1v(D(){k(q.6M){q.8.3b.2i(\'32\',6.H.76);q.8=P;q.6M=F;k(6.2K.57){q.73="cn"}N{q.1j.cm=\'\';q.1j.8q=\'\';q.1j.8p=\'\'}}})},76:D(e){k(6.H.A!=P){6.H.6W(e);G F}B u=q.2u;6(1i).1Q(\'2D\',6.H.7h).1Q(\'3Z\',6.H.6W);u.8.Y=6.Q.2T(e);u.8.2H=u.8.Y;u.8.5s=F;u.8.cf=q!=q.2u;6.H.A=u;k(u.8.3v&&q!=q.2u){81=6.Q.2x(u.3d);82=6.Q.2e(u);7Q={x:I(6.K(u,\'S\'))||0,y:I(6.K(u,\'U\'))||0};1f=u.8.2H.x-81.x-82.1p/2-7Q.x;1e=u.8.2H.y-81.y-82.1m/2-7Q.y;6.22.3f(u,[1f,1e])}G 6.4G||F},8X:D(e){B u=6.H.A;u.8.5s=O;B 6Y=u.1j;u.8.4x=6.K(u,\'1k\');u.8.3l=6.K(u,\'11\');k(!u.8.7S)u.8.7S=u.8.3l;u.8.1s={x:I(6.K(u,\'S\'))||0,y:I(6.K(u,\'U\'))||0};u.8.6t=0;u.8.6G=0;k(6.2K.57){B 7l=6.Q.5G(u,O);u.8.6t=7l.l||0;u.8.6G=7l.t||0}u.8.19=6.1R(6.Q.2x(u),6.Q.2e(u));k(u.8.3l!=\'3u\'&&u.8.3l!=\'2G\'){6Y.11=\'3u\'}6.H.W.7T();B 3o=u.9d(O);6(3o).K({1k:\'2V\',S:\'2a\',U:\'2a\'});3o.1j.3s=\'0\';3o.1j.3I=\'0\';3o.1j.3F=\'0\';3o.1j.3G=\'0\';6.H.W.2B(3o);B 2p=6.H.W.X(0).1j;k(u.8.7c){2p.1d=\'8F\';2p.1a=\'8F\'}N{2p.1a=u.8.19.1m+\'1c\';2p.1d=u.8.19.1p+\'1c\'}2p.1k=\'2V\';2p.3s=\'2a\';2p.3I=\'2a\';2p.3F=\'2a\';2p.3G=\'2a\';6.1R(u.8.19,6.Q.2e(3o));k(u.8.1Y){k(u.8.1Y.S){u.8.1s.x+=u.8.Y.x-u.8.19.x-u.8.1Y.S;u.8.19.x=u.8.Y.x-u.8.1Y.S}k(u.8.1Y.U){u.8.1s.y+=u.8.Y.y-u.8.19.y-u.8.1Y.U;u.8.19.y=u.8.Y.y-u.8.1Y.U}k(u.8.1Y.53){u.8.1s.x+=u.8.Y.x-u.8.19.x-u.8.19.1m+u.8.1Y.53;u.8.19.x=u.8.Y.x-u.8.19.1p+u.8.1Y.53}k(u.8.1Y.4g){u.8.1s.y+=u.8.Y.y-u.8.19.y-u.8.19.1m+u.8.1Y.4g;u.8.19.y=u.8.Y.y-u.8.19.1m+u.8.1Y.4g}}u.8.1L=u.8.1s.x;u.8.1J=u.8.1s.y;k(u.8.5K||u.8.1D==\'5S\'){5U=6.Q.5G(u.3d,O);u.8.19.x=u.5w+(6.2K.57?0:6.2K.4J?-5U.l:5U.l);u.8.19.y=u.5l+(6.2K.57?0:6.2K.4J?-5U.t:5U.t);6(u.3d).2B(6.H.W.X(0))}k(u.8.1D){6.H.7M(u);u.8.3t.1D=6.H.8c}k(u.8.3v){6.22.7H(u)}2p.S=u.8.19.x-u.8.6t+\'1c\';2p.U=u.8.19.y-u.8.6G+\'1c\';2p.1d=u.8.19.1p+\'1c\';2p.1a=u.8.19.1m+\'1c\';6.H.A.8.6r=F;k(u.8.3E){u.8.3t.3N=6.H.7I}k(u.8.2Z!=F){6.H.W.K(\'2Z\',u.8.2Z)}k(u.8.1B){6.H.W.K(\'1B\',u.8.1B);k(3c.6s){6.H.W.K(\'7d\',\'8W(1B=\'+u.8.1B*3h+\')\')}}k(u.8.54){6.H.W.3g(u.8.54);6.H.W.X(0).5Z.1j.1k=\'1t\'}k(u.8.2F)u.8.2F.1H(u,[3o,u.8.1s.x,u.8.1s.y]);k(6.Z&&6.Z.5g>0){6.Z.9N(u)}k(u.8.2A==F){6Y.1k=\'1t\'}G F},7M:D(u){k(u.8.1D.1N==7q){k(u.8.1D==\'5S\'){u.8.1q=6.1R({x:0,y:0},6.Q.2e(u.3d));B 5f=6.Q.5G(u.3d,O);u.8.1q.w=u.8.1q.1p-5f.l-5f.r;u.8.1q.h=u.8.1q.1m-5f.t-5f.b}N k(u.8.1D==\'1i\'){B 7j=6.Q.8B();u.8.1q={x:0,y:0,w:7j.w,h:7j.h}}}N k(u.8.1D.1N==60){u.8.1q={x:I(u.8.1D[0])||0,y:I(u.8.1D[1])||0,w:I(u.8.1D[2])||0,h:I(u.8.1D[3])||0}}u.8.1q.1f=u.8.1q.x-u.8.19.x;u.8.1q.1e=u.8.1q.y-u.8.19.y},6y:D(A){k(A.8.5K||A.8.1D==\'5S\'){6(\'1O\',1i).2B(6.H.W.X(0))}6.H.W.7T().3q().K(\'1B\',1);k(3c.6s){6.H.W.K(\'7d\',\'8W(1B=3h)\')}},6W:D(e){6(1i).2i(\'2D\',6.H.7h).2i(\'3Z\',6.H.6W);k(6.H.A==P){G}B A=6.H.A;6.H.A=P;k(A.8.5s==F){G F}k(A.8.2z==O){6(A).K(\'11\',A.8.3l)}B 6Y=A.1j;k(A.3v){6.H.W.K(\'8a\',\'5y\')}k(A.8.54){6.H.W.3y(A.8.54)}k(A.8.49==F){k(A.8.V>0){k(!A.8.1E||A.8.1E==\'4o\'){B x=3W 6.V(A,{1g:A.8.V},\'S\');x.8R(A.8.1s.x,A.8.5N)}k(!A.8.1E||A.8.1E==\'4l\'){B y=3W 6.V(A,{1g:A.8.V},\'U\');y.8R(A.8.1s.y,A.8.5C)}}N{k(!A.8.1E||A.8.1E==\'4o\')A.1j.S=A.8.5N+\'1c\';k(!A.8.1E||A.8.1E==\'4l\')A.1j.U=A.8.5C+\'1c\'}6.H.6y(A);k(A.8.2A==F){6(A).K(\'1k\',A.8.4x)}}N k(A.8.V>0){A.8.6r=O;B 4v=F;k(6.Z&&6.T&&A.8.2z){4v=6.Q.2x(6.T.W.X(0))}6.H.W.7a({S:4v?4v.x:A.8.19.x,U:4v?4v.y:A.8.19.y},A.8.V,D(){A.8.6r=F;k(A.8.2A==F){A.1j.1k=A.8.4x}6.H.6y(A)})}N{6.H.6y(A);k(A.8.2A==F){6(A).K(\'1k\',A.8.4x)}}k(6.Z&&6.Z.5g>0){6.Z.9U(A)}k(6.T&&A.8.2z){6.T.9g(A)}k(A.8.1Z&&(A.8.5N!=A.8.1s.x||A.8.5C!=A.8.1s.y)){A.8.1Z.1H(A,A.8.7E||[0,0,A.8.5N,A.8.5C])}k(A.8.2q)A.8.2q.1H(A);G F},7I:D(x,y,1f,1e){k(1f!=0)1f=I((1f+(q.8.3E*1f/R.3D(1f))/2)/q.8.3E)*q.8.3E;k(1e!=0)1e=I((1e+(q.8.3K*1e/R.3D(1e))/2)/q.8.3K)*q.8.3K;G{1f:1f,1e:1e,x:0,y:0}},8c:D(x,y,1f,1e){1f=R.2l(R.3x(1f,q.8.1q.1f),q.8.1q.w+q.8.1q.1f-q.8.19.1p);1e=R.2l(R.3x(1e,q.8.1q.1e),q.8.1q.h+q.8.1q.1e-q.8.19.1m);G{1f:1f,1e:1e,x:0,y:0}},7h:D(e){k(6.H.A==P||6.H.A.8.6r==O){G}B A=6.H.A;A.8.2H=6.Q.2T(e);k(A.8.5s==F){8Q=R.c4(R.4T(A.8.Y.x-A.8.2H.x,2)+R.4T(A.8.Y.y-A.8.2H.y,2));k(8Q<A.8.4b){G}N{6.H.8X(e)}}B 1f=A.8.2H.x-A.8.Y.x;B 1e=A.8.2H.y-A.8.Y.y;1C(B i 27 A.8.3t){B 2c=A.8.3t[i].1H(A,[A.8.1s.x+1f,A.8.1s.y+1e,1f,1e]);k(2c&&2c.1N==6D){1f=i!=\'4Y\'?2c.1f:(2c.x-A.8.1s.x);1e=i!=\'4Y\'?2c.1e:(2c.y-A.8.1s.y)}}A.8.1L=A.8.19.x+1f-A.8.6t;A.8.1J=A.8.19.y+1e-A.8.6G;k(A.8.3v&&(A.8.2g||A.8.1Z)){6.22.2g(A,A.8.1L,A.8.1J)}k(A.8.2O)A.8.2O.1H(A,[A.8.1s.x+1f,A.8.1s.y+1e]);k(!A.8.1E||A.8.1E==\'4o\'){A.8.5N=A.8.1s.x+1f;6.H.W.X(0).1j.S=A.8.1L+\'1c\'}k(!A.8.1E||A.8.1E==\'4l\'){A.8.5C=A.8.1s.y+1e;6.H.W.X(0).1j.U=A.8.1J+\'1c\'}k(6.Z&&6.Z.5g>0){6.Z.6S(A)}G F},2N:D(o){k(!6.H.W){6(\'1O\',1i).2B(\'<2o 1u="8s"></2o>\');6.H.W=6(\'#8s\');B C=6.H.W.X(0);B 2X=C.1j;2X.11=\'2G\';2X.1k=\'1t\';2X.8a=\'5y\';2X.8r=\'1t\';2X.5F=\'43\';k(3c.6s){C.73="9I"}N{2X.cb=\'1t\';2X.8p=\'1t\';2X.8q=\'1t\'}}k(!o){o={}}G q.1v(D(){k(q.6M||!6.Q)G;k(3c.6s){q.cK=D(){G F};q.ca=D(){G F}}B C=q;B 3b=o.2b?6(q).cc(o.2b):6(q);k(6.2K.57){3b.1v(D(){q.73="9I"})}N{3b.K(\'-cd-4Y-68\',\'1t\');3b.K(\'4Y-68\',\'1t\');3b.K(\'-c9-4Y-68\',\'1t\')}q.8={3b:3b,49:o.49?O:F,2A:o.2A?O:F,2z:o.2z?o.2z:F,3v:o.3v?o.3v:F,5K:o.5K?o.5K:F,2Z:o.2Z?I(o.2Z)||0:F,1B:o.1B?2d(o.1B):F,V:I(o.V)||P,44:o.44?o.44:F,3t:{},Y:{},2F:o.2F&&o.2F.1N==2n?o.2F:F,2q:o.2q&&o.2q.1N==2n?o.2q:F,1Z:o.1Z&&o.1Z.1N==2n?o.1Z:F,1E:/4l|4o/.4h(o.1E)?o.1E:F,4b:o.4b?I(o.4b)||0:0,1Y:o.1Y?o.1Y:F,7c:o.7c?O:F,54:o.54||F};k(o.3t&&o.3t.1N==2n)q.8.3t.4Y=o.3t;k(o.2O&&o.2O.1N==2n)q.8.2O=o.2O;k(o.1D&&((o.1D.1N==7q&&(o.1D==\'5S\'||o.1D==\'1i\'))||(o.1D.1N==60&&o.1D.1F==4))){q.8.1D=o.1D}k(o.1V){q.8.1V=o.1V}k(o.3N){k(2S o.3N==\'c8\'){q.8.3E=I(o.3N)||1;q.8.3K=I(o.3N)||1}N k(o.3N.1F==2){q.8.3E=I(o.3N[0])||1;q.8.3K=I(o.3N[1])||1}}k(o.2g&&o.2g.1N==2n){q.8.2g=o.2g}q.6M=O;3b.1v(D(){q.2u=C});3b.1Q(\'32\',6.H.76)})}};6.3j.1R({6V:6.H.3R,4w:6.H.2N});6.Z={9V:D(3A,3w,4P,4y){G 3A<=6.H.A.8.1L&&(3A+4P)>=(6.H.A.8.1L+6.H.A.8.19.w)&&3w<=6.H.A.8.1J&&(3w+4y)>=(6.H.A.8.1J+6.H.A.8.19.h)?O:F},7R:D(3A,3w,4P,4y){G!(3A>(6.H.A.8.1L+6.H.A.8.19.w)||(3A+4P)<6.H.A.8.1L||3w>(6.H.A.8.1J+6.H.A.8.19.h)||(3w+4y)<6.H.A.8.1J)?O:F},Y:D(3A,3w,4P,4y){G 3A<6.H.A.8.2H.x&&(3A+4P)>6.H.A.8.2H.x&&3w<6.H.A.8.2H.y&&(3w+4y)>6.H.A.8.2H.y?O:F},3H:F,2t:{},5g:0,2k:{},9N:D(u){k(6.H.A==P){G}B i;6.Z.2t={};B 7b=F;1C(i 27 6.Z.2k){k(6.Z.2k[i]!=P){B M=6.Z.2k[i].X(0);k(6(6.H.A).7w(\'.\'+M.L.a)){k(M.L.m==F){M.L.p=6.1R(6.Q.2x(M),6.Q.4Q(M));M.L.m=O}k(M.L.ac){6.Z.2k[i].3g(M.L.ac)}6.Z.2t[i]=6.Z.2k[i];k(6.T&&M.L.s&&6.H.A.8.2z){M.L.C=6(\'.\'+M.L.a,M);u.1j.1k=\'1t\';6.T.7t(M);M.L.6R=6.T.5J(6.1y(M,\'1u\')).4s;u.1j.1k=u.8.4x;7b=O}k(M.L.6u){M.L.6u.1H(6.Z.2k[i].X(0),[6.H.A])}}}}k(7b){6.T.2w()}},9K:D(){6.Z.2t={};1C(i 27 6.Z.2k){k(6.Z.2k[i]!=P){B M=6.Z.2k[i].X(0);k(6(6.H.A).7w(\'.\'+M.L.a)){M.L.p=6.1R(6.Q.2x(M),6.Q.4Q(M));k(M.L.ac){6.Z.2k[i].3g(M.L.ac)}6.Z.2t[i]=6.Z.2k[i];k(6.T&&M.L.s&&6.H.A.8.2z){M.L.C=6(\'.\'+M.L.a,M);u.1j.1k=\'1t\';6.T.7t(M);u.1j.1k=u.8.4x}}}}},6S:D(e){k(6.H.A==P){G}6.Z.3H=F;B i;B 7o=F;B 9R=0;1C(i 27 6.Z.2t){B M=6.Z.2t[i].X(0);k(6.Z.3H==F&&6.Z[M.L.t](M.L.p.x,M.L.p.y,M.L.p.1p,M.L.p.1m)){k(M.L.2L&&M.L.h==F){6.Z.2t[i].3g(M.L.2L)}k(M.L.h==F&&M.L.4q){7o=O}M.L.h=O;6.Z.3H=M;k(6.T&&M.L.s&&6.H.A.8.2z){6.T.W.X(0).2J=M.L.9Q;6.T.6S(M)}9R++}N k(M.L.h==O){k(M.L.4W){M.L.4W.1H(M,[e,6.H.W.X(0).5Z,M.L.V])}k(M.L.2L){6.Z.2t[i].3y(M.L.2L)}M.L.h=F}}k(6.T&&!6.Z.3H&&6.H.A.2z){6.T.W.X(0).1j.1k=\'1t\'}k(7o){6.Z.3H.L.4q.1H(6.Z.3H,[e,6.H.W.X(0).5Z])}},9U:D(e){B i;1C(i 27 6.Z.2t){B M=6.Z.2t[i].X(0);k(M.L.ac){6.Z.2t[i].3y(M.L.ac)}k(M.L.2L){6.Z.2t[i].3y(M.L.2L)}k(M.L.s){6.T.4O[6.T.4O.1F]=i}k(M.L.6q&&M.L.h==O){M.L.h=F;M.L.6q.1H(M,[e,M.L.V])}M.L.m=F;M.L.h=F}6.Z.2t={}},3R:D(){G q.1v(D(){k(q.6w){k(q.L.s){1u=6.1y(q,\'1u\');6.T.3B[1u]=P;6(\'.\'+q.L.a,q).6V()}6.Z.2k[\'d\'+q.70]=P;q.6w=F;q.f=P}})},2N:D(o){G q.1v(D(){k(q.6w==O||!o.2j||!6.Q||!6.H){G}q.L={a:o.2j,ac:o.6N||F,2L:o.6O||F,9Q:o.30||F,6q:o.c3||o.6q||F,4q:o.4q||o.90||F,4W:o.4W||o.8Z||F,6u:o.6u||F,t:o.45&&(o.45==\'9V\'||o.45==\'7R\')?o.45:\'Y\',V:o.V?o.V:F,m:F,h:F};k(o.7N==O&&6.T){1u=6.1y(q,\'1u\');6.T.3B[1u]=q.L.a;q.L.s=O;k(o.1Z){q.L.1Z=o.1Z;q.L.6R=6.T.5J(1u).4s}}q.6w=O;q.70=I(R.9T()*71);6.Z.2k[\'d\'+q.70]=6(q);6.Z.5g++})}};6.3j.1R({9e:6.Z.3R,91:6.Z.2N});6.c5=6.Z.9K;6.E={18:P,2r:P,A:P,Y:P,1T:P,11:P,4I:D(e){6.E.A=(q.6a)?q.6a:q;6.E.Y=6.Q.2T(e);6.E.1T={1d:I(6(6.E.A).K(\'1d\'))||0,1a:I(6(6.E.A).K(\'1a\'))||0};6.E.11={U:I(6(6.E.A).K(\'U\'))||0,S:I(6(6.E.A).K(\'S\'))||0};6(1i).1Q(\'2D\',6.E.7e).1Q(\'3Z\',6.E.7g);k(2S 6.E.A.J.9J===\'D\'){6.E.A.J.9J.1H(6.E.A)}G F},7g:D(e){6(1i).2i(\'2D\',6.E.7e).2i(\'3Z\',6.E.7g);k(2S 6.E.A.J.9L===\'D\'){6.E.A.J.9L.1H(6.E.A)}6.E.A=P},7e:D(e){k(!6.E.A){G}Y=6.Q.2T(e);4r=6.E.11.U-6.E.Y.y+Y.y;4t=6.E.11.S-6.E.Y.x+Y.x;4r=R.3x(R.2l(4r,6.E.A.J.5e-6.E.1T.1a),6.E.A.J.4S);4t=R.3x(R.2l(4t,6.E.A.J.5i-6.E.1T.1d),6.E.A.J.4M);k(2S 6.E.A.J.2O===\'D\'){B 5c=6.E.A.J.2O.1H(6.E.A,[4t,4r]);k(2S 5c==\'c6\'&&5c.1F==2){4t=5c[0];4r=5c[1]}}6.E.A.1j.U=4r+\'1c\';6.E.A.1j.S=4t+\'1c\';G F},2w:D(e){6(1i).1Q(\'2D\',6.E.5y).1Q(\'3Z\',6.E.5h);6.E.18=q.18;6.E.2r=q.2r;6.E.Y=6.Q.2T(e);k(6.E.18.J.2F){6.E.18.J.2F.1H(6.E.18,[q])}6.E.1T={1d:I(6(q.18).K(\'1d\'))||0,1a:I(6(q.18).K(\'1a\'))||0};6.E.11={U:I(6(q.18).K(\'U\'))||0,S:I(6(q.18).K(\'S\'))||0};G F},5h:D(){6(1i).2i(\'2D\',6.E.5y).2i(\'3Z\',6.E.5h);k(6.E.18.J.2q){6.E.18.J.2q.1H(6.E.18,[6.E.2r])}6.E.18=P;6.E.2r=P},4d:D(1f,6Q){G R.2l(R.3x(6.E.1T.1d+1f*6Q,6.E.18.J.6i),6.E.18.J.6g)},4e:D(1e,6Q){G R.2l(R.3x(6.E.1T.1a+1e*6Q,6.E.18.J.5d),6.E.18.J.5a)},9H:D(1a){G R.2l(R.3x(1a,6.E.18.J.5d),6.E.18.J.5a)},5y:D(e){k(6.E.18==P){G}Y=6.Q.2T(e);1f=Y.x-6.E.Y.x;1e=Y.y-6.E.Y.y;1b={1d:6.E.1T.1d,1a:6.E.1T.1a};1G={U:6.E.11.U,S:6.E.11.S};3O(6.E.2r){1n\'e\':1b.1d=6.E.4d(1f,1);1K;1n\'9E\':1b.1d=6.E.4d(1f,1);1b.1a=6.E.4e(1e,1);1K;1n\'w\':1b.1d=6.E.4d(1f,-1);1G.S=6.E.11.S-1b.1d+6.E.1T.1d;1K;1n\'3n\':1b.1d=6.E.4d(1f,-1);1G.S=6.E.11.S-1b.1d+6.E.1T.1d;1b.1a=6.E.4e(1e,1);1K;1n\'4H\':1b.1a=6.E.4e(1e,-1);1G.U=6.E.11.U-1b.1a+6.E.1T.1a;1b.1d=6.E.4d(1f,-1);1G.S=6.E.11.S-1b.1d+6.E.1T.1d;1K;1n\'n\':1b.1a=6.E.4e(1e,-1);1G.U=6.E.11.U-1b.1a+6.E.1T.1a;1K;1n\'66\':1b.1a=6.E.4e(1e,-1);1G.U=6.E.11.U-1b.1a+6.E.1T.1a;1b.1d=6.E.4d(1f,1);1K;1n\'s\':1b.1a=6.E.4e(1e,1);1K}k(6.E.18.J.2E){k(6.E.2r==\'n\'||6.E.2r==\'s\')2I=1b.1a*6.E.18.J.2E;N 2I=1b.1d;3a=6.E.9H(2I*6.E.18.J.2E);2I=3a/6.E.18.J.2E;3O(6.E.2r){1n\'n\':1n\'4H\':1n\'66\':1G.U+=1b.1a-3a;1K}3O(6.E.2r){1n\'4H\':1n\'w\':1n\'3n\':1G.S+=1b.1d-2I;1K}1b.1a=3a;1b.1d=2I}k(1G.U<6.E.18.J.4S){3a=1b.1a+1G.U-6.E.18.J.4S;1G.U=6.E.18.J.4S;k(6.E.18.J.2E){2I=3a/6.E.18.J.2E;3O(6.E.2r){1n\'4H\':1n\'w\':1n\'3n\':1G.S+=1b.1d-2I;1K}1b.1d=2I}1b.1a=3a}k(1G.S<6.E.18.J.4M){2I=1b.1d+1G.S-6.E.18.J.4M;1G.S=6.E.18.J.4M;k(6.E.18.J.2E){3a=2I*6.E.18.J.2E;3O(6.E.2r){1n\'n\':1n\'4H\':1n\'66\':1G.U+=1b.1a-3a;1K}1b.1a=3a}1b.1d=2I}k(1G.U+1b.1a>6.E.18.J.5e){1b.1a=6.E.18.J.5e-1G.U;k(6.E.18.J.2E){1b.1d=1b.1a/6.E.18.J.2E}}k(1G.S+1b.1d>6.E.18.J.5i){1b.1d=6.E.18.J.5i-1G.S;k(6.E.18.J.2E){1b.1a=1b.1d*6.E.18.J.2E}}B 4f=F;3p=6.E.18.1j;3p.S=1G.S+\'1c\';3p.U=1G.U+\'1c\';3p.1d=1b.1d+\'1c\';3p.1a=1b.1a+\'1c\';k(6.E.18.J.9D){4f=6.E.18.J.9D.1H(6.E.18,[1b,1G]);k(4f){k(4f.1T){6.1R(1b,4f.1T)}k(4f.11){6.1R(1G,4f.11)}}}3p.S=1G.S+\'1c\';3p.U=1G.U+\'1c\';3p.1d=1b.1d+\'1c\';3p.1a=1b.1a+\'1c\';G F},2N:D(12){k(!12||!12.2s||12.2s.1N!=6D){G}G q.1v(D(){B C=q;C.J=12;C.J.6i=12.6i||10;C.J.5d=12.5d||10;C.J.6g=12.6g||4c;C.J.5a=12.5a||4c;C.J.4S=12.4S||-9C;C.J.4M=12.4M||-9C;C.J.5i=12.5i||4c;C.J.5e=12.5e||4c;7p=6(C).K(\'11\');k(!(7p==\'3u\'||7p==\'2G\')){C.1j.11=\'3u\'}9P=/n|66|e|9E|s|3n|w|4H/g;1C(i 27 C.J.2s){k(i.6d().9F(9P)!=P){k(C.J.2s[i].1N==7q){2b=6(C.J.2s[i]);k(2b.4i()>0){C.J.2s[i]=2b.X(0)}}k(C.J.2s[i].5v){C.J.2s[i].18=C;C.J.2s[i].2r=i;6(C.J.2s[i]).1Q(\'32\',6.E.2w)}}}k(C.J.2U){k(2S C.J.2U===\'7m\'){64=6(C.J.2U);k(64.4i()>0){64.1v(D(){q.6a=C});64.1Q(\'32\',6.E.4I)}}N k(C.J.2U.5v){C.J.2U.6a=C;6(C.J.2U).1Q(\'32\',6.E.4I)}N k(C.J.2U==O){6(q).1Q(\'32\',6.E.4I)}}})},3R:D(){G q.1v(D(){B C=q;1C(i 27 C.J.2s){C.J.2s[i].18=P;C.J.2s[i].2r=P;6(C.J.2s[i]).2i(\'32\',6.E.2w)}k(C.J.2U){k(2S C.J.2U===\'7m\'){2b=6(C.J.2U);k(2b.4i()>0){2b.2i(\'32\',6.E.4I)}}N k(C.J.2U==O){6(q).2i(\'32\',6.E.4I)}}C.J=P})}};6.3j.1R({c7:6.E.2N,ce:6.E.3R});6.1M=P;6.4G=F;6.28=P;6.4E=[];6.67=D(e){B 5b=e.9k||e.9j||-1;k(5b==17||5b==16){6.4G=O}};6.63=D(e){6.4G=F};6.9c=D(e){q.f.Y=6.Q.2T(e);q.f.1o=6.1R(6.Q.2x(q),6.Q.2e(q));q.f.26=6.Q.5r(q);q.f.Y.x-=q.f.1o.x;q.f.Y.y-=q.f.1o.y;k(q.f.2L)6.1M.3g(q.f.2L);6.1M.K({1k:\'2V\',1d:\'8Y\',1a:\'8Y\'});k(q.f.o){6.1M.K(\'1B\',q.f.o)}6.28=q;6.61=F;6.4E=[];q.f.C.1v(D(){q.1o={x:q.5w+(q.34&&!6.2K.4J?I(q.34.5X)||0:0)+(6.28.24||0),y:q.5l+(q.34&&!6.2K.4J?I(q.34.5E)||0:0)+(6.28.1X||0),1p:q.5u,1m:q.5p};k(q.s==O){k(6.4G==F){q.s=F;6(q).3y(6.28.f.4L)}N{6.61=O;6.4E[6.4E.1F]=6.1y(q,\'1u\')}}});6(q).2B(6.1M.X(0));q.f.5H=6.Q.5G(6.1M[0],O);6.69.1H(q,[e]);6(1i).1Q(\'2D\',6.69).1Q(\'3Z\',6.87);G F};6.69=D(e){k(!6.28)G;6.9A.1H(6.28,[e])};6.9A=D(e){k(!6.28)G;B Y=6.Q.2T(e);B 26=6.Q.5r(6.28);Y.x+=26.l-q.f.26.l-q.f.1o.x;Y.y+=26.t-q.f.26.t-q.f.1o.y;B 5I=R.2l(Y.x,q.f.Y.x);B 3n=R.2l(R.3D(Y.x-q.f.Y.x),R.3D(q.f.26.w-5I));B 5V=R.2l(Y.y,q.f.Y.y);B 5Y=R.2l(R.3D(Y.y-q.f.Y.y),R.3D(q.f.26.h-5V));k(q.1X>0&&Y.y-20<q.1X){B 2v=R.2l(26.t,10);5V-=2v;5Y+=2v;q.1X-=2v}N k(q.1X+q.f.1o.h<q.f.26.h&&Y.y+20>q.1X+q.f.1o.h){B 2v=R.2l(q.f.26.h-q.1X,10);q.1X+=2v;k(q.1X!=26.t)5Y+=2v}k(q.24>0&&Y.x-20<q.24){B 2v=R.2l(26.l,10);5I-=2v;3n+=2v;q.24-=2v}N k(q.24+q.f.1o.w<q.f.26.w&&Y.x+20>q.24+q.f.1o.w){B 2v=R.2l(q.f.26.w-q.24,10);q.24+=2v;k(q.24!=26.l)3n+=2v}6.1M.K({S:5I+\'1c\',U:5V+\'1c\',1d:3n-(q.f.5H.l+q.f.5H.r)+\'1c\',1a:5Y-(q.f.5H.t+q.f.5H.b)+\'1c\'});6.1M.l=5I+q.f.26.l;6.1M.t=5V+q.f.26.t;6.1M.r=6.1M.l+3n;6.1M.b=6.1M.t+5Y;6.61=F;q.f.C.1v(D(){6c=6.4E.7X(6.1y(q,\'1u\'));k(!(q.1o.x>6.1M.r||(q.1o.x+q.1o.1p)<6.1M.l||q.1o.y>6.1M.b||(q.1o.y+q.1o.1m)<6.1M.t)){6.61=O;k(q.s!=O){q.s=O;6(q).3g(6.28.f.4L)}k(6c!=-1){q.s=F;6(q).3y(6.28.f.4L)}}N k((q.s==O)&&(6c==-1)){q.s=F;6(q).3y(6.28.f.4L)}N k((!q.s)&&(6.4G==O)&&(6c!=-1)){q.s=O;6(q).3g(6.28.f.4L)}});G F};6.87=D(e){k(!6.28)G;6.9b.1H(6.28,[e])};6.9b=D(e){6(1i).2i(\'2D\',6.69).2i(\'3Z\',6.87);k(!6.28)G;6.1M.K(\'1k\',\'1t\');k(q.f.2L)6.1M.3y(q.f.2L);6.28=F;6(\'1O\').2B(6.1M.X(0));k(6.61==O){k(q.f.5j)q.f.5j(6.88(6.1y(q,\'1u\')))}N{k(q.f.5k)q.f.5k(6.88(6.1y(q,\'1u\')))}6.4E=[]};6.88=D(s){B h=\'\';B o=[];k(a=6(\'#\'+s)){a.X(0).f.C.1v(D(){k(q.s==O){k(h.1F>0){h+=\'&\'}h+=s+\'[]=\'+6.1y(q,\'1u\');o[o.1F]=6.1y(q,\'1u\')}})}G{4s:h,o:o}};6.3j.cp=D(o){k(!6.1M){6(\'1O\',1i).2B(\'<2o 1u="1M"></2o>\').1Q(\'6H\',6.67).1Q(\'8g\',6.63);6.1M=6(\'#1M\');6.1M.K({11:\'2G\',1k:\'1t\'});k(3c.3m){6(\'1O\',1i).1Q(\'6H\',6.67).1Q(\'8g\',6.63)}N{6(1i).1Q(\'6H\',6.67).1Q(\'8g\',6.63)}}k(!o){o={}}G q.1v(D(){k(q.9a)G;q.9a=O;q.f={a:o.2j,o:o.1B?2d(o.1B):F,4L:o.99?o.99:F,2L:o.30?o.30:F,5j:o.5j?o.5j:F,5k:o.5k?o.5k:F};q.f.C=6(\'.\'+o.2j);6(q).1Q(\'32\',6.9c)})};6.T={4O:[],3B:{},W:F,4V:P,2w:D(){k(6.H.A==P){G}B 2W,2f,c,cs;6.T.W.X(0).2J=6.H.A.8.44;2W=6.T.W.X(0).1j;2W.1k=\'2V\';6.T.W.19=6.1R(6.Q.2x(6.T.W.X(0)),6.Q.2e(6.T.W.X(0)));2W.1d=6.H.A.8.19.1p+\'1c\';2W.1a=6.H.A.8.19.1m+\'1c\';2f=6.Q.8f(6.H.A);2W.3s=2f.t;2W.3I=2f.r;2W.3F=2f.b;2W.3G=2f.l;k(6.H.A.8.2A==O){c=6.H.A.9d(O);cs=c.1j;cs.3s=\'2a\';cs.3I=\'2a\';cs.3F=\'2a\';cs.3G=\'2a\';cs.1k=\'2V\';6.T.W.7T().2B(c)}6(6.H.A).9f(6.T.W.X(0));6.H.A.1j.1k=\'1t\'},9g:D(e){k(!e.8.2z&&6.Z.3H.7N){k(e.8.2q)e.8.2q.1H(A);6(e).K(\'11\',e.8.7S||e.8.3l);6(e).6V();6(6.Z.3H).96(e)}6.T.W.3y(e.8.44).6I(\'&98;\');6.T.4V=P;B 2W=6.T.W.X(0).1j;2W.1k=\'1t\';6.T.W.9f(e);k(e.8.V>0){6(e).94(e.8.V)}6(\'1O\').2B(6.T.W.X(0));B 5B=[];B 5A=F;1C(B i=0;i<6.T.4O.1F;i++){B M=6.Z.2k[6.T.4O[i]].X(0);B 1u=6.1y(M,\'1u\');B 5t=6.T.5J(1u);k(M.L.6R!=5t.4s){M.L.6R=5t.4s;k(5A==F&&M.L.1Z){5A=M.L.1Z}5t.1u=1u;5B[5B.1F]=5t}}6.T.4O=[];k(5A!=F&&5B.1F>0){5A(5B)}},6S:D(e,o){k(!6.H.A)G;B 3Q=F;B i=0;k(e.L.C.4i()>0){1C(i=e.L.C.4i();i>0;i--){k(e.L.C.X(i-1)!=6.H.A){k(!e.3J.7O){k((e.L.C.X(i-1).1o.y+e.L.C.X(i-1).1o.1m/2)>6.H.A.8.1J){3Q=e.L.C.X(i-1)}N{1K}}N{k((e.L.C.X(i-1).1o.x+e.L.C.X(i-1).1o.1p/2)>6.H.A.8.1L&&(e.L.C.X(i-1).1o.y+e.L.C.X(i-1).1o.1m/2)>6.H.A.8.1J){3Q=e.L.C.X(i-1)}}}}}k(3Q&&6.T.4V!=3Q){6.T.4V=3Q;6(3Q).cg(6.T.W.X(0))}N k(!3Q&&(6.T.4V!=P||6.T.W.X(0).3d!=e)){6.T.4V=P;6(e).2B(6.T.W.X(0))}6.T.W.X(0).1j.1k=\'2V\'},7t:D(e){k(6.H.A==P){G}e.L.C.1v(D(){q.1o=6.1R(6.Q.4Q(q),6.Q.2x(q))})},5J:D(s){B i;B h=\'\';B o={};k(s){k(6.T.3B[s]){o[s]=[];6(\'#\'+s+\' .\'+6.T.3B[s]).1v(D(){k(h.1F>0){h+=\'&\'}h+=s+\'[]=\'+6.1y(q,\'1u\');o[s][o[s].1F]=6.1y(q,\'1u\')})}N{1C(a 27 s){k(6.T.3B[s[a]]){o[s[a]]=[];6(\'#\'+s[a]+\' .\'+6.T.3B[s[a]]).1v(D(){k(h.1F>0){h+=\'&\'}h+=s[a]+\'[]=\'+6.1y(q,\'1u\');o[s[a]][o[s[a]].1F]=6.1y(q,\'1u\')})}}}}N{1C(i 27 6.T.3B){o[i]=[];6(\'#\'+i+\' .\'+6.T.3B[i]).1v(D(){k(h.1F>0){h+=\'&\'}h+=i+\'[]=\'+6.1y(q,\'1u\');o[i][o[i].1F]=6.1y(q,\'1u\')})}}G{4s:h,o:o}},95:D(e){k(!e.ch){G}G q.1v(D(){k(!q.3J||!6(e).7w(\'.\'+q.3J.2j))6(e).3g(q.3J.2j);6(e).4w(q.3J.8)})},3R:D(){G q.1v(D(){6(\'.\'+q.3J.2j).6V();6(q).9e();q.3J=P;q.92=P})},2N:D(o){k(o.2j&&6.Q&&6.H&&6.Z){k(!6.T.W){6(\'1O\',1i).2B(\'<2o 1u="97">&98;</2o>\');6.T.W=6(\'#97\');6.T.W.X(0).1j.1k=\'1t\'}q.91({2j:o.2j,6N:o.6N?o.6N:F,6O:o.6O?o.6O:F,30:o.30?o.30:F,4q:o.4q||o.90,4W:o.4W||o.8Z,7N:O,1Z:o.1Z||o.ci,V:o.V?o.V:F,2A:o.2A?O:F,45:o.45?o.45:\'7R\'});G q.1v(D(){B 8={49:o.49?O:F,93:4c,1B:o.1B?2d(o.1B):F,44:o.30?o.30:F,V:o.V?o.V:F,2z:O,2A:o.2A?O:F,2b:o.2b?o.2b:P,1D:o.1D?o.1D:P,2F:o.2F&&o.2F.1N==2n?o.2F:F,2O:o.2O&&o.2O.1N==2n?o.2O:F,2q:o.2q&&o.2q.1N==2n?o.2q:F,1E:/4l|4o/.4h(o.1E)?o.1E:F,4b:o.4b?I(o.4b)||0:F,1Y:o.1Y?o.1Y:F};6(\'.\'+o.2j,q).4w(8);q.92=O;q.3J={2j:o.2j,49:o.49?O:F,93:4c,1B:o.1B?2d(o.1B):F,44:o.30?o.30:F,V:o.V?o.V:F,2z:O,2A:o.2A?O:F,2b:o.2b?o.2b:P,1D:o.1D?o.1D:P,7O:o.7O?O:F,8:8}})}}};6.3j.1R({bM:6.T.2N,96:6.T.95,bO:6.T.3R});6.bK=6.T.5J;6.1I={48:P,4A:F,6E:P,7F:D(e){6.1I.4A=O;6.1I.41(e,q,O)},8l:D(e){k(6.1I.48!=q)G;6.1I.4A=F;6.1I.3q(e,q)},41:D(e,C,4A){k(6.1I.48!=P)G;k(!C){C=q}6.1I.48=C;1o=6.1R(6.Q.2x(C),6.Q.2e(C));5M=6(C);3M=5M.1y(\'3M\');6A=5M.1y(\'6A\');k(3M){6.1I.6E=3M;5M.1y(\'3M\',\'\');6(\'#9v\').6I(3M);k(6A)6(\'#7G\').6I(6A.3V(\'bJ://\',\'\'));N 6(\'#7G\').6I(\'\');W=6(\'#5z\');k(C.2P.2J){W.X(0).2J=C.2P.2J}N{W.X(0).2J=\'\'}80=6.Q.2e(W.X(0));9B=4A&&C.2P.11==\'7P\'?\'4g\':C.2P.11;3O(9B){1n\'U\':1J=1o.y-80.1m;1L=1o.x;1K;1n\'S\':1J=1o.y;1L=1o.x-80.1p;1K;1n\'53\':1J=1o.y;1L=1o.x+1o.1p;1K;1n\'7P\':6(\'1O\').1Q(\'2D\',6.1I.2D);Y=6.Q.2T(e);1J=Y.y+15;1L=Y.x+15;1K;9w:1J=1o.y+1o.1m;1L=1o.x;1K}W.K({U:1J+\'1c\',S:1L+\'1c\'});k(C.2P.5D==F){W.41()}N{W.94(C.2P.5D)}k(C.2P.59)C.2P.59.1H(C);5M.1Q(\'9h\',6.1I.3q).1Q(\'9i\',6.1I.8l)}},2D:D(e){k(6.1I.48==P){6(\'1O\').2i(\'2D\',6.1I.2D);G}Y=6.Q.2T(e);6(\'#5z\').K({U:Y.y+15+\'1c\',S:Y.x+15+\'1c\'})},3q:D(e,C){k(!C){C=q}k(6.1I.4A!=O&&6.1I.48==C){6.1I.48=P;6(\'#5z\').bZ(1);6(C).1y(\'3M\',6.1I.6E).2i(\'9h\',6.1I.3q).2i(\'9i\',6.1I.8l);k(C.2P.52)C.2P.52.1H(C);6.1I.6E=P}},2N:D(12){k(!6.1I.W){6(\'1O\').2B(\'<2o 1u="5z"><2o 1u="9v"></2o><2o 1u="7G"></2o></2o>\');6(\'#5z\').K({11:\'2G\',2Z:4c,1k:\'1t\'});6.1I.W=O}G q.1v(D(){k(6.1y(q,\'3M\')){q.2P={11:/U|4g|S|53|7P/.4h(12.11)?12.11:\'4g\',2J:12.2J?12.2J:F,5D:12.5D?12.5D:F,59:12.59&&12.59.1N==2n?12.59:F,52:12.52&&12.52.1N==2n?12.52:F};B C=6(q);C.1Q(\'bW\',6.1I.41);C.1Q(\'7F\',6.1I.7F)}})}};6.3j.bV=6.1I.2N;6.22={7Y:1,9p:D(29){B 29=29;G q.1v(D(){q.2M.4k.1v(D(62){6.22.3f(q,29[62])})})},X:D(){B 29=[];q.1v(D(7v){k(q.8k){29[7v]=[];B u=q;B 1T=6.Q.2e(q);q.2M.4k.1v(D(62){B x=q.5w;B y=q.5l;5W=I(x*3h/(1T.w-q.5u));5m=I(y*3h/(1T.h-q.5p));29[7v][62]=[5W||0,5m||0,x||0,y||0]})}});G 29},7H:D(u){u.8.9r=u.8.1q.w-u.8.19.1p;u.8.9l=u.8.1q.h-u.8.19.1m;k(u.6v.2M.7B){6m=u.6v.2M.4k.X(u.7C+1);k(6m){u.8.1q.w=(I(6(6m).K(\'S\'))||0)+u.8.19.1p;u.8.1q.h=(I(6(6m).K(\'U\'))||0)+u.8.19.1m}6l=u.6v.2M.4k.X(u.7C-1);k(6l){B 7s=I(6(6l).K(\'S\'))||0;B 7y=I(6(6l).K(\'S\'))||0;u.8.1q.x+=7s;u.8.1q.y+=7y;u.8.1q.w-=7s;u.8.1q.h-=7y}}u.8.9u=u.8.1q.w-u.8.19.1p;u.8.9t=u.8.1q.h-u.8.19.1m;k(u.8.1V){u.8.3E=((u.8.1q.w-u.8.19.1p)/u.8.1V)||1;u.8.3K=((u.8.1q.h-u.8.19.1m)/u.8.1V)||1;u.8.9x=u.8.9u/u.8.1V;u.8.9y=u.8.9t/u.8.1V}u.8.1q.1f=u.8.1q.x-u.8.1s.x;u.8.1q.1e=u.8.1q.y-u.8.1s.y;6.H.W.K(\'8a\',\'9w\')},2g:D(u,x,y){k(u.8.1V){9z=I(x/u.8.9x);5W=9z*3h/u.8.1V;9s=I(y/u.8.9y);5m=9s*3h/u.8.1V}N{5W=I(x*3h/u.8.9r);5m=I(y*3h/u.8.9l)}u.8.7E=[5W||0,5m||0,x||0,y||0];k(u.8.2g)u.8.2g.1H(u,u.8.7E)},9m:D(3m){5b=3m.9k||3m.9j||-1;3O(5b){1n 35:6.22.3f(q.2u,[6B,6B]);1K;1n 36:6.22.3f(q.2u,[-6B,-6B]);1K;1n 37:6.22.3f(q.2u,[-q.2u.8.3E||-1,0]);1K;1n 38:6.22.3f(q.2u,[0,-q.2u.8.3K||-1]);1K;1n 39:6.22.3f(q.2u,[q.2u.8.3E||1,0]);1K;1n 40:6.H.3f(q.2u,[0,q.2u.8.3K||1]);1K}},3f:D(u,11){k(!u.8){G}u.8.19=6.1R(6.Q.2x(u),6.Q.2e(u));u.8.1s={x:I(6.K(u,\'S\'))||0,y:I(6.K(u,\'U\'))||0};u.8.3l=6.K(u,\'11\');k(u.8.3l!=\'3u\'&&u.8.3l!=\'2G\'){u.1j.11=\'3u\'}6.H.7M(u);6.22.7H(u);1f=I(11[0])||0;1e=I(11[1])||0;1L=u.8.1s.x+1f;1J=u.8.1s.y+1e;k(u.8.1V){2c=6.H.7I.1H(u,[1L,1J,1f,1e]);k(2c.1N==6D){1f=2c.1f;1e=2c.1e}1L=u.8.1s.x+1f;1J=u.8.1s.y+1e}2c=6.H.8c.1H(u,[1L,1J,1f,1e]);k(2c&&2c.1N==6D){1f=2c.1f;1e=2c.1e}1L=u.8.1s.x+1f;1J=u.8.1s.y+1e;k(u.8.3v&&(u.8.2g||u.8.1Z)){6.22.2g(u,1L,1J)}1L=!u.8.1E||u.8.1E==\'4o\'?1L:u.8.1s.x||0;1J=!u.8.1E||u.8.1E==\'4l\'?1J:u.8.1s.y||0;u.1j.S=1L+\'1c\';u.1j.U=1J+\'1c\'},2N:D(o){G q.1v(D(){k(q.8k==O||!o.2j||!6.Q||!6.H||!6.Z){G}3C=6(o.2j,q);k(3C.4i()==0){G}B 2Y={1D:\'5S\',3v:O,2g:o.2g&&o.2g.1N==2n?o.2g:P,1Z:o.1Z&&o.1Z.1N==2n?o.1Z:P,2b:q,1B:o.1B||F};k(o.1V&&I(o.1V)){2Y.1V=I(o.1V)||1;2Y.1V=2Y.1V>0?2Y.1V:1}k(3C.4i()==1)3C.4w(2Y);N{6(3C.X(0)).4w(2Y);2Y.2b=P;3C.4w(2Y)}3C.6H(6.22.9m);3C.1y(\'7Y\',6.22.7Y++);q.8k=O;q.2M={};q.2M.9n=2Y.9n;q.2M.1V=2Y.1V;q.2M.4k=3C;q.2M.7B=o.7B?O:F;7K=q;7K.2M.4k.1v(D(9q){q.7C=9q;q.6v=7K});k(o.29&&o.29.1N==60){1C(i=o.29.1F-1;i>=0;i--){k(o.29[i].1N==60&&o.29[i].1F==2){C=q.2M.4k.X(i);k(C.5v){6.22.3f(C,o.29[i])}}}}})}};6.3j.1R({cC:6.22.2N,cB:6.22.9p,bI:6.22.X});6.1R({1S:{7L:D(p,n,1l,1h,1g){G((-R.9o(p*R.3k)/2)+0.5)*1h+1l},at:D(p,n,1l,1h,1g){G 1h*(n/=1g)*n*n+1l},aI:D(p,n,1l,1h,1g){G-1h*((n=n/1g-1)*n*n*n-1)+1l},aA:D(p,n,1l,1h,1g){k((n/=1g/2)<1)G 1h/2*n*n*n*n+1l;G-1h/2*((n-=2)*n*n*n-2)+1l},5o:D(p,n,1l,1h,1g){k((n/=1g)<(1/2.75)){G 1h*(7.6T*n*n)+1l}N k(n<(2/2.75)){G 1h*(7.6T*(n-=(1.5/2.75))*n+.75)+1l}N k(n<(2.5/2.75)){G 1h*(7.6T*(n-=(2.25/2.75))*n+.a8)+1l}N{G 1h*(7.6T*(n-=(2.9Y/2.75))*n+.ax)+1l}},7x:D(p,n,1l,1h,1g){k(6.1S.5o)G 1h-6.1S.5o(p,1g-n,0,1h,1g)+1l;G 1l+1h},bk:D(p,n,1l,1h,1g){k(6.1S.7x&&6.1S.5o)k(n<1g/2)G 6.1S.7x(p,n*2,0,1h,1g)*.5+1l;G 6.1S.5o(p,n*2-1g,0,1h,1g)*.5+1h*.5+1l;G 1l+1h},bn:D(p,n,1l,1h,1g){B a,s;k(n==0)G 1l;k((n/=1g)==1)G 1l+1h;a=1h*0.3;p=1g*.3;k(a<R.3D(1h)){a=1h;s=p/4}N{s=p/(2*R.3k)*R.8d(1h/a)}G-(a*R.4T(2,10*(n-=1))*R.6j((n*1g-s)*(2*R.3k)/p))+1l},bi:D(p,n,1l,1h,1g){B a,s;k(n==0)G 1l;k((n/=1g/2)==2)G 1l+1h;a=1h*0.3;p=1g*.3;k(a<R.3D(1h)){a=1h;s=p/4}N{s=p/(2*R.3k)*R.8d(1h/a)}G a*R.4T(2,-10*n)*R.6j((n*1g-s)*(2*R.3k)/p)+1h+1l},bh:D(p,n,1l,1h,1g){B a,s;k(n==0)G 1l;k((n/=1g/2)==2)G 1l+1h;a=1h*0.3;p=1g*.3;k(a<R.3D(1h)){a=1h;s=p/4}N{s=p/(2*R.3k)*R.8d(1h/a)}k(n<1){G-.5*(a*R.4T(2,10*(n-=1))*R.6j((n*1g-s)*(2*R.3k)/p))+1l}G a*R.4T(2,-10*(n-=1))*R.6j((n*1g-s)*(2*R.3k)/p)*.5+1h+1l}}});6.b0=P;6.3j.b8=D(o){G q.1v(D(){k(!o||!o.7k){G}B C=q;6(o.7k).1v(D(){3W 6.V.9O(C,q,o)})})};6.V.9O=D(e,5Q,o){B z=q;z.C=6(e);z.5Q=5Q;z.2C=1i.9G(\'2o\');6(z.2C).K({11:\'2G\'}).3g(o.2J);k(!o.1g){o.1g=aM}z.1g=o.1g;z.33=o.33;z.6b=0;z.65=0;k(6.bc){z.6b=(I(6.2m(z.2C,\'5X\'))||0)+(I(6.2m(z.2C,\'7W\'))||0)+(I(6.2m(z.2C,\'7U\'))||0)+(I(6.2m(z.2C,\'7Z\'))||0);z.65=(I(6.2m(z.2C,\'5E\'))||0)+(I(6.2m(z.2C,\'86\'))||0)+(I(6.2m(z.2C,\'84\'))||0)+(I(6.2m(z.2C,\'83\'))||0)}z.2w=6.1R(6.Q.2x(z.C.X(0)),6.Q.2e(z.C.X(0)));z.4n=6.1R(6.Q.2x(z.5Q),6.Q.2e(z.5Q));z.2w.1p-=z.6b;z.2w.1m-=z.65;z.4n.1p-=z.6b;z.4n.1m-=z.65;z.5P=o.33;6(\'1O\').2B(z.2C);6(z.2C).K(\'1d\',z.2w.1p+\'1c\').K(\'1a\',z.2w.1m+\'1c\').K(\'U\',z.2w.y+\'1c\').K(\'S\',z.2w.x+\'1c\').7a({U:z.4n.y,S:z.4n.x,1d:z.4n.1p,1a:z.4n.1m},z.1g,D(){6(z.2C).bl();k(z.33&&z.33.1N==2n){z.33.1H(z.C.X(0),[z.7k])}})};6.14={3U:P,2Q:P,1r:P,23:10,2w:D(C,2X,23,9M){6.14.2Q=C;6.14.1r=2X;6.14.23=I(23)||10;6.14.3U=3c.7n(6.14.9S,I(9M)||40)},9S:D(){1C(i=0;i<6.14.1r.1F;i++){k(!6.14.1r[i].21){6.14.1r[i].21=6.1R(6.Q.78(6.14.1r[i]),6.Q.4Q(6.14.1r[i]),6.Q.5r(6.14.1r[i]))}N{6.14.1r[i].21.t=6.14.1r[i].1X;6.14.1r[i].21.l=6.14.1r[i].24}k(6.14.2Q.8&&6.14.2Q.8.5s==O){3L={x:6.14.2Q.8.1L,y:6.14.2Q.8.1J,1p:6.14.2Q.8.19.1p,1m:6.14.2Q.8.19.1m}}N{3L=6.1R(6.Q.78(6.14.2Q),6.Q.4Q(6.14.2Q))}k(6.14.1r[i].21.t>0&&6.14.1r[i].21.y+6.14.1r[i].21.t>3L.y){6.14.1r[i].1X-=6.14.23}N k(6.14.1r[i].21.t<=6.14.1r[i].21.h&&6.14.1r[i].21.t+6.14.1r[i].21.1m<3L.y+3L.1m){6.14.1r[i].1X+=6.14.23}k(6.14.1r[i].21.l>0&&6.14.1r[i].21.x+6.14.1r[i].21.l>3L.x){6.14.1r[i].24-=6.14.23}N k(6.14.1r[i].21.l<=6.14.1r[i].21.as&&6.14.1r[i].21.l+6.14.1r[i].21.1p<3L.x+3L.1p){6.14.1r[i].24+=6.14.23}}},5h:D(){3c.7i(6.14.3U);6.14.2Q=P;6.14.1r=P;1C(i 27 6.14.1r){6.14.1r[i].21=P}}};',62,808,'||||||jQuery||dragCfg||||||||||||if||||||this||||elm||||||dragged|var|el|function|iResize|false|return|iDrag|parseInt|resizeOptions|css|dropCfg|iEL|else|true|null|iUtil|Math|left|iSort|top|fx|helper|get|pointer|iDrop||position|options||iAutoscroller||||resizeElement|oC|height|newSizes|px|width|dy|dx|duration|delta|document|style|display|firstNum|hb|case|pos|wb|cont|elsToScroll|oR|none|id|each|es|255|attr|elem|props|opacity|for|containment|axis|length|newPosition|apply|iTooltip|ny|break|nx|selectHelper|constructor|body|tp|bind|extend|easing|sizes|oldStyle|fractions|result|scrollTop|cursorAt|onChange||parentData|iSlider|step|scrollLeft||scr|in|selectdrug|values|0px|handle|newCoords|parseFloat|getSize|margins|onSlide|wrs|unbind|accept|zones|min|curCSS|Function|div|dhs|onStop|resizeDirection|handlers|highlighted|dragElem|diff|start|getPosition|vp|so|ghosting|append|transferEl|mousemove|ratio|onStart|absolute|currentPointer|nWidth|className|browser|hc|slideCfg|build|onDrag|tooltipCFG|elToScroll|documentElement|typeof|getPointer|dragHandle|block|shs|els|params|zIndex|helperclass|color|mousedown|complete|currentStyle||||||nHeight|dhe|window|parentNode|nodeEl|dragmoveBy|addClass|100|clientScroll|fn|PI|oP|event|sw|clonedEl|elS|hide|newStyles|marginTop|onDragModifier|relative|si|zoney|max|removeClass|visibility|zonex|collected|toDrag|abs|gx|marginBottom|marginLeft|overzone|marginRight|sortCfg|gy|elementData|title|grid|switch|styles|cur|destroy|nmp|prop|timer|replace|new|old|animationHandler|mouseup||show||hidden|hpc|tolerance|orig||current|revert|parseColor|snapDistance|3000|getWidth|getHeight|newDimensions|bottom|test|size|wr|sliders|vertically|128|end|horizontally|oldDisplay|onHover|newTop|hash|newLeft|139|dh|Draggable|oD|zoneh|cssRules|focused|np|oldVisibility|ih|selectCurrent|iw|selectKeyHelper|nw|startDrag|opera|rule|sc|minLeft|restoreStyle|changed|zonew|getSizeLite|rgb|minTop|pow|toInteger|inFrontOf|onOut|fA|user|F0||speed|onHide|right|frameClass||0x|msie|de|onShow|maxHeight|pressedKey|newPos|minHeight|maxBottom|contBorders|count|stop|maxRight|onselect|onselectstop|offsetTop|yproc|clientHeight|bounceout|offsetHeight|pr|getScroll|init|ser|offsetWidth|tagName|offsetLeft|clientWidth|move|tooltipHelper|fnc|ts|nRy|delay|borderTopWidth|overflow|getBorder|selectBorders|sx|serialize|insideParent|cssSides|jEl|nRx|queue|callback|targetEl|namedColors|parent|border|parentBorders|sy|xproc|borderLeftWidth|sh|firstChild|Array|selectedone|key|selectKeyUp|handleEl|diffHeight|ne|selectKeyDown|select|selectcheck|dragEl|diffWidth|iIndex|toLowerCase|src|png|maxWidth|opt|minWidth|sin|startTime|prev|next|nodeName|while|self|onDrop|prot|ActiveXObject|diffX|onActivate|SliderContainer|isDroppable|styleSheets|hidehelper|192|href|2000|borderColor|Object|oldTitle|oldPosition|diffY|keydown|html|sideEnd|211|exec|isDraggable|activeclass|hoverclass|margin|side|os|checkhover|5625|padding|DraggableDestroy|dragstop|getValues|dEs|func|idsa|10000|innerHeight|unselectable|scrollHeight||draginit|scrollWidth|getPositionLite|traverseDOM|animate|oneIsSortable|autoSize|filter|moveDrag|innerWidth|stopDrag|dragmove|clearInterval|clnt|to|oldBorder|string|setInterval|applyOnHover|elPosition|String|stopAnim|prevLeft|measure|169|slider|is|bouncein|prevTop|oldFloat|cssSidesEnd|restricted|SliderIteration|object|lastSi|focus|tooltipURL|modifyContainer|snapToGrid|borderWidth|sliderEl|linear|getContainment|sortable|floats|mouse|sliderPos|intersect|initialPosition|empty|paddingLeft|Color|borderRightWidth|indexOf|tabindex|paddingRight|helperSize|parentPos|sliderSize|paddingBottom|paddingTop||borderBottomWidth|selectstop|Selectserialize|pValue|cursor|floatVal|fitToContainer|asin|fontWeight|getMargins|keyup|windowSize|parseStyle|pause|isSlider|hidefocused|colorCssProps|fxe|offsetParent|userSelect|KhtmlUserSelect|listStyle|dragHelper|Width|toggle|cssProps|notColor|240|styleFloat|wid|insertBefore|getClient|isFunction|img|fxCheckTag|auto|trim|split|images|emptyGIF|245|oldOverflow|144|230|224|165|distance|custom|140|107|getTime|Date|alpha|dragstart|1px|onout|onhover|Droppable|isSortable|zindex|fadeIn|addItem|SortableAddItem|sortHelper|nbsp|selectedclass|isSelectable|selectstopApply|selectstart|cloneNode|DroppableDestroy|after|check|mouseout|blur|keyCode|charCode|containerMaxy|dragmoveByKey|onslide|cos|set|nr|containerMaxx|yfrac|maxy|maxx|tooltipTitle|default|fracW|fracH|xfrac|selectcheckApply|filteredPosition|1000|onResize|se|match|createElement|getHeightMinMax|on|onDragStart|remeasure|onDragStop|interval|highlight|itransferTo|directions|shc|hlt|doScroll|random|checkdrop|fit|wrapper|clientX|625|darkkhaki|189|appendChild|darkgreen|aqua|pageX|darkcyan|brown|blue|9375|black|183|beige||220|darkblue|azure|cyan|darkgrey|darkorchid|215|green|gold|fuchsia|148|indigo|130|lightblue|173|wh|easein|khaki|darkviolet|122|984375|153|darkorange|easeboth|darkolivegreen|204|darkred|233|150|getPadding|darksalmon|easeout|darkmagenta|nextSibling|header|500|th|colgroup|col|script|frame|meta|centerEl|optgroup|option|frameset|fixPNG|tfoot|progid|transferHelper|prototype|DXImageTransform|AlphaImageLoader|tr|td|thead|caption|TransferTo|tbody|destroyWrapper|removeChild|boxModel|purgeEvents|cssFloat|fxWrapper|ol|elasticboth|elasticout|clientY|bounceboth|remove|Microsoft|elasticin|dl|ul|216||input|w_|float|buildWrapper|hr|textarea|table|form|button|iframe|pageY|lime|inset|outset|ridge|groove|SliderGetValues|http|SortSerialize|rules|Sortable|borderStyle|SortableDestroy|solid|dashed|stopAll|Left|Bottom|Right|ToolTip|mouseover|dotted|transparent|fadeOut|isNaN|selectorText|RegExp|ondrop|sqrt|recallDroppables|array|Resizable|number|khtml|ondragstart|mozUserSelect|find|moz|ResizableDestroy|fromHandler|before|childNodes|onchange|cssText|100000000|dequeue|MozUserSelect|off|toUpperCase|Selectable|Top|double||yellow|lightyellow|white|silver|193|182|238|lightgrey|SliderSetValues|Slider|red|navy|pink|olive|orange|203|maroon|onselectstart|magenta|purple|lightgreen|lightpink|borderLeftColor|backgroundColor|borderBottomColor|outlineWidth|lightcyan|textIndent|borderRightColor|outlineOffset|borderTopColor|letterSpacing|fontSize|outlineColor|lineHeight'.split('|'),0,{}))
 
 
 
 
 
 
 
 
wpsc-core/js/jquery.accessible-news-slider.js DELETED
@@ -1,67 +0,0 @@
1
- jQuery.fn.slideNews = function(settings) {
2
- alert("test");
3
- settings = jQuery.extend({
4
- headline: "Shopping Cart",
5
- newsWidth: 74,
6
- newsSpeed: "normal"
7
- }, settings);
8
- return this.each(function(i){
9
- //jQuery(".messaging",this).css("display","none");
10
- //jQuery("a:eq(0)",this).attr("href","#skip_to_news_" + i);
11
- //jQuery("a:eq(4)",this).attr("name","skip_to_news_" + i);
12
- itemLength = jQuery(".item",this).length;
13
- newsContainerWidth = itemLength * settings.newsWidth;
14
- jQuery(".container",this).css("width",newsContainerWidth + "px");
15
- //jQuery(".news_items",this).prepend("<p class='view_all'>" + settings.headline + " [ " + itemLength + " total ] &nbsp;-&nbsp; <a href='#'>View All</a></p>");
16
- /*jQuery("a:eq(3)",this).click(function() {
17
- thisSlider = jQuery(this).parent().parent().parent();
18
- jQuery(".next",thisSlider).css("display","none");
19
- jQuery(".prev",thisSlider).css("display","none");
20
- jQuery(".container",thisSlider).css("left","0px");
21
- jQuery(".container",thisSlider).css("width",settings.newsWidth * 2 + "px");
22
- //jQuery(".view_all",thisSlider).css("display","none");
23
- });*/
24
- jQuery(".next",this).css("display","block");
25
- animating = false;
26
- jQuery(".next",this).click(function() {
27
- thisParent = jQuery(this).parent();
28
- if (animating == false) {
29
- animating = true;
30
- animateLeft = parseInt(jQuery(".container",thisParent).css("left")) - (settings.newsWidth * 1);
31
- if (animateLeft + parseInt(jQuery(".container",thisParent).css("width")) > 0) {
32
- jQuery(".prev",thisParent).css("display","block");
33
- jQuery(".container",thisParent).animate({left: animateLeft}, settings.newsSpeed, function() {
34
- jQuery(this).css("left",animateLeft);
35
- if (parseInt(jQuery(".container",thisParent).css("left")) + parseInt(jQuery(".container",thisParent).css("width")) <= settings.newsWidth * 2) {
36
- jQuery(".next",thisParent).css("display","none");
37
- }
38
- animating = false;
39
- });
40
- } else {
41
- animating = false;
42
- }
43
- return false;
44
- }
45
- });
46
- jQuery(".prev",this).click(function() {
47
- thisParent = jQuery(this).parent();
48
- if (animating == false) {
49
- animating = true;
50
- animateLeft = parseInt(jQuery(".container",thisParent).css("left")) + (settings.newsWidth * 1);
51
- if ((animateLeft + parseInt(jQuery(".container",thisParent).css("width"))) <= parseInt(jQuery(".container",thisParent).css("width"))) {
52
- jQuery(".next",thisParent).css("display","block");
53
- jQuery(".container",thisParent).animate({left: animateLeft}, settings.newsSpeed, function() {
54
- jQuery(this).css("left",animateLeft);
55
- if (parseInt(jQuery(".container",thisParent).css("left")) == 0) {
56
- jQuery(".prev",thisParent).css("display","none");
57
- }
58
- animating = false;
59
- });
60
- } else {
61
- animating = false;
62
- }
63
- return false;
64
- }
65
- });
66
- });
67
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/jquery.infieldlabel.min.js DELETED
@@ -1,11 +0,0 @@
1
- //full version and license can be found here: http://plugins.jquery.com/files/jquery.inlineFieldLabel.js.txt
2
- (function($){$.fn.inlineFieldLabel=function(options){var opts=$.extend({},$.fn.inlineFieldLabel.defaults,options);this.each(function(){$this=$(this);var o=$.metadata?$.extend({},opts,$this.metadata({type:opts.metadataType,name:opts.metadataName})):opts;innerFunction($this,o.label);});return this;};$.fn.inlineFieldLabel.defaults={label:'some placeholder',metadataType:'class',metadataName:'metadata'};function innerFunction(jqElement,fieldLabel){var textInput=null;var clonedTextInput=null;var strBefore="";var strAfter="";var counter=0;textInput=jqElement;if(textInput.attr('type')=='password'){clonedTextInput=textInput.clone();strBefore=clonedTextInput.append(textInput.clone()).html();strAfter=strBefore.replace('type="password"','type="text"');;strAfter.replace('type="password"','type="text"');textInput.after(strAfter);clonedTextInput=textInput.next();clonedTextInput.addClass("intra-field-label").val(fieldLabel);textInput.hide();}else{textInput.addClass("intra-field-label").val(fieldLabel);}
3
- if(clonedTextInput!=null){clonedTextInput.focus(function(){textInput.show();textInput.trigger('focus');clonedTextInput.hide();});}
4
- textInput.focus(function()
5
- {if(this.value==fieldLabel)
6
- {textInput.removeClass("intra-field-label").val("");};});textInput.blur(function()
7
- {if(this.value=="")
8
- {if(clonedTextInput!=null){textInput.hide();clonedTextInput.show();}
9
- else{textInput.addClass("intra-field-label").val(fieldLabel);}};});textInput.parents('form:first').find('input[type="submit"]').click(function(){if(clonedTextInput!=null){textInput.show();clonedTextInput.remove();}
10
- if(textInput.val()==fieldLabel)
11
- {textInput.removeClass("intra-field-label").val("");};});}})(jQuery);
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/jquery.jeditable.pack.js DELETED
@@ -1 +0,0 @@
1
- eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.Q.b=5(E,16){4 1={E:E,A:\'29\',F:\'F\',i:\'Y\',g:\'X\',k:\'X\',z:\'12\',O:\'l\',1j:\'28\',1k:\'26...\',D:\'25 24 23\',s:{},n:{}};3(16){$.N(1,16)}4 13=$.b.f[1.i].13||5(){};4 a=$.b.f[1.i].a||5(){};4 L=$.b.f[1.i].L||$.b.f[\'C\'].L;4 x=$.b.f[1.i].x||$.b.f[\'C\'].x;4 u=$.b.f[1.i].u||$.b.f[\'C\'].u;4 h=$.b.f[1.i].h||$.b.f[\'C\'].h;4 U=1.U||5(){};3(!$.y($(7)[1.z])){$.Q[1.z]=5(Q){q Q?7.22(1.z,Q):7.21(1.z)}}$(7).j(\'20\',1.1Z);1.1s=\'X\'==1.g;1.1r=\'X\'==1.k;q 7.17(5(){4 2=7;4 1u=$(2).g();4 1t=$(2).k();3(!$.T($(7).9())){$(7).9(1.D)}$(7)[1.z](5(e){3(2.M){q}3(0==$(2).g()){1.g=1u;1.k=1t}c{3(1.g!=\'S\'){1.g=1.1s?$(2).g():1.g}3(1.k!=\'S\'){1.k=1.1r?$(2).k():1.k}}3($(7).9().1q().1p(/;/,\'\')==1.D.1q().1p(/;/,\'\')){$(7).9(\'\')}2.M=1l;2.w=$(2).9();$(2).9(\'\');4 8=$(\'<8/>\');3(1.14){3(\'1o\'==1.14){8.j(\'15\',$(2).j(\'15\'))}c{8.j(\'15\',1.14)}}3(1.H){3(\'1o\'==1.H){8.j(\'H\',$(2).j(\'H\'));8.1n(\'1m\',$(2).1n(\'1m\'))}c{8.j(\'H\',1.H)}}4 6=u.d(8,[1,2]);4 G;3(1.1i){4 t=1f(5(){6.1g=1l;x.d(8,[1.1k,1,2])},1Y);4 s={};s[1.F]=2.F;3($.y(1.s)){$.N(s,1.s.d(2,[2.w,1]))}c{$.N(s,1.s)}$.1X({i:1.1j,1W:1.1i,P:s,1V:v,1U:5(1h){1T.1e(t);G=1h;6.1g=v}})}c 3(1.P){G=1.P;3($.y(1.P)){G=1.P.d(2,[2.w,1])}}c{G=2.w}x.d(8,[G,1,2]);6.j(\'A\',1.A);L.d(8,[1,2]);$(2).p(8);13.d(8,[1,2]);$(\':6:1S:1R:1b\',8).1Q();3(1.o){6.o()}6.1P(5(e){3(e.1O==27){e.1d();h.d(8,[1,2])}});4 t;3(\'l\'==1.O){6.W(5(e){t=1f(5(){h.d(8,[1,2])},1N)})}c 3(\'a\'==1.O){6.W(5(e){8.a()})}c 3($.y(1.O)){6.W(5(e){1.O.d(2,[6.B(),1])})}c{6.W(5(e){})}8.a(5(e){3(t){1e(t)}e.1d();3(v!==a.d(8,[1,2])){3($.y(1.E)){4 V=1.E.d(2,[6.B(),1]);$(2).9(V);2.M=v;U.d(2,[2.1c,1]);3(!$.T($(2).9())){$(2).9(1.D)}}c{4 n={};n[1.A]=6.B();n[1.F]=2.F;3($.y(1.n)){$.N(n,1.n.d(2,[2.w,1]))}c{$.N(n,1.n)}3(\'1M\'==1.1L){n[\'1K\']=\'1J\'}$(2).9(1.1I);$.1H(1.E,n,5(V){$(2).9(V);2.M=v;U.d(2,[2.1c,1]);3(!$.T($(2).9())){$(2).9(1.D)}})}}q v})});7.h=5(){$(2).9(2.w);2.M=v;3(!$.T($(2).9())){$(2).9(1.D)}}})};$.b={f:{C:{u:5(1,m){4 6=$(\'<6 i="1G">\');$(7).p(6);q(6)},x:5(K,1,m){$(\':6:1b\',7).B(K)},h:5(1,m){m.h()},L:5(1,m){4 8=7;3(1.a){3(1.a.1a(/>$/)){4 a=$(1.a).12(5(){3(a.j("i")!="a"){8.a()}});}c{4 a=$(\'<19 i="a">\');a.9(1.a)}$(7).p(a)}3(1.l){3(1.l.1a(/>$/)){4 l=$(1.l);}c{4 l=$(\'<19 i="l">\');l.9(1.l)}$(7).p(l);$(l).12(5(z){3($.y($.b.f[1.i].h)){4 h=$.b.f[1.i].h}c{4 h=$.b.f[\'C\'].h}h.d(8,[1,m]);q v})}}},Y:{u:5(1,m){4 6=$(\'<6>\');3(1.g!=\'S\'){6.g(1.g)}3(1.k!=\'S\'){6.k(1.k)}6.j(\'1F\',\'1E\');$(7).p(6);q(6)}},r:{u:5(1,m){4 r=$(\'<r>\');3(1.11){r.j(\'11\',1.11)}c{r.k(1.k)}3(1.10){r.j(\'10\',1.10)}c{r.g(1.g)}$(7).p(r);q(r)}},o:{u:5(1,m){4 o=$(\'<o>\');$(7).p(o);q(o)},x:5(K,1,m){3(1D==K.1C){1B(\'4 I = \'+K);1A(4 J 1z I){3(!I.1y(J)){18}3(\'R\'==J){18}4 Z=$(\'<Z>\').B(J).p(I[J]);$(\'o\',7).p(Z)}}$(\'o\',7).1x().17(5(){3($(7).B()==I[\'R\']||$(7).Y()==m.w){$(7).j(\'R\',\'R\')}})}}},1w:5(A,6){$.b.f[A]=6}}})(1v);',62,134,'|settings|self|if|var|function|input|this|form|html|submit|editable|else|apply||types|width|reset|type|attr|height|cancel|original|submitdata|select|append|return|textarea|loaddata||element|false|revert|content|isFunction|event|name|val|defaults|placeholder|target|id|input_content|style|json|key|string|buttons|editing|extend|onblur|data|fn|selected|none|trim|callback|str|blur|auto|text|option|cols|rows|click|plugin|cssclass|class|options|each|continue|button|match|first|innerHTML|preventDefault|clearTimeout|setTimeout|disabled|result|loadurl|loadtype|loadtext|true|display|css|inherit|replace|toLowerCase|autoheight|autowidth|savedheight|savedwidth|jQuery|addInputType|children|hasOwnProperty|in|for|eval|constructor|String|off|autocomplete|hidden|post|indicator|put|_method|method|PUT|500|keyCode|keydown|focus|enabled|visible|window|success|async|url|ajax|100|tooltip|title|trigger|bind|edit|to|Click|Loading||GET|value'.split('|'),0,{}))
 
wpsc-core/js/swfupload.js DELETED
@@ -1,928 +0,0 @@
1
- /**
2
- * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
3
- *
4
- * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
5
- *
6
- * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz�n and Mammon Media and is released under the MIT License:
7
- * http://www.opensource.org/licenses/mit-license.php
8
- *
9
- * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
10
- * http://www.opensource.org/licenses/mit-license.php
11
- *
12
- */
13
-
14
-
15
- /* ******************* */
16
- /* Constructor & Init */
17
- /* ******************* */
18
- var SWFUpload;
19
-
20
- if (SWFUpload == undefined) {
21
- SWFUpload = function (settings) {
22
- this.initSWFUpload(settings);
23
- };
24
- }
25
-
26
- SWFUpload.prototype.initSWFUpload = function (settings) {
27
- try {
28
- this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
29
- this.settings = settings;
30
- this.eventQueue = [];
31
- this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
32
- this.movieElement = null;
33
-
34
- // Setup global control tracking
35
- SWFUpload.instances[this.movieName] = this;
36
-
37
- // Load the settings. Load the Flash movie.
38
- this.initSettings();
39
- this.loadFlash();
40
- this.displayDebugInfo();
41
- } catch (ex) {
42
- delete SWFUpload.instances[this.movieName];
43
- throw ex;
44
- }
45
- };
46
-
47
- /* *************** */
48
- /* Static Members */
49
- /* *************** */
50
- SWFUpload.instances = {};
51
- SWFUpload.movieCount = 0;
52
- SWFUpload.version = "2.2.0 Beta 2";
53
- SWFUpload.QUEUE_ERROR = {
54
- QUEUE_LIMIT_EXCEEDED : -100,
55
- FILE_EXCEEDS_SIZE_LIMIT : -110,
56
- ZERO_BYTE_FILE : -120,
57
- INVALID_FILETYPE : -130
58
- };
59
- SWFUpload.UPLOAD_ERROR = {
60
- HTTP_ERROR : -200,
61
- MISSING_UPLOAD_URL : -210,
62
- IO_ERROR : -220,
63
- SECURITY_ERROR : -230,
64
- UPLOAD_LIMIT_EXCEEDED : -240,
65
- UPLOAD_FAILED : -250,
66
- SPECIFIED_FILE_ID_NOT_FOUND : -260,
67
- FILE_VALIDATION_FAILED : -270,
68
- FILE_CANCELLED : -280,
69
- UPLOAD_STOPPED : -290
70
- };
71
- SWFUpload.FILE_STATUS = {
72
- QUEUED : -1,
73
- IN_PROGRESS : -2,
74
- ERROR : -3,
75
- COMPLETE : -4,
76
- CANCELLED : -5
77
- };
78
- SWFUpload.BUTTON_ACTION = {
79
- SELECT_FILE : -100,
80
- SELECT_FILES : -110,
81
- START_UPLOAD : -120
82
- };
83
- SWFUpload.CURSOR = {
84
- ARROW : -1,
85
- HAND : -2
86
- };
87
- SWFUpload.WINDOW_MODE = {
88
- WINDOW : "window",
89
- TRANSPARENT : "transparent",
90
- OPAQUE : "opaque"
91
- };
92
-
93
- /* ******************** */
94
- /* Instance Members */
95
- /* ******************** */
96
-
97
- // Private: initSettings ensures that all the
98
- // settings are set, getting a default value if one was not assigned.
99
- SWFUpload.prototype.initSettings = function () {
100
- this.ensureDefault = function (settingName, defaultValue) {
101
- this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
102
- };
103
-
104
- // Upload backend settings
105
- this.ensureDefault("upload_url", "");
106
- this.ensureDefault("file_post_name", "Filedata");
107
- this.ensureDefault("post_params", {});
108
- this.ensureDefault("use_query_string", false);
109
- this.ensureDefault("requeue_on_error", false);
110
- this.ensureDefault("http_success", []);
111
-
112
- // File Settings
113
- this.ensureDefault("file_types", "*.*");
114
- this.ensureDefault("file_types_description", "All Files");
115
- this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
116
- this.ensureDefault("file_upload_limit", 0);
117
- this.ensureDefault("file_queue_limit", 0);
118
-
119
- // Flash Settings
120
- this.ensureDefault("flash_url", "swfupload.swf");
121
- this.ensureDefault("prevent_swf_caching", true);
122
-
123
- // Button Settings
124
- this.ensureDefault("button_image_url", "");
125
- this.ensureDefault("button_width", 1);
126
- this.ensureDefault("button_height", 1);
127
- this.ensureDefault("button_text", "");
128
- this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
129
- this.ensureDefault("button_text_top_padding", 0);
130
- this.ensureDefault("button_text_left_padding", 0);
131
- this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
132
- this.ensureDefault("button_disabled", false);
133
- this.ensureDefault("button_placeholder_id", null);
134
- this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
135
- this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
136
-
137
- // Debug Settings
138
- this.ensureDefault("debug", false);
139
- this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API
140
-
141
- // Event Handlers
142
- this.settings.return_upload_start_handler = this.returnUploadStart;
143
- this.ensureDefault("swfupload_loaded_handler", null);
144
- this.ensureDefault("file_dialog_start_handler", null);
145
- this.ensureDefault("file_queued_handler", null);
146
- this.ensureDefault("file_queue_error_handler", null);
147
- this.ensureDefault("file_dialog_complete_handler", null);
148
-
149
- this.ensureDefault("upload_start_handler", null);
150
- this.ensureDefault("upload_progress_handler", null);
151
- this.ensureDefault("upload_error_handler", null);
152
- this.ensureDefault("upload_success_handler", null);
153
- this.ensureDefault("upload_complete_handler", null);
154
-
155
- this.ensureDefault("debug_handler", this.debugMessage);
156
-
157
- this.ensureDefault("custom_settings", {});
158
-
159
- // Other settings
160
- this.customSettings = this.settings.custom_settings;
161
-
162
- // Update the flash url if needed
163
- if (this.settings.prevent_swf_caching) {
164
- this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999);
165
- }
166
-
167
- delete this.ensureDefault;
168
- };
169
-
170
- SWFUpload.prototype.loadFlash = function () {
171
- if (this.settings.button_placeholder_id !== "") {
172
- this.replaceWithFlash();
173
- } else {
174
- this.appendFlash();
175
- }
176
- };
177
-
178
- // Private: appendFlash gets the HTML tag for the Flash
179
- // It then appends the flash to the body
180
- SWFUpload.prototype.appendFlash = function () {
181
- var targetElement, container;
182
-
183
- // Make sure an element with the ID we are going to use doesn't already exist
184
- if (document.getElementById(this.movieName) !== null) {
185
- throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
186
- }
187
-
188
- // Get the body tag where we will be adding the flash movie
189
- targetElement = document.getElementsByTagName("body")[0];
190
-
191
- if (targetElement == undefined) {
192
- throw "Could not find the 'body' element.";
193
- }
194
-
195
- // Append the container and load the flash
196
- container = document.createElement("div");
197
- container.style.width = "1px";
198
- container.style.height = "1px";
199
- container.style.overflow = "hidden";
200
-
201
- targetElement.appendChild(container);
202
- container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
203
- };
204
-
205
- // Private: replaceWithFlash replaces the button_placeholder element with the flash movie.
206
- SWFUpload.prototype.replaceWithFlash = function () {
207
- var targetElement, tempParent;
208
-
209
- // Make sure an element with the ID we are going to use doesn't already exist
210
- if (document.getElementById(this.movieName) !== null) {
211
- throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
212
- }
213
-
214
- // Get the element where we will be placing the flash movie
215
- targetElement = document.getElementById(this.settings.button_placeholder_id);
216
-
217
- if (targetElement == undefined) {
218
- throw "Could not find the placeholder element.";
219
- }
220
-
221
- // Append the container and load the flash
222
- tempParent = document.createElement("div");
223
- tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
224
- targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
225
-
226
- };
227
-
228
- // Private: getFlashHTML generates the object tag needed to embed the flash in to the document
229
- SWFUpload.prototype.getFlashHTML = function () {
230
- // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
231
- return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
232
- '<param name="wmode" value="', this.settings.button_window_mode , '" />',
233
- '<param name="movie" value="', this.settings.flash_url, '" />',
234
- '<param name="quality" value="high" />',
235
- '<param name="menu" value="false" />',
236
- '<param name="allowScriptAccess" value="always" />',
237
- '<param name="flashvars" value="' + this.getFlashVars() + '" />',
238
- '</object>'].join("");
239
- };
240
-
241
- // Private: getFlashVars builds the parameter string that will be passed
242
- // to flash in the flashvars param.
243
- SWFUpload.prototype.getFlashVars = function () {
244
- // Build a string from the post param object
245
- var paramString = this.buildParamString();
246
- var httpSuccessString = this.settings.http_success.join(",");
247
-
248
- // Build the parameter string
249
- return ["movieName=", encodeURIComponent(this.movieName),
250
- "&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
251
- "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
252
- "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
253
- "&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
254
- "&amp;params=", encodeURIComponent(paramString),
255
- "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
256
- "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
257
- "&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
258
- "&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
259
- "&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
260
- "&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
261
- "&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
262
- "&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
263
- "&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
264
- "&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
265
- "&amp;buttonText=", encodeURIComponent(this.settings.button_text),
266
- "&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
267
- "&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
268
- "&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
269
- "&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
270
- "&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
271
- "&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
272
- ].join("");
273
- };
274
-
275
- // Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
276
- // The element is cached after the first lookup
277
- SWFUpload.prototype.getMovieElement = function () {
278
- if (this.movieElement == undefined) {
279
- this.movieElement = document.getElementById(this.movieName);
280
- }
281
-
282
- if (this.movieElement === null) {
283
- throw "Could not find Flash element";
284
- }
285
-
286
- return this.movieElement;
287
- };
288
-
289
- // Private: buildParamString takes the name/value pairs in the post_params setting object
290
- // and joins them up in to a string formatted "name=value&amp;name=value"
291
- SWFUpload.prototype.buildParamString = function () {
292
- var postParams = this.settings.post_params;
293
- var paramStringPairs = [];
294
-
295
- if (typeof(postParams) === "object") {
296
- for (var name in postParams) {
297
- if (postParams.hasOwnProperty(name)) {
298
- // alert(name);
299
- paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
300
- }
301
- }
302
- }
303
-
304
- return paramStringPairs.join("&amp;");
305
- };
306
-
307
- // Public: Used to remove a SWFUpload instance from the page. This method strives to remove
308
- // all references to the SWF, and other objects so memory is properly freed.
309
- // Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
310
- SWFUpload.prototype.destroy = function () {
311
- try {
312
- // Make sure Flash is done before we try to remove it
313
- this.stopUpload();
314
-
315
- // Remove the SWFUpload DOM nodes
316
- var movieElement = null;
317
- try {
318
- movieElement = this.getMovieElement();
319
- } catch (ex) {
320
- }
321
-
322
- if (movieElement != undefined && movieElement.parentNode != undefined && typeof movieElement.parentNode.removeChild === "function") {
323
- var container = movieElement.parentNode;
324
- if (container != undefined) {
325
- container.removeChild(movieElement);
326
- if (container.parentNode != undefined && typeof container.parentNode.removeChild === "function") {
327
- container.parentNode.removeChild(container);
328
- }
329
- }
330
- }
331
-
332
- // Destroy references
333
- SWFUpload.instances[this.movieName] = null;
334
- delete SWFUpload.instances[this.movieName];
335
-
336
- delete this.movieElement;
337
- delete this.settings;
338
- delete this.customSettings;
339
- delete this.eventQueue;
340
- delete this.movieName;
341
-
342
- delete window[this.movieName];
343
-
344
- return true;
345
- } catch (ex1) {
346
- return false;
347
- }
348
- };
349
-
350
- // Public: displayDebugInfo prints out settings and configuration
351
- // information about this SWFUpload instance.
352
- // This function (and any references to it) can be deleted when placing
353
- // SWFUpload in production.
354
- SWFUpload.prototype.displayDebugInfo = function () {
355
- this.debug(
356
- [
357
- "---SWFUpload Instance Info---\n",
358
- "Version: ", SWFUpload.version, "\n",
359
- "Movie Name: ", this.movieName, "\n",
360
- "Settings:\n",
361
- "\t", "upload_url: ", this.settings.upload_url, "\n",
362
- "\t", "flash_url: ", this.settings.flash_url, "\n",
363
- "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
364
- "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
365
- "\t", "http_success: ", this.settings.http_success.join(", "), "\n",
366
- "\t", "file_post_name: ", this.settings.file_post_name, "\n",
367
- "\t", "post_params: ", this.settings.post_params.toString(), "\n",
368
- "\t", "file_types: ", this.settings.file_types, "\n",
369
- "\t", "file_types_description: ", this.settings.file_types_description, "\n",
370
- "\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
371
- "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
372
- "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
373
- "\t", "debug: ", this.settings.debug.toString(), "\n",
374
-
375
- "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
376
-
377
- "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
378
- "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
379
- "\t", "button_width: ", this.settings.button_width.toString(), "\n",
380
- "\t", "button_height: ", this.settings.button_height.toString(), "\n",
381
- "\t", "button_text: ", this.settings.button_text.toString(), "\n",
382
- "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
383
- "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
384
- "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
385
- "\t", "button_action: ", this.settings.button_action.toString(), "\n",
386
- "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",
387
-
388
- "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
389
- "Event Handlers:\n",
390
- "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
391
- "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
392
- "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
393
- "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
394
- "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
395
- "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
396
- "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
397
- "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
398
- "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
399
- "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
400
- ].join("")
401
- );
402
- };
403
-
404
- /* Note: addSetting and getSetting are no longer used by SWFUpload but are included
405
- the maintain v2 API compatibility
406
- */
407
- // Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
408
- SWFUpload.prototype.addSetting = function (name, value, default_value) {
409
- if (value == undefined) {
410
- return (this.settings[name] = default_value);
411
- } else {
412
- return (this.settings[name] = value);
413
- }
414
- };
415
-
416
- // Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
417
- SWFUpload.prototype.getSetting = function (name) {
418
- if (this.settings[name] != undefined) {
419
- return this.settings[name];
420
- }
421
-
422
- return "";
423
- };
424
-
425
-
426
-
427
- // Private: callFlash handles function calls made to the Flash element.
428
- // Calls are made with a setTimeout for some functions to work around
429
- // bugs in the ExternalInterface library.
430
- SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
431
- argumentArray = argumentArray || [];
432
-
433
- var movieElement = this.getMovieElement();
434
- var returnValue;
435
-
436
- if (typeof movieElement[functionName] === "function") {
437
- // We have to go through all this if/else stuff because the Flash functions don't have apply() and only accept the exact number of arguments.
438
- if (argumentArray.length === 0) {
439
- returnValue = movieElement[functionName]();
440
- } else if (argumentArray.length === 1) {
441
- returnValue = movieElement[functionName](argumentArray[0]);
442
- } else if (argumentArray.length === 2) {
443
- returnValue = movieElement[functionName](argumentArray[0], argumentArray[1]);
444
- } else if (argumentArray.length === 3) {
445
- returnValue = movieElement[functionName](argumentArray[0], argumentArray[1], argumentArray[2]);
446
- } else {
447
- throw "Too many arguments";
448
- }
449
-
450
- // Unescape file post param values
451
- if (returnValue != undefined && typeof returnValue.post === "object") {
452
- returnValue = this.unescapeFilePostParams(returnValue);
453
- }
454
-
455
- return returnValue;
456
- } else {
457
- throw "Invalid function name: " + functionName;
458
- }
459
- };
460
-
461
-
462
- /* *****************************
463
- -- Flash control methods --
464
- Your UI should use these
465
- to operate SWFUpload
466
- ***************************** */
467
-
468
- // Public: selectFile causes a File Selection Dialog window to appear. This
469
- // dialog only allows 1 file to be selected. WARNING: this function does not work in Flash Player 10
470
- SWFUpload.prototype.selectFile = function () {
471
- this.callFlash("SelectFile");
472
- };
473
-
474
- // Public: selectFiles causes a File Selection Dialog window to appear/ This
475
- // dialog allows the user to select any number of files
476
- // Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
477
- // If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around
478
- // for this bug. WARNING: this function does not work in Flash Player 10
479
- SWFUpload.prototype.selectFiles = function () {
480
- this.callFlash("SelectFiles");
481
- };
482
-
483
-
484
- // Public: startUpload starts uploading the first file in the queue unless
485
- // the optional parameter 'fileID' specifies the ID
486
- SWFUpload.prototype.startUpload = function (fileID) {
487
- this.callFlash("StartUpload", [fileID]);
488
- };
489
-
490
- // Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index.
491
- // If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
492
- // If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
493
- SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
494
- if (triggerErrorEvent !== false) {
495
- triggerErrorEvent = true;
496
- }
497
- this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
498
- };
499
-
500
- // Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
501
- // If nothing is currently uploading then nothing happens.
502
- SWFUpload.prototype.stopUpload = function () {
503
- this.callFlash("StopUpload");
504
- };
505
-
506
- /* ************************
507
- * Settings methods
508
- * These methods change the SWFUpload settings.
509
- * SWFUpload settings should not be changed directly on the settings object
510
- * since many of the settings need to be passed to Flash in order to take
511
- * effect.
512
- * *********************** */
513
-
514
- // Public: getStats gets the file statistics object.
515
- SWFUpload.prototype.getStats = function () {
516
- return this.callFlash("GetStats");
517
- };
518
-
519
- // Public: setStats changes the SWFUpload statistics. You shouldn't need to
520
- // change the statistics but you can. Changing the statistics does not
521
- // affect SWFUpload accept for the successful_uploads count which is used
522
- // by the upload_limit setting to determine how many files the user may upload.
523
- SWFUpload.prototype.setStats = function (statsObject) {
524
- this.callFlash("SetStats", [statsObject]);
525
- };
526
-
527
- // Public: getFile retrieves a File object by ID or Index. If the file is
528
- // not found then 'null' is returned.
529
- SWFUpload.prototype.getFile = function (fileID) {
530
- if (typeof(fileID) === "number") {
531
- return this.callFlash("GetFileByIndex", [fileID]);
532
- } else {
533
- return this.callFlash("GetFile", [fileID]);
534
- }
535
- };
536
-
537
- // Public: addFileParam sets a name/value pair that will be posted with the
538
- // file specified by the Files ID. If the name already exists then the
539
- // exiting value will be overwritten.
540
- SWFUpload.prototype.addFileParam = function (fileID, name, value) {
541
- return this.callFlash("AddFileParam", [fileID, name, value]);
542
- };
543
-
544
- // Public: removeFileParam removes a previously set (by addFileParam) name/value
545
- // pair from the specified file.
546
- SWFUpload.prototype.removeFileParam = function (fileID, name) {
547
- this.callFlash("RemoveFileParam", [fileID, name]);
548
- };
549
-
550
- // Public: setUploadUrl changes the upload_url setting.
551
- SWFUpload.prototype.setUploadURL = function (url) {
552
- this.settings.upload_url = url.toString();
553
- this.callFlash("SetUploadURL", [url]);
554
- };
555
-
556
- // Public: setPostParams changes the post_params setting
557
- SWFUpload.prototype.setPostParams = function (paramsObject) {
558
- this.settings.post_params = paramsObject;
559
- this.callFlash("SetPostParams", [paramsObject]);
560
- };
561
-
562
- // Public: addPostParam adds post name/value pair. Each name can have only one value.
563
- SWFUpload.prototype.addPostParam = function (name, value) {
564
- this.settings.post_params[name] = value;
565
- this.callFlash("SetPostParams", [this.settings.post_params]);
566
- };
567
-
568
- // Public: removePostParam deletes post name/value pair.
569
- SWFUpload.prototype.removePostParam = function (name) {
570
- delete this.settings.post_params[name];
571
- this.callFlash("SetPostParams", [this.settings.post_params]);
572
- };
573
-
574
- // Public: setFileTypes changes the file_types setting and the file_types_description setting
575
- SWFUpload.prototype.setFileTypes = function (types, description) {
576
- this.settings.file_types = types;
577
- this.settings.file_types_description = description;
578
- this.callFlash("SetFileTypes", [types, description]);
579
- };
580
-
581
- // Public: setFileSizeLimit changes the file_size_limit setting
582
- SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
583
- this.settings.file_size_limit = fileSizeLimit;
584
- this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
585
- };
586
-
587
- // Public: setFileUploadLimit changes the file_upload_limit setting
588
- SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
589
- this.settings.file_upload_limit = fileUploadLimit;
590
- this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
591
- };
592
-
593
- // Public: setFileQueueLimit changes the file_queue_limit setting
594
- SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
595
- this.settings.file_queue_limit = fileQueueLimit;
596
- this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
597
- };
598
-
599
- // Public: setFilePostName changes the file_post_name setting
600
- SWFUpload.prototype.setFilePostName = function (filePostName) {
601
- this.settings.file_post_name = filePostName;
602
- this.callFlash("SetFilePostName", [filePostName]);
603
- };
604
-
605
- // Public: setUseQueryString changes the use_query_string setting
606
- SWFUpload.prototype.setUseQueryString = function (useQueryString) {
607
- this.settings.use_query_string = useQueryString;
608
- this.callFlash("SetUseQueryString", [useQueryString]);
609
- };
610
-
611
- // Public: setRequeueOnError changes the requeue_on_error setting
612
- SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
613
- this.settings.requeue_on_error = requeueOnError;
614
- this.callFlash("SetRequeueOnError", [requeueOnError]);
615
- };
616
-
617
- // Public: setHTTPSuccess changes the http_success setting
618
- SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
619
- if (typeof http_status_codes === "string") {
620
- http_status_codes = http_status_codes.replace(" ", "").split(",");
621
- }
622
-
623
- this.settings.http_success = http_status_codes;
624
- this.callFlash("SetHTTPSuccess", [http_status_codes]);
625
- };
626
-
627
-
628
- // Public: setDebugEnabled changes the debug_enabled setting
629
- SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
630
- this.settings.debug_enabled = debugEnabled;
631
- this.callFlash("SetDebugEnabled", [debugEnabled]);
632
- };
633
-
634
- // Public: setButtonImageURL loads a button image sprite
635
- SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
636
- if (buttonImageURL == undefined) {
637
- buttonImageURL = "";
638
- }
639
-
640
- this.settings.button_image_url = buttonImageURL;
641
- this.callFlash("SetButtonImageURL", [buttonImageURL]);
642
- };
643
-
644
- // Public: setButtonDimensions resizes the Flash Movie and button
645
- SWFUpload.prototype.setButtonDimensions = function (width, height) {
646
- this.settings.button_width = width;
647
- this.settings.button_height = height;
648
-
649
- var movie = this.getMovieElement();
650
- if (movie != undefined) {
651
- movie.style.width = width + "px";
652
- movie.style.height = height + "px";
653
- }
654
-
655
- this.callFlash("SetButtonDimensions", [width, height]);
656
- };
657
- // Public: setButtonText Changes the text overlaid on the button
658
- SWFUpload.prototype.setButtonText = function (html) {
659
- this.settings.button_text = html;
660
- this.callFlash("SetButtonText", [html]);
661
- };
662
- // Public: setButtonTextPadding changes the top and left padding of the text overlay
663
- SWFUpload.prototype.setButtonTextPadding = function (left, top) {
664
- this.settings.button_text_top_padding = top;
665
- this.settings.button_text_left_padding = left;
666
- this.callFlash("SetButtonTextPadding", [left, top]);
667
- };
668
-
669
- // Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
670
- SWFUpload.prototype.setButtonTextStyle = function (css) {
671
- this.settings.button_text_style = css;
672
- this.callFlash("SetButtonTextStyle", [css]);
673
- };
674
- // Public: setButtonDisabled disables/enables the button
675
- SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
676
- this.settings.button_disabled = isDisabled;
677
- this.callFlash("SetButtonDisabled", [isDisabled]);
678
- };
679
- // Public: setButtonAction sets the action that occurs when the button is clicked
680
- SWFUpload.prototype.setButtonAction = function (buttonAction) {
681
- this.settings.button_action = buttonAction;
682
- this.callFlash("SetButtonAction", [buttonAction]);
683
- };
684
-
685
- // Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
686
- SWFUpload.prototype.setButtonCursor = function (cursor) {
687
- this.settings.button_cursor = cursor;
688
- this.callFlash("SetButtonCursor", [cursor]);
689
- };
690
-
691
- /* *******************************
692
- Flash Event Interfaces
693
- These functions are used by Flash to trigger the various
694
- events.
695
-
696
- All these functions a Private.
697
-
698
- Because the ExternalInterface library is buggy the event calls
699
- are added to a queue and the queue then executed by a setTimeout.
700
- This ensures that events are executed in a determinate order and that
701
- the ExternalInterface bugs are avoided.
702
- ******************************* */
703
-
704
- SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
705
- // Warning: Don't call this.debug inside here or you'll create an infinite loop
706
-
707
- if (argumentArray == undefined) {
708
- argumentArray = [];
709
- } else if (!(argumentArray instanceof Array)) {
710
- argumentArray = [argumentArray];
711
- }
712
-
713
- var self = this;
714
- if (typeof this.settings[handlerName] === "function") {
715
- // Queue the event
716
- this.eventQueue.push(function () {
717
- this.settings[handlerName].apply(this, argumentArray);
718
- });
719
-
720
- // Execute the next queued event
721
- setTimeout(function () {
722
- self.executeNextEvent();
723
- }, 0);
724
-
725
- } else if (this.settings[handlerName] !== null) {
726
- throw "Event handler " + handlerName + " is unknown or is not a function";
727
- }
728
- };
729
-
730
- // Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout
731
- // we must queue them in order to garentee that they are executed in order.
732
- SWFUpload.prototype.executeNextEvent = function () {
733
- // Warning: Don't call this.debug inside here or you'll create an infinite loop
734
-
735
- var f = this.eventQueue ? this.eventQueue.shift() : null;
736
- if (typeof(f) === "function") {
737
- f.apply(this);
738
- }
739
- };
740
-
741
- // Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
742
- // properties that contain characters that are not valid for JavaScript identifiers. To work around this
743
- // the Flash Component escapes the parameter names and we must unescape again before passing them along.
744
- SWFUpload.prototype.unescapeFilePostParams = function (file) {
745
- var reg = /[$]([0-9a-f]{4})/i;
746
- var unescapedPost = {};
747
- var uk;
748
-
749
- if (file != undefined) {
750
- for (var k in file.post) {
751
- if (file.post.hasOwnProperty(k)) {
752
- uk = k;
753
- var match;
754
- while ((match = reg.exec(uk)) !== null) {
755
- uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
756
- }
757
- unescapedPost[uk] = file.post[k];
758
- }
759
- }
760
-
761
- file.post = unescapedPost;
762
- }
763
-
764
- return file;
765
- };
766
-
767
- SWFUpload.prototype.flashReady = function () {
768
- // Check that the movie element is loaded correctly with its ExternalInterface methods defined
769
- var movieElement = this.getMovieElement();
770
- if (typeof movieElement.StartUpload !== "function") {
771
- throw "ExternalInterface methods failed to initialize.";
772
- }
773
-
774
- // Fix IE Flash/Form bug
775
- if (window[this.movieName] == undefined) {
776
- window[this.movieName] = movieElement;
777
- }
778
-
779
- this.queueEvent("swfupload_loaded_handler");
780
- };
781
-
782
-
783
- /* This is a chance to do something before the browse window opens */
784
- SWFUpload.prototype.fileDialogStart = function () {
785
- this.queueEvent("file_dialog_start_handler");
786
- };
787
-
788
-
789
- /* Called when a file is successfully added to the queue. */
790
- SWFUpload.prototype.fileQueued = function (file) {
791
- file = this.unescapeFilePostParams(file);
792
- this.queueEvent("file_queued_handler", file);
793
- };
794
-
795
-
796
- /* Handle errors that occur when an attempt to queue a file fails. */
797
- SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
798
- file = this.unescapeFilePostParams(file);
799
- this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
800
- };
801
-
802
- /* Called after the file dialog has closed and the selected files have been queued.
803
- You could call startUpload here if you want the queued files to begin uploading immediately. */
804
- SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {
805
- this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
806
- };
807
-
808
- SWFUpload.prototype.uploadStart = function (file) {
809
- file = this.unescapeFilePostParams(file);
810
- this.queueEvent("return_upload_start_handler", file);
811
- };
812
-
813
- SWFUpload.prototype.returnUploadStart = function (file) {
814
- var returnValue;
815
- if (typeof this.settings.upload_start_handler === "function") {
816
- file = this.unescapeFilePostParams(file);
817
- returnValue = this.settings.upload_start_handler.call(this, file);
818
- } else if (this.settings.upload_start_handler != undefined) {
819
- throw "upload_start_handler must be a function";
820
- }
821
-
822
- // Convert undefined to true so if nothing is returned from the upload_start_handler it is
823
- // interpretted as 'true'.
824
- if (returnValue === undefined) {
825
- returnValue = true;
826
- }
827
-
828
- returnValue = !!returnValue;
829
-
830
- this.callFlash("ReturnUploadStart", [returnValue]);
831
- };
832
-
833
-
834
-
835
- SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
836
- file = this.unescapeFilePostParams(file);
837
- this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
838
- };
839
-
840
- SWFUpload.prototype.uploadError = function (file, errorCode, message) {
841
- file = this.unescapeFilePostParams(file);
842
- this.queueEvent("upload_error_handler", [file, errorCode, message]);
843
- };
844
-
845
- SWFUpload.prototype.uploadSuccess = function (file, serverData) {
846
- file = this.unescapeFilePostParams(file);
847
- this.queueEvent("upload_success_handler", [file, serverData]);
848
- };
849
-
850
- SWFUpload.prototype.uploadComplete = function (file) {
851
- file = this.unescapeFilePostParams(file);
852
- this.queueEvent("upload_complete_handler", file);
853
- };
854
-
855
- /* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
856
- internal debug console. You can override this event and have messages written where you want. */
857
- SWFUpload.prototype.debug = function (message) {
858
- this.queueEvent("debug_handler", message);
859
- };
860
-
861
-
862
- /* **********************************
863
- Debug Console
864
- The debug console is a self contained, in page location
865
- for debug message to be sent. The Debug Console adds
866
- itself to the body if necessary.
867
-
868
- The console is automatically scrolled as messages appear.
869
-
870
- If you are using your own debug handler or when you deploy to production and
871
- have debug disabled you can remove these functions to reduce the file size
872
- and complexity.
873
- ********************************** */
874
-
875
- // Private: debugMessage is the default debug_handler. If you want to print debug messages
876
- // call the debug() function. When overriding the function your own function should
877
- // check to see if the debug setting is true before outputting debug information.
878
- SWFUpload.prototype.debugMessage = function (message) {
879
- if (this.settings.debug) {
880
- var exceptionMessage, exceptionValues = [];
881
-
882
- // Check for an exception object and print it nicely
883
- if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
884
- for (var key in message) {
885
- if (message.hasOwnProperty(key)) {
886
- exceptionValues.push(key + ": " + message[key]);
887
- }
888
- }
889
- exceptionMessage = exceptionValues.join("\n") || "";
890
- exceptionValues = exceptionMessage.split("\n");
891
- exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
892
- SWFUpload.Console.writeLine(exceptionMessage);
893
- } else {
894
- SWFUpload.Console.writeLine(message);
895
- }
896
- }
897
- };
898
-
899
- SWFUpload.Console = {};
900
- SWFUpload.Console.writeLine = function (message) {
901
- var console, documentForm;
902
-
903
- try {
904
- console = document.getElementById("SWFUpload_Console");
905
-
906
- if (!console) {
907
- documentForm = document.createElement("form");
908
- document.getElementsByTagName("body")[0].appendChild(documentForm);
909
-
910
- console = document.createElement("textarea");
911
- console.id = "SWFUpload_Console";
912
- console.style.fontFamily = "monospace";
913
- console.setAttribute("wrap", "off");
914
- console.wrap = "off";
915
- console.style.overflow = "auto";
916
- console.style.width = "700px";
917
- console.style.height = "350px";
918
- console.style.margin = "5px";
919
- documentForm.appendChild(console);
920
- }
921
-
922
- console.value += message + "\n";
923
-
924
- console.scrollTop = console.scrollHeight - console.clientHeight;
925
- } catch (ex) {
926
- alert("Exception: " + ex.name + " Message: " + ex.message);
927
- }
928
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/swfupload.swf DELETED
Binary file
wpsc-core/js/swfupload/SWFObject License.txt DELETED
@@ -1,4 +0,0 @@
1
- /* SWFObject v2.0 rc4 <http://code.google.com/p/swfobject/>
2
- Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
3
- This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
4
- */
 
 
 
 
wpsc-core/js/swfupload/swfupload.cookies.js DELETED
@@ -1,53 +0,0 @@
1
- /*
2
- Cookie Plug-in
3
-
4
- This plug in automatically gets all the cookies for this site and adds them to the post_params.
5
- Cookies are loaded only on initialization. The refreshCookies function can be called to update the post_params.
6
- The cookies will override any other post params with the same name.
7
- */
8
-
9
- var SWFUpload;
10
- if (typeof(SWFUpload) === "function") {
11
- SWFUpload.prototype.initSettings = function (oldInitSettings) {
12
- return function () {
13
- if (typeof(oldInitSettings) === "function") {
14
- oldInitSettings.call(this);
15
- }
16
-
17
- this.refreshCookies(false); // The false parameter must be sent since SWFUpload has not initialzed at this point
18
- };
19
- }(SWFUpload.prototype.initSettings);
20
-
21
- // refreshes the post_params and updates SWFUpload. The sendToFlash parameters is optional and defaults to True
22
- SWFUpload.prototype.refreshCookies = function (sendToFlash) {
23
- if (sendToFlash === undefined) {
24
- sendToFlash = true;
25
- }
26
- sendToFlash = !!sendToFlash;
27
-
28
- // Get the post_params object
29
- var postParams = this.settings.post_params;
30
-
31
- // Get the cookies
32
- var i, cookieArray = document.cookie.split(';'), caLength = cookieArray.length, c, eqIndex, name, value;
33
- for (i = 0; i < caLength; i++) {
34
- c = cookieArray[i];
35
-
36
- // Left Trim spaces
37
- while (c.charAt(0) === " ") {
38
- c = c.substring(1, c.length);
39
- }
40
- eqIndex = c.indexOf("=");
41
- if (eqIndex > 0) {
42
- name = c.substring(0, eqIndex);
43
- value = c.substring(eqIndex + 1);
44
- postParams[name] = value;
45
- }
46
- }
47
-
48
- if (sendToFlash) {
49
- this.setPostParams(postParams);
50
- }
51
- };
52
-
53
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/swfupload/swfupload.gears.js DELETED
@@ -1,1035 +0,0 @@
1
- /*
2
- SWFUpload.Gears : http://www.swfupload.org, http://swfupload.googlecode.com
3
-
4
- mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
5
-
6
- SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz�n and Mammon Media and is released under the MIT License:
7
- http://www.opensource.org/licenses/mit-license.php
8
-
9
- SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
10
- http://www.opensource.org/licenses/mit-license.php
11
-
12
- --------------------------------
13
-
14
- Summary:
15
- It is an API compatible SWFUpload class that wraps Google Gears instead of Flash. This SWFUpload plugin is not actually a plugin.
16
-
17
- Features:
18
- * Use Google Gears to handle uploads
19
- * Separately Namespaced to allow fallback to SWFUpload
20
- * Adds an event for gears loading failed (swfupload_load_failed_handler)
21
-
22
- Usage:
23
- This library supplies DOM Ready loading by overridding the SWFUpload.Gears.onload function:
24
-
25
- <script type="text/javascript">
26
- var swfu;
27
- SWFUpload.onload = function () {
28
- swfu = new SWFUpload({
29
- swfupload_load_failed_handler: swfuploadLoadFailed
30
- });
31
- };
32
- </script>
33
-
34
-
35
- Notes:
36
- * Other SWFUpload Plugins are not compatible with SWFUpload.Gears.
37
- * Since the Flash button is simulated when using Gears there might be slight UI differences
38
- in different web browsers.
39
- * Since Google Gears does not apply the same security restrictions the selectFile() and selectFiles() methods are
40
- available and working if Gears loading is successful.
41
- * SWFUpload.Gears maintains API compatibility so event handlers and settings objects for SWFUpload.Gears are fully compatible with SWFUpload. This
42
- allows for easy fall back to SWFUpload if SWFUpload.Gears fails to load.
43
- */
44
-
45
- var SWFUpload;
46
- if (SWFUpload == undefined) {
47
- SWFUpload = function (settings) {
48
- this.initSWFUpload(settings);
49
- };
50
- }
51
-
52
- /* ******************* */
53
- /* Constructor & Init */
54
- /* ******************* */
55
-
56
- var SWFUpload.Gears = function (settings) {
57
- this.initSWFUpload(settings);
58
- };
59
-
60
-
61
- SWFUpload.Gears.prototype.initSWFUpload = function (settings) {
62
- try {
63
- this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
64
- this.settings = settings;
65
- this.eventQueue = [];
66
- this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
67
- this.movieElement = null;
68
-
69
- // Setup global control tracking
70
- SWFUpload.instances[this.movieName] = this;
71
-
72
- // Load the settings. Load the Flash movie.
73
- this.initSettings();
74
- this.loadGears();
75
- this.displayDebugInfo();
76
- } catch (ex) {
77
- delete SWFUpload.instances[this.movieName];
78
- throw ex;
79
- }
80
- };
81
-
82
- /* *************** */
83
- /* Static Members */
84
- /* *************** */
85
- SWFUpload.instances = {};
86
- SWFUpload.movieCount = 0;
87
- SWFUpload.Gears.version = "0.1 for SWFUpload v2.2.0";
88
- SWFUpload.QUEUE_ERROR = {
89
- QUEUE_LIMIT_EXCEEDED : -100,
90
- FILE_EXCEEDS_SIZE_LIMIT : -110,
91
- ZERO_BYTE_FILE : -120,
92
- INVALID_FILETYPE : -130
93
- };
94
- SWFUpload.UPLOAD_ERROR = {
95
- HTTP_ERROR : -200,
96
- MISSING_UPLOAD_URL : -210,
97
- IO_ERROR : -220,
98
- SECURITY_ERROR : -230,
99
- UPLOAD_LIMIT_EXCEEDED : -240,
100
- UPLOAD_FAILED : -250,
101
- SPECIFIED_FILE_ID_NOT_FOUND : -260,
102
- FILE_VALIDATION_FAILED : -270,
103
- FILE_CANCELLED : -280,
104
- UPLOAD_STOPPED : -290
105
- };
106
- SWFUpload.FILE_STATUS = {
107
- QUEUED : -1,
108
- IN_PROGRESS : -2,
109
- ERROR : -3,
110
- COMPLETE : -4,
111
- CANCELLED : -5
112
- };
113
- SWFUpload.BUTTON_ACTION = {
114
- SELECT_FILE : -100,
115
- SELECT_FILES : -110,
116
- START_UPLOAD : -120
117
- };
118
-
119
- /* ******************** */
120
- /* Instance Members */
121
- /* ******************** */
122
-
123
- // Private: initSettings ensures that all the
124
- // settings are set, getting a default value if one was not assigned.
125
- SWFUpload.Gears.prototype.initSettings = function () {
126
- this.ensureDefault = function (settingName, defaultValue) {
127
- this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
128
- };
129
-
130
- // Upload backend settings
131
- this.ensureDefault("upload_url", "");
132
- this.ensureDefault("file_post_name", "Filedata");
133
- this.ensureDefault("post_params", {});
134
- this.ensureDefault("use_query_string", false);
135
- this.ensureDefault("requeue_on_error", false);
136
-
137
- // File Settings
138
- this.ensureDefault("file_types", "*.*");
139
- this.ensureDefault("file_types_description", "All Files");
140
- this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
141
- this.ensureDefault("file_upload_limit", 0);
142
- this.ensureDefault("file_queue_limit", 0);
143
-
144
- // Flash Settings
145
- this.ensureDefault("flash_url", "");
146
- this.ensureDefault("prevent_swf_caching", true);
147
-
148
- // Button Settings
149
- this.ensureDefault("button_image_url", "");
150
- this.ensureDefault("button_width", 1);
151
- this.ensureDefault("button_height", 1);
152
- this.ensureDefault("button_text", "");
153
- this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
154
- this.ensureDefault("button_text_top_padding", 0);
155
- this.ensureDefault("button_text_left_padding", 0);
156
- this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
157
- this.ensureDefault("button_disabled", false);
158
- this.ensureDefault("button_placeholder_id", null);
159
-
160
- // Debug Settings
161
- this.ensureDefault("debug", false);
162
- this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API
163
-
164
- // Event Handlers
165
- this.settings.return_upload_start_handler = this.returnUploadStart;
166
- this.ensureDefault("swfupload_load_failed_handler", null);
167
- this.ensureDefault("swfupload_loaded_handler", null);
168
- this.ensureDefault("file_dialog_start_handler", null);
169
- this.ensureDefault("file_queued_handler", null);
170
- this.ensureDefault("file_queue_error_handler", null);
171
- this.ensureDefault("file_dialog_complete_handler", null);
172
-
173
- this.ensureDefault("upload_start_handler", null);
174
- this.ensureDefault("upload_progress_handler", null);
175
- this.ensureDefault("upload_error_handler", null);
176
- this.ensureDefault("upload_success_handler", null);
177
- this.ensureDefault("upload_complete_handler", null);
178
-
179
- this.ensureDefault("debug_handler", this.debugMessage);
180
-
181
- this.ensureDefault("custom_settings", {});
182
-
183
- // Other settings
184
- this.customSettings = this.settings.custom_settings;
185
-
186
- delete this.ensureDefault;
187
- };
188
-
189
- SWFUpload.Gears.prototype.loadGears = function () {
190
- // Check to see if gears is available, if not trigger the failed event
191
-
192
- // FIXME -- How do we handle a user permission rejection?
193
- if (!window.google || !google.gears) {
194
- this.queueEvent("swfupload_load_failed_handler");
195
- } else {
196
-
197
- if (this.settings.button_placeholder_id !== "") {
198
- this.replaceWithGears();
199
- } else {
200
- this.appendGears();
201
- }
202
- }
203
- };
204
-
205
- // Private: appendGears doesn't actually need to do anything except cause gears to set up
206
- SWFUpload.Gears.prototype.appendFlash = function () {
207
- this.getGears();
208
- };
209
-
210
- // Private: replaceWithFlash replaces the button_placeholder element with the flash movie.
211
- // For this release we are not going to replace any HTML elements. The element can just access SWFUpload.Gears like
212
- // we did with Flash Player 9
213
- SWFUpload.Gears.prototype.replaceWithFlash = function () {
214
- this.getGears();
215
-
216
- /*
217
- var targetElement, tempParent;
218
-
219
- // Make sure an element with the ID we are going to use doesn't already exist
220
- if (document.getElementById(this.movieName) !== null) {
221
- throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
222
- }
223
-
224
- // Get the element where we will be placing the flash movie
225
- targetElement = document.getElementById(this.settings.button_placeholder_id);
226
-
227
- if (targetElement == undefined) {
228
- throw "Could not find the placeholder element.";
229
- }
230
-
231
- // Append the container and load the flash
232
- var button = document.createElement("button");
233
- button.id = this.movieName;
234
- button.cssName = "swfupload";
235
- var buttonInnards = document.createElement("div");
236
- buttonInnards.innerHTML = this.settings.button_text;
237
- button.style.overflow = "hidden";
238
- buttonInnards.style.overflow = "hidden";
239
- button.style.marginTop = this.settings.button_text_top_padding + "px";
240
- button.style.marginLeft = this.settings.button_text_left_padding + "px";
241
- button.style.width = this.settings.button_width + "px";
242
- button.style.height = this.settings.button_height + "px";
243
-
244
- targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
245
- */
246
-
247
-
248
-
249
- };
250
-
251
- SWFUpload.Gears.prototype.getGears = function () {
252
-
253
- };
254
-
255
-
256
- // Public: getMovieElement retrieves the "gearsMovie" that emulates the Flash Movie
257
- SWFUpload.Gears.prototype.getMovieElement = function () {
258
- return this.movieElement;
259
- };
260
-
261
- // Private: buildParamString takes the name/value pairs in the post_params setting object
262
- // and joins them up in to a string formatted "name=value&amp;name=value"
263
- SWFUpload.Gears.prototype.buildParamString = function () {
264
- var postParams = this.settings.post_params;
265
- var paramStringPairs = [];
266
-
267
- if (typeof(postParams) === "object") {
268
- for (var name in postParams) {
269
- if (postParams.hasOwnProperty(name)) {
270
- paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
271
- }
272
- }
273
- }
274
-
275
- return paramStringPairs.join("&amp;");
276
- };
277
-
278
- // Public: Used to remove a SWFUpload instance from the page. This method strives to remove
279
- // all references to the SWF, and other objects so memory is properly freed.
280
- // Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
281
- SWFUpload.Gears.prototype.destroy = function () {
282
- try {
283
- // Make sure Flash is done before we try to remove it
284
- this.stopUpload();
285
-
286
- // Remove the SWFUpload DOM nodes
287
- var movieElement = null;
288
- try {
289
- movieElement = this.getMovieElement();
290
- } catch (ex) {
291
- }
292
-
293
- // Destroy references
294
- SWFUpload.instances[this.movieName] = null;
295
- delete SWFUpload.instances[this.movieName];
296
-
297
- delete this.movieElement;
298
- delete this.settings;
299
- delete this.customSettings;
300
- delete this.eventQueue;
301
- delete this.movieName;
302
-
303
- return true;
304
- } catch (ex1) {
305
- return false;
306
- }
307
- };
308
-
309
- // Public: displayDebugInfo prints out settings and configuration
310
- // information about this SWFUpload instance.
311
- // This function (and any references to it) can be deleted when placing
312
- // SWFUpload in production.
313
- SWFUpload.Gears.prototype.displayDebugInfo = function () {
314
- this.debug(
315
- [
316
- "---SWFUpload Instance Info---\n",
317
- "Version: ", SWFUpload.version, "\n",
318
- "Movie Name: ", this.movieName, "\n",
319
- "Settings:\n",
320
- "\t", "upload_url: ", this.settings.upload_url, "\n",
321
- "\t", "flash_url: ", this.settings.flash_url, "\n",
322
- "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
323
- "\t", "file_post_name: ", this.settings.file_post_name, "\n",
324
- "\t", "post_params: ", this.settings.post_params.toString(), "\n",
325
- "\t", "file_types: ", this.settings.file_types, "\n",
326
- "\t", "file_types_description: ", this.settings.file_types_description, "\n",
327
- "\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
328
- "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
329
- "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
330
- "\t", "debug: ", this.settings.debug.toString(), "\n",
331
-
332
- "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
333
-
334
- "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
335
- "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
336
- "\t", "button_width: ", this.settings.button_width.toString(), "\n",
337
- "\t", "button_height: ", this.settings.button_height.toString(), "\n",
338
- "\t", "button_text: ", this.settings.button_text.toString(), "\n",
339
- "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
340
- "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
341
- "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
342
- "\t", "button_action: ", this.settings.button_action.toString(), "\n",
343
- "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",
344
-
345
- "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
346
- "Event Handlers:\n",
347
- "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
348
- "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
349
- "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
350
- "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
351
- "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
352
- "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
353
- "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
354
- "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
355
- "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
356
- "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
357
- ].join("")
358
- );
359
- };
360
-
361
- /* Note: addSetting and getSetting are no longer used by SWFUpload but are included
362
- the maintain v2 API compatibility
363
- */
364
- // Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
365
- SWFUpload.Gears.prototype.addSetting = function (name, value, default_value) {
366
- if (value == undefined) {
367
- return (this.settings[name] = default_value);
368
- } else {
369
- return (this.settings[name] = value);
370
- }
371
- };
372
-
373
- // Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
374
- SWFUpload.Gears.prototype.getSetting = function (name) {
375
- if (this.settings[name] != undefined) {
376
- return this.settings[name];
377
- }
378
-
379
- return "";
380
- };
381
-
382
-
383
-
384
- // Private: callFlash handles function calls made to the Flash element.
385
- // Calls are made with a setTimeout for some functions to work around
386
- // bugs in the ExternalInterface library.
387
- SWFUpload.Gears.prototype.callFlash = function (functionName, argumentArray) {
388
- argumentArray = argumentArray || [];
389
-
390
- var movieElement = this.getMovieElement();
391
- var returnValue;
392
-
393
- if (typeof movieElement[functionName] === "function") {
394
- return movieElement[functionName].call(this, argumentArray);
395
- } else {
396
- throw "Invalid function name: " + functionName;
397
- }
398
- };
399
-
400
-
401
- /* *****************************
402
- -- Flash control methods --
403
- Your UI should use these
404
- to operate SWFUpload
405
- ***************************** */
406
-
407
- // Public: selectFile causes a File Selection Dialog window to appear. This
408
- // dialog only allows 1 file to be selected. WARNING: this function does not work in Flash Player 10
409
- SWFUpload.Gears.prototype.selectFile = function () {
410
- this.callFlash("SelectFile");
411
- };
412
-
413
- // Public: selectFiles causes a File Selection Dialog window to appear/ This
414
- // dialog allows the user to select any number of files
415
- // Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
416
- // If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around
417
- // for this bug. WARNING: this function does not work in Flash Player 10
418
- SWFUpload.Gears.prototype.selectFiles = function () {
419
- this.callFlash("SelectFiles");
420
- };
421
-
422
-
423
- // Public: startUpload starts uploading the first file in the queue unless
424
- // the optional parameter 'fileID' specifies the ID
425
- SWFUpload.Gears.prototype.startUpload = function (fileID) {
426
- this.callFlash("StartUpload", [fileID]);
427
- };
428
-
429
- /* Cancels a the file upload. You must specify a file_id */
430
- // Public: cancelUpload cancels any queued file. The fileID parameter
431
- // must be specified.
432
- SWFUpload.Gears.prototype.cancelUpload = function (fileID) {
433
- this.callFlash("CancelUpload", [fileID]);
434
- };
435
-
436
- // Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
437
- // If nothing is currently uploading then nothing happens.
438
- SWFUpload.Gears.prototype.stopUpload = function () {
439
- this.callFlash("StopUpload");
440
- };
441
-
442
- /* ************************
443
- * Settings methods
444
- * These methods change the SWFUpload settings.
445
- * SWFUpload settings should not be changed directly on the settings object
446
- * since many of the settings need to be passed to Flash in order to take
447
- * effect.
448
- * *********************** */
449
-
450
- // Public: getStats gets the file statistics object.
451
- SWFUpload.Gears.prototype.getStats = function () {
452
- return this.callFlash("GetStats");
453
- };
454
-
455
- // Public: setStats changes the SWFUpload statistics. You shouldn't need to
456
- // change the statistics but you can. Changing the statistics does not
457
- // affect SWFUpload accept for the successful_uploads count which is used
458
- // by the upload_limit setting to determine how many files the user may upload.
459
- SWFUpload.Gears.prototype.setStats = function (statsObject) {
460
- this.callFlash("SetStats", [statsObject]);
461
- };
462
-
463
- // Public: getFile retrieves a File object by ID or Index. If the file is
464
- // not found then 'null' is returned.
465
- SWFUpload.Gears.prototype.getFile = function (fileID) {
466
- if (typeof(fileID) === "number") {
467
- return this.callFlash("GetFileByIndex", [fileID]);
468
- } else {
469
- return this.callFlash("GetFile", [fileID]);
470
- }
471
- };
472
-
473
- // Public: addFileParam sets a name/value pair that will be posted with the
474
- // file specified by the Files ID. If the name already exists then the
475
- // exiting value will be overwritten.
476
- SWFUpload.Gears.prototype.addFileParam = function (fileID, name, value) {
477
- return this.callFlash("AddFileParam", [fileID, name, value]);
478
- };
479
-
480
- // Public: removeFileParam removes a previously set (by addFileParam) name/value
481
- // pair from the specified file.
482
- SWFUpload.Gears.prototype.removeFileParam = function (fileID, name) {
483
- this.callFlash("RemoveFileParam", [fileID, name]);
484
- };
485
-
486
- // Public: setUploadUrl changes the upload_url setting.
487
- SWFUpload.Gears.prototype.setUploadURL = function (url) {
488
- this.settings.upload_url = url.toString();
489
- this.callFlash("SetUploadURL", [url]);
490
- };
491
-
492
- // Public: setPostParams changes the post_params setting
493
- SWFUpload.Gears.prototype.setPostParams = function (paramsObject) {
494
- this.settings.post_params = paramsObject;
495
- this.callFlash("SetPostParams", [paramsObject]);
496
- };
497
-
498
- // Public: addPostParam adds post name/value pair. Each name can have only one value.
499
- SWFUpload.Gears.prototype.addPostParam = function (name, value) {
500
- this.settings.post_params[name] = value;
501
- this.callFlash("SetPostParams", [this.settings.post_params]);
502
- };
503
-
504
- // Public: removePostParam deletes post name/value pair.
505
- SWFUpload.Gears.prototype.removePostParam = function (name) {
506
- delete this.settings.post_params[name];
507
- this.callFlash("SetPostParams", [this.settings.post_params]);
508
- };
509
-
510
- // Public: setFileTypes changes the file_types setting and the file_types_description setting
511
- SWFUpload.Gears.prototype.setFileTypes = function (types, description) {
512
- this.settings.file_types = types;
513
- this.settings.file_types_description = description;
514
- this.callFlash("SetFileTypes", [types, description]);
515
- };
516
-
517
- // Public: setFileSizeLimit changes the file_size_limit setting
518
- SWFUpload.Gears.prototype.setFileSizeLimit = function (fileSizeLimit) {
519
- this.settings.file_size_limit = fileSizeLimit;
520
- this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
521
- };
522
-
523
- // Public: setFileUploadLimit changes the file_upload_limit setting
524
- SWFUpload.Gears.prototype.setFileUploadLimit = function (fileUploadLimit) {
525
- this.settings.file_upload_limit = fileUploadLimit;
526
- this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
527
- };
528
-
529
- // Public: setFileQueueLimit changes the file_queue_limit setting
530
- SWFUpload.Gears.prototype.setFileQueueLimit = function (fileQueueLimit) {
531
- this.settings.file_queue_limit = fileQueueLimit;
532
- this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
533
- };
534
-
535
- // Public: setFilePostName changes the file_post_name setting
536
- SWFUpload.Gears.prototype.setFilePostName = function (filePostName) {
537
- this.settings.file_post_name = filePostName;
538
- this.callFlash("SetFilePostName", [filePostName]);
539
- };
540
-
541
- // Public: setUseQueryString changes the use_query_string setting
542
- SWFUpload.Gears.prototype.setUseQueryString = function (useQueryString) {
543
- this.settings.use_query_string = useQueryString;
544
- this.callFlash("SetUseQueryString", [useQueryString]);
545
- };
546
-
547
- // Public: setRequeueOnError changes the requeue_on_error setting
548
- SWFUpload.Gears.prototype.setRequeueOnError = function (requeueOnError) {
549
- this.settings.requeue_on_error = requeueOnError;
550
- this.callFlash("SetRequeueOnError", [requeueOnError]);
551
- };
552
-
553
- // Public: setDebugEnabled changes the debug_enabled setting
554
- SWFUpload.Gears.prototype.setDebugEnabled = function (debugEnabled) {
555
- this.settings.debug_enabled = debugEnabled;
556
- this.callFlash("SetDebugEnabled", [debugEnabled]);
557
- };
558
-
559
- // Public: setButtonImageURL loads a button image sprite
560
- SWFUpload.Gears.prototype.setButtonImageURL = function (buttonImageURL) {
561
- if (buttonImageURL == undefined) {
562
- buttonImageURL = "";
563
- }
564
-
565
- this.settings.button_image_url = buttonImageURL;
566
- this.callFlash("SetButtonImageURL", [buttonImageURL]);
567
- };
568
-
569
- // Public: setButtonDimensions resizes the Flash Movie and button
570
- SWFUpload.Gears.prototype.setButtonDimensions = function (width, height) {
571
- this.settings.button_width = width;
572
- this.settings.button_height = height;
573
-
574
- var movie = this.getMovieElement();
575
- if (movie != undefined) {
576
- movie.style.width = width + "px";
577
- movie.style.height = height + "px";
578
- }
579
-
580
- this.callFlash("SetButtonDimensions", [width, height]);
581
- };
582
- // Public: setButtonText Changes the text overlaid on the button
583
- SWFUpload.Gears.prototype.setButtonText = function (html) {
584
- this.settings.button_text = html;
585
- this.callFlash("SetButtonText", [html]);
586
- };
587
- // Public: setButtonTextPadding changes the top and left padding of the text overlay
588
- SWFUpload.Gears.prototype.setButtonTextPadding = function (left, top) {
589
- this.settings.button_text_top_padding = top;
590
- this.settings.button_text_left_padding = left;
591
- this.callFlash("SetButtonTextPadding", [left, top]);
592
- };
593
-
594
- // Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
595
- SWFUpload.Gears.prototype.setButtonTextStyle = function (css) {
596
- this.settings.button_text_style = css;
597
- this.callFlash("SetButtonTextStyle", [css]);
598
- };
599
- // Public: setButtonDisabled disables/enables the button
600
- SWFUpload.Gears.prototype.setButtonDisabled = function (isDisabled) {
601
- this.settings.button_disabled = isDisabled;
602
- this.callFlash("SetButtonDisabled", [isDisabled]);
603
- };
604
- // Public: setButtonAction sets the action that occurs when the button is clicked
605
- SWFUpload.Gears.prototype.setButtonAction = function (buttonAction) {
606
- this.settings.button_action = buttonAction;
607
- this.callFlash("SetButtonAction", [buttonAction]);
608
- };
609
-
610
- /* *******************************
611
- Flash Event Interfaces
612
- These functions are used by Flash to trigger the various
613
- events.
614
-
615
- All these functions a Private.
616
-
617
- Because the ExternalInterface library is buggy the event calls
618
- are added to a queue and the queue then executed by a setTimeout.
619
- This ensures that events are executed in a determinate order and that
620
- the ExternalInterface bugs are avoided.
621
- ******************************* */
622
-
623
- SWFUpload.Gears.prototype.queueEvent = function (handlerName, argumentArray) {
624
- // Warning: Don't call this.debug inside here or you'll create an infinite loop
625
-
626
- if (argumentArray == undefined) {
627
- argumentArray = [];
628
- } else if (!(argumentArray instanceof Array)) {
629
- argumentArray = [argumentArray];
630
- }
631
-
632
- var self = this;
633
- if (typeof this.settings[handlerName] === "function") {
634
- // Queue the event
635
- this.eventQueue.push(function () {
636
- this.settings[handlerName].apply(this, argumentArray);
637
- });
638
-
639
- // Execute the next queued event
640
- setTimeout(function () {
641
- self.executeNextEvent();
642
- }, 0);
643
-
644
- } else if (this.settings[handlerName] !== null) {
645
- throw "Event handler " + handlerName + " is unknown or is not a function";
646
- }
647
- };
648
-
649
- // Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout
650
- // we must queue them in order to garentee that they are executed in order.
651
- SWFUpload.Gears.prototype.executeNextEvent = function () {
652
- // Warning: Don't call this.debug inside here or you'll create an infinite loop
653
-
654
- var f = this.eventQueue ? this.eventQueue.shift() : null;
655
- if (typeof(f) === "function") {
656
- f.apply(this);
657
- }
658
- };
659
-
660
- // Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
661
- // properties that contain characters that are not valid for JavaScript identifiers. To work around this
662
- // the Flash Component escapes the parameter names and we must unescape again before passing them along.
663
- SWFUpload.Gears.prototype.unescapeFilePostParams = function (file) {
664
- var reg = /[$]([0-9a-f]{4})/i;
665
- var unescapedPost = {};
666
- var uk;
667
-
668
- if (file != undefined) {
669
- for (var k in file.post) {
670
- if (file.post.hasOwnProperty(k)) {
671
- uk = k;
672
- var match;
673
- while ((match = reg.exec(uk)) !== null) {
674
- uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
675
- }
676
- unescapedPost[uk] = file.post[k];
677
- }
678
- }
679
-
680
- file.post = unescapedPost;
681
- }
682
-
683
- return file;
684
- };
685
-
686
- SWFUpload.Gears.prototype.flashReady = function () {
687
- // Check that the movie element is loaded correctly with its ExternalInterface methods defined
688
- var movieElement = this.getMovieElement();
689
- if (typeof movieElement.StartUpload !== "function") {
690
- throw "ExternalInterface methods failed to initialize.";
691
- }
692
-
693
- // Fix IE Flash/Form bug
694
- if (window[this.movieName] == undefined) {
695
- window[this.movieName] = movieElement;
696
- }
697
-
698
- this.queueEvent("swfupload_loaded_handler");
699
- };
700
-
701
-
702
- /* This is a chance to do something before the browse window opens */
703
- SWFUpload.Gears.prototype.fileDialogStart = function () {
704
- this.queueEvent("file_dialog_start_handler");
705
- };
706
-
707
-
708
- /* Called when a file is successfully added to the queue. */
709
- SWFUpload.Gears.prototype.fileQueued = function (file) {
710
- file = this.unescapeFilePostParams(file);
711
- this.queueEvent("file_queued_handler", file);
712
- };
713
-
714
-
715
- /* Handle errors that occur when an attempt to queue a file fails. */
716
- SWFUpload.Gears.prototype.fileQueueError = function (file, errorCode, message) {
717
- file = this.unescapeFilePostParams(file);
718
- this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
719
- };
720
-
721
- /* Called after the file dialog has closed and the selected files have been queued.
722
- You could call startUpload here if you want the queued files to begin uploading immediately. */
723
- SWFUpload.Gears.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued) {
724
- this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
725
- };
726
-
727
- SWFUpload.Gears.prototype.uploadStart = function (file) {
728
- file = this.unescapeFilePostParams(file);
729
- this.queueEvent("return_upload_start_handler", file);
730
- };
731
-
732
- SWFUpload.Gears.prototype.returnUploadStart = function (file) {
733
- var returnValue;
734
- if (typeof this.settings.upload_start_handler === "function") {
735
- file = this.unescapeFilePostParams(file);
736
- returnValue = this.settings.upload_start_handler.call(this, file);
737
- } else if (this.settings.upload_start_handler != undefined) {
738
- throw "upload_start_handler must be a function";
739
- }
740
-
741
- // Convert undefined to true so if nothing is returned from the upload_start_handler it is
742
- // interpretted as 'true'.
743
- if (returnValue === undefined) {
744
- returnValue = true;
745
- }
746
-
747
- returnValue = !!returnValue;
748
-
749
- this.callFlash("ReturnUploadStart", [returnValue]);
750
- };
751
-
752
-
753
-
754
- SWFUpload.Gears.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
755
- file = this.unescapeFilePostParams(file);
756
- this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
757
- };
758
-
759
- SWFUpload.Gears.prototype.uploadError = function (file, errorCode, message) {
760
- file = this.unescapeFilePostParams(file);
761
- this.queueEvent("upload_error_handler", [file, errorCode, message]);
762
- };
763
-
764
- SWFUpload.Gears.prototype.uploadSuccess = function (file, serverData) {
765
- file = this.unescapeFilePostParams(file);
766
- this.queueEvent("upload_success_handler", [file, serverData]);
767
- };
768
-
769
- SWFUpload.Gears.prototype.uploadComplete = function (file) {
770
- file = this.unescapeFilePostParams(file);
771
- this.queueEvent("upload_complete_handler", file);
772
- };
773
-
774
- /* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
775
- internal debug console. You can override this event and have messages written where you want. */
776
- SWFUpload.Gears.prototype.debug = function (message) {
777
- this.queueEvent("debug_handler", message);
778
- };
779
-
780
-
781
- /* **********************************
782
- Debug Console
783
- The debug console is a self contained, in page location
784
- for debug message to be sent. The Debug Console adds
785
- itself to the body if necessary.
786
-
787
- The console is automatically scrolled as messages appear.
788
-
789
- If you are using your own debug handler or when you deploy to production and
790
- have debug disabled you can remove these functions to reduce the file size
791
- and complexity.
792
- ********************************** */
793
-
794
- // Private: debugMessage is the default debug_handler. If you want to print debug messages
795
- // call the debug() function. When overriding the function your own function should
796
- // check to see if the debug setting is true before outputting debug information.
797
- SWFUpload.Gears.prototype.debugMessage = function (message) {
798
- if (this.settings.debug) {
799
- var exceptionMessage, exceptionValues = [];
800
-
801
- // Check for an exception object and print it nicely
802
- if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
803
- for (var key in message) {
804
- if (message.hasOwnProperty(key)) {
805
- exceptionValues.push(key + ": " + message[key]);
806
- }
807
- }
808
- exceptionMessage = exceptionValues.join("\n") || "";
809
- exceptionValues = exceptionMessage.split("\n");
810
- exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
811
- SWFUpload.Console.writeLine(exceptionMessage);
812
- } else {
813
- SWFUpload.Console.writeLine(message);
814
- }
815
- }
816
- };
817
-
818
- SWFUpload.Gears.Console = {};
819
- SWFUpload.Gears.Console.writeLine = function (message) {
820
- var console, documentForm;
821
-
822
- try {
823
- console = document.getElementById("SWFUpload_Console");
824
-
825
- if (!console) {
826
- documentForm = document.createElement("form");
827
- document.getElementsByTagName("body")[0].appendChild(documentForm);
828
-
829
- console = document.createElement("textarea");
830
- console.id = "SWFUpload_Console";
831
- console.style.fontFamily = "monospace";
832
- console.setAttribute("wrap", "off");
833
- console.wrap = "off";
834
- console.style.overflow = "auto";
835
- console.style.width = "700px";
836
- console.style.height = "350px";
837
- console.style.margin = "5px";
838
- documentForm.appendChild(console);
839
- }
840
-
841
- console.value += message + "\n";
842
-
843
- console.scrollTop = console.scrollHeight - console.clientHeight;
844
- } catch (ex) {
845
- alert("Exception: " + ex.name + " Message: " + ex.message);
846
- }
847
- };
848
-
849
- /* ***************************************************************************
850
- GearsMovie object emulates a Flash generated object with the
851
- SWFUpload ExternalInterface methods exposted.
852
-
853
- Note: The object is _not_ a DOM Node (like the SWFUpload object element)
854
- and any attempts to treat it as such will fail.
855
- *************************************************************************** */
856
-
857
- // In general you shouldn't be accessing this class directly (it's private) but if you do we've
858
- // marked Public and Private methods
859
- SWFUpload.Gears.GearsMovie = function (swfuploadGearsInstance) {
860
- this.swfuploadGearsInstance = swfuploadGearsInstance;
861
- this.gearsDesktop = google.gears.factory.create("beta.desktop");
862
- this.gearsUploader = null;
863
-
864
- this.fileQueue = [];
865
- this.allFiles = [];
866
- this.currentFile = null;
867
- this.fileCounter = 0;
868
- };
869
-
870
- // Public
871
- SWFUpload.Gears.GearsMovie.prototype.SelectFile = function () {
872
- // FIXME - Call SWFUpload file dialog start event
873
-
874
- this.gearsDesktop.openFiles(this.selectFilesHandler, { singleFile : true, [this.swfuploadGearsInstance.settings.file_types] }) // FIXME -- file_types isn't in the right format
875
- };
876
-
877
- // Public
878
- SWFUpload.Gears.GearsMovie.prototype.SelectFiles = function () {
879
- // FIXME - Call SWFUpload file dialog start event
880
-
881
- this.gearsDesktop.openFiles(this.selectFilesHandler, { singleFile : false, [this.swfuploadGearsInstance.settings.file_types] }) // FIXME -- file_types isn't in the right format
882
- };
883
-
884
- // Private
885
- SWFUpload.Gears.GearsMovie.prototype.selectFilesHandler = function (files) {
886
- // FIXME -- check if "THIS" is the right context
887
-
888
- // Go through each file
889
- for (var i = 0; i < files.length; i++) {
890
- var file = files[i];
891
- var gearsFile = new SWFupload.Gears.GearsFile();
892
- gearsFile.id = this.swfuploadGearsInstance.movieName + "_" + this.fileCounter++;
893
- gearsFile.name = file.name;
894
- gearsFile.size = file.blob.length;
895
- gearsFile.filestatus = SWFUpload.FILE_STATUS.QUEUED;
896
- gearsFile.file = file;
897
-
898
- // Check it
899
-
900
- this.fileQueue.push(gearsFile);
901
- this.allFiles[gearsFile.id] = gearsFile;
902
- // Trigger fileQueued event or fileQueueError event
903
-
904
- }
905
-
906
- // Trigger fileDialogComplete event
907
- };
908
-
909
- SWFUpload.Gears.GearsMovie.prototype.StartUpload = function (idOrIndex) {
910
- if (this.gearsUploader !== null) return;
911
-
912
- if (idOrIndex == undefined) {
913
- this.currentFile = this.fileQueue.shift();
914
-
915
- this.gearsUploader = google.gears.factory.create('beta.httprequest');
916
- this.gearsUploader.onreadystatechange = this.readyStateChangeHandler;
917
- this.gearsUploader.open("POST", this.swfuploadGearsInstance.settings.upload_url);
918
-
919
- this.gearsUploader.setRequestHeader('Content-Disposition', 'attachment; filename="' + this.currentFile.name + '"'); // FIXME -- need to escape quotes
920
- this.gearsUploader.setRequestHeader('Content-Type', 'application/octet-stream');
921
- //this.gearsUploader.setRequestHeader('Content-Range', 'bytes ' + byteRange); // HUH?
922
-
923
- this.gearsUploader.send(this.currentFile.file.blob); // FIXME - send the file
924
-
925
- } else {
926
-
927
- } // FIXME -- do the ID search
928
- };
929
-
930
- SWFUpload.Gears.GearsMovie.prototype.readyStateChangeHandler = function () {
931
- // this is probably the HTTPRequest object rather than the GearsMovie
932
- if (this.readyState === 4) {
933
- alert(this.status + " " + this.responseText);
934
- }
935
- };
936
-
937
- SWFUpload.Gears.GearsFile = function () {
938
- this.name = "";
939
- this.size = "";
940
- this.post = {};
941
- this.type = "";
942
- this.creationdate = null;
943
- this.modificationdate = null;
944
-
945
- this.file = null; // Private
946
- }
947
-
948
-
949
-
950
- // Copyright 2007, Google Inc.
951
- //
952
- // Redistribution and use in source and binary forms, with or without
953
- // modification, are permitted provided that the following conditions are met:
954
- //
955
- // 1. Redistributions of source code must retain the above copyright notice,
956
- // this list of conditions and the following disclaimer.
957
- // 2. Redistributions in binary form must reproduce the above copyright notice,
958
- // this list of conditions and the following disclaimer in the documentation
959
- // and/or other materials provided with the distribution.
960
- // 3. Neither the name of Google Inc. nor the names of its contributors may be
961
- // used to endorse or promote products derived from this software without
962
- // specific prior written permission.
963
- //
964
- // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
965
- // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
966
- // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
967
- // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
968
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
969
- // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
970
- // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
971
- // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
972
- // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
973
- // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
974
- //
975
- // Sets up google.gears.*, which is *the only* supported way to access Gears.
976
- //
977
- // Circumvent this file at your own risk!
978
- //
979
- // In the future, Gears may automatically define google.gears.* without this
980
- // file. Gears may use these objects to transparently fix bugs and compatibility
981
- // issues. Applications that use the code below will continue to work seamlessly
982
- // when that happens.
983
-
984
- (function () {
985
- // We are already defined. Hooray!
986
- if (window.google && google.gears) {
987
- return;
988
- }
989
-
990
- var factory = null;
991
-
992
- // Firefox
993
- if (typeof GearsFactory != 'undefined') {
994
- factory = new GearsFactory();
995
- } else {
996
- // IE
997
- try {
998
- factory = new ActiveXObject('Gears.Factory');
999
- // privateSetGlobalObject is only required and supported on WinCE.
1000
- if (factory.getBuildInfo().indexOf('ie_mobile') != -1) {
1001
- factory.privateSetGlobalObject(this);
1002
- }
1003
- } catch (e) {
1004
- // Safari
1005
- if ((typeof navigator.mimeTypes != 'undefined')
1006
- && navigator.mimeTypes["application/x-googlegears"]) {
1007
- factory = document.createElement("object");
1008
- factory.style.display = "none";
1009
- factory.width = 0;
1010
- factory.height = 0;
1011
- factory.type = "application/x-googlegears";
1012
- document.documentElement.appendChild(factory);
1013
- }
1014
- }
1015
- }
1016
-
1017
- // *Do not* define any objects if Gears is not installed. This mimics the
1018
- // behavior of Gears defining the objects in the future.
1019
- if (!factory) {
1020
- return;
1021
- }
1022
-
1023
- // Now set up the objects, being careful not to overwrite anything.
1024
- //
1025
- // Note: In Internet Explorer for Windows Mobile, you can't add properties to
1026
- // the window object. However, global objects are automatically added as
1027
- // properties of the window object in all browsers.
1028
- if (!window.google) {
1029
- google = {};
1030
- }
1031
-
1032
- if (!google.gears) {
1033
- google.gears = {factory: factory};
1034
- }
1035
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/swfupload/swfupload.queue.js DELETED
@@ -1,77 +0,0 @@
1
- /*
2
- Queue Plug-in
3
-
4
- Features:
5
- *Adds a cancelQueue() method for cancelling the entire queue.
6
- *All queued files are uploaded when startUpload() is called.
7
- *If false is returned from uploadComplete then the queue upload is stopped.
8
- If false is not returned (strict comparison) then the queue upload is continued.
9
- *Adds a QueueComplete event that is fired when all the queued files have finished uploading.
10
- Set the event handler with the queue_complete_handler setting.
11
-
12
- */
13
-
14
- var SWFUpload;
15
- if (typeof(SWFUpload) === "function") {
16
- SWFUpload.queue = {};
17
-
18
- SWFUpload.prototype.initSettings = (function (oldInitSettings) {
19
- return function () {
20
- if (typeof(oldInitSettings) === "function") {
21
- oldInitSettings.call(this);
22
- }
23
-
24
- this.customSettings.queue_cancelled_flag = false;
25
- this.customSettings.queue_upload_count = 0;
26
-
27
- this.settings.user_upload_complete_handler = this.settings.upload_complete_handler;
28
- this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;
29
-
30
- this.settings.queue_complete_handler = this.settings.queue_complete_handler || null;
31
- };
32
- })(SWFUpload.prototype.initSettings);
33
-
34
- SWFUpload.prototype.startUpload = function (fileID) {
35
- this.customSettings.queue_cancelled_flag = false;
36
- this.callFlash("StartUpload", false, [fileID]);
37
- };
38
-
39
- SWFUpload.prototype.cancelQueue = function () {
40
- this.customSettings.queue_cancelled_flag = true;
41
- this.stopUpload();
42
-
43
- var stats = this.getStats();
44
- while (stats.files_queued > 0) {
45
- this.cancelUpload();
46
- stats = this.getStats();
47
- }
48
- };
49
-
50
- SWFUpload.queue.uploadCompleteHandler = function (file) {
51
- var user_upload_complete_handler = this.settings.user_upload_complete_handler;
52
- var continueUpload;
53
-
54
- if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {
55
- this.customSettings.queue_upload_count++;
56
- }
57
-
58
- if (typeof(user_upload_complete_handler) === "function") {
59
- continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;
60
- } else {
61
- continueUpload = true;
62
- }
63
-
64
- if (continueUpload) {
65
- var stats = this.getStats();
66
- if (stats.files_queued > 0 && this.customSettings.queue_cancelled_flag === false) {
67
- this.startUpload();
68
- } else if (this.customSettings.queue_cancelled_flag === false) {
69
- this.queueEvent("queue_complete_handler", [this.customSettings.queue_upload_count]);
70
- this.customSettings.queue_upload_count = 0;
71
- } else {
72
- this.customSettings.queue_cancelled_flag = false;
73
- this.customSettings.queue_upload_count = 0;
74
- }
75
- }
76
- };
77
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/swfupload/swfupload.swfobject.js DELETED
@@ -1,110 +0,0 @@
1
- /*
2
- SWFUpload.SWFObject Plugin
3
-
4
- Summary:
5
- This plugin uses SWFObject to embed SWFUpload dynamically in the page. SWFObject provides accurate Flash Player detection and DOM Ready loading.
6
- This plugin replaces the Graceful Degradation plugin.
7
-
8
- Features:
9
- * swfupload_load_failed_hander event
10
- * swfupload_pre_load_handler event
11
- * minimum_flash_version setting (default: "9.0.28")
12
- * SWFUpload.onload event for early loading
13
-
14
- Usage:
15
- Provide handlers and settings as needed. When using the SWFUpload.SWFObject plugin you should initialize SWFUploading
16
- in SWFUpload.onload rather than in window.onload. When initialized this way SWFUpload can load earlier preventing the UI flicker
17
- that was seen using the Graceful Degradation plugin.
18
-
19
- <script type="text/javascript">
20
- var swfu;
21
- SWFUpload.onload = function () {
22
- swfu = new SWFUpload({
23
- minimum_flash_version: "9.0.28",
24
- swfupload_pre_load_handler: swfuploadPreLoad,
25
- swfupload_load_failed_handler: swfuploadLoadFailed
26
- });
27
- };
28
- </script>
29
-
30
- Notes:
31
- You must provide set minimum_flash_version setting to "8" if you are using SWFUpload for Flash Player 8.
32
- The swfuploadLoadFailed event is only fired if the minimum version of Flash Player is not met. Other issues such as missing SWF files, browser bugs
33
- or corrupt Flash Player installations will not trigger this event.
34
- The swfuploadPreLoad event is fired as soon as the minimum version of Flash Player is found. It does not wait for SWFUpload to load and can
35
- be used to prepare the SWFUploadUI and hide alternate content.
36
- swfobject's onDomReady event is cross-browser safe but will default to the window.onload event when DOMReady is not supported by the browser.
37
- Early DOM Loading is supported in major modern browsers but cannot be guaranteed for every browser ever made.
38
- */
39
-
40
-
41
- /* SWFObject v2.0 rc4 <http://code.google.com/p/swfobject/>
42
- Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
43
- This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
44
- */
45
- var swfobject=function(){var X="undefined",P="object",a="visibility:visible",e="visibility:hidden",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",V="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,S=false,C=false;var Y=function(){var l=typeof g.getElementById!=X&&typeof g.getElementsByTagName!=X&&typeof g.createElement!=X&&typeof g.appendChild!=X&&typeof g.replaceChild!=X&&typeof g.removeChild!=X&&typeof g.cloneNode!=X,t=[0,0,0],n=null;if(typeof N.plugins!=X&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=X){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var d=function(){if(!Y.w3cdom){return }J(I);if(Y.ie&&Y.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=b("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);U()}}}}catch(j){}}if(Y.webkit&&typeof g.readyState!=X){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){U()}},10)}if(typeof g.addEventListener!=X){g.addEventListener("DOMContentLoaded",U,null)}M(U)}();function U(){if(S){return }if(Y.ie&&Y.win){var m=W("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=X){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=X){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=X){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(Y.pv[0]>0){var k=b(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(Y.webkit&&Y.webkit<312){T(k)}}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(Y.win||Y.mac)){D(H[j])}else{c(k)}}}}A("#"+m,a)}}function T(m){var k=m.getElementsByTagName(P)[0];if(k){var p=W("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(Y.ie&&Y.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=b(i);for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)})}}function D(j){C=true;var o=b(j.id);if(o){if(j.altContentId){var l=b(j.altContentId);if(l){L=l}}else{L=Z(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=Y.ie&&Y.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(Y.ie&&Y.win&&o.readyState!=4){var i=W("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function c(j){if(Y.ie&&Y.win&&j.readyState!=4){var i=W("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(Z(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(Z(j),j)}}function Z(n){var m=W("div");if(Y.win&&Y.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=b(q);if(typeof AE.id==X){AE.id=q}if(Y.ie&&Y.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=b(AE.id)}else{if(Y.webkit&&Y.webkit<312){var AA=W("embed");AA.setAttribute("type",V);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=W(P);s.setAttribute("type",V);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=W("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function b(i){return g.getElementById(i)}function W(i){return g.createElement(i)}function O(k){var j=Y.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(Y.ie&&Y.mac){return }var l=g.getElementsByTagName("head")[0],k=W("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(Y.ie&&Y.win)&&typeof g.createTextNode!=X){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(Y.ie&&Y.win&&typeof g.styleSheets!=X&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}return{registerObject:function(l,i,k){if(!Y.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;A("#"+l,e)},getObjectById:function(l){var i=null;if(Y.w3cdom&&S){var j=b(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=X)){i=j}else{if(typeof k.SetVariable!=X){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!Y.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){A("#"+u,e);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=X){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);A("#"+u,a)})}else{if(m&&!C&&O("6.0.65")&&(Y.win||Y.mac)){A("#"+u,e);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i);A("#"+u,a)})}}},getFlashPlayerVersion:function(){return{major:Y.pv[0],minor:Y.pv[1],release:Y.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(Y.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(Y.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=b(K);if(i){i.parentNode.replaceChild(L,i);L=null;C=false}}}}}();
46
-
47
-
48
- var SWFUpload;
49
- if (typeof(SWFUpload) === "function") {
50
- SWFUpload.onload = function () {};
51
-
52
- swfobject.addDomLoadEvent(function () {
53
- if (typeof(SWFUpload.onload) === "function") {
54
- SWFUpload.onload.call(window);
55
- }
56
- });
57
-
58
- SWFUpload.prototype.initSettings = (function (oldInitSettings) {
59
- return function () {
60
- if (typeof(oldInitSettings) === "function") {
61
- oldInitSettings.call(this);
62
- }
63
-
64
- this.ensureDefault = function (settingName, defaultValue) {
65
- this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
66
- };
67
-
68
- this.ensureDefault("minimum_flash_version", "9.0.28");
69
- this.ensureDefault("swfupload_pre_load_handler", null);
70
- this.ensureDefault("swfupload_load_failed_handler", null);
71
-
72
- delete this.ensureDefault;
73
-
74
- };
75
- })(SWFUpload.prototype.initSettings);
76
-
77
-
78
- SWFUpload.prototype.loadFlash = function (oldLoadFlash) {
79
- return function () {
80
- var hasFlash = swfobject.hasFlashPlayerVersion(this.settings.minimum_flash_version);
81
-
82
- if (hasFlash) {
83
- this.queueEvent("swfupload_pre_load_handler");
84
- if (typeof(oldLoadFlash) === "function") {
85
- oldLoadFlash.call(this);
86
- }
87
- } else {
88
- this.queueEvent("swfupload_load_failed_handler");
89
- }
90
- };
91
-
92
- }(SWFUpload.prototype.loadFlash);
93
-
94
- SWFUpload.prototype.displayDebugInfo = function (oldDisplayDebugInfo) {
95
- return function () {
96
- if (typeof(oldDisplayDebugInfo) === "function") {
97
- oldDisplayDebugInfo.call(this);
98
- }
99
-
100
- this.debug(
101
- [
102
- "SWFUpload.SWFObject Plugin settings:", "\n",
103
- "\t", "minimum_flash_version: ", this.settings.minimum_flash_version, "\n",
104
- "\t", "swfupload_pre_load_handler assigned: ", (typeof(this.settings.swfupload_pre_load_handler) === "function").toString(), "\n",
105
- "\t", "swfupload_load_failed_handler assigned: ", (typeof(this.settings.swfupload_load_failed_handler) === "function").toString(), "\n",
106
- ].join("")
107
- );
108
- };
109
- }(SWFUpload.prototype.displayDebugInfo);
110
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-core/js/user.js CHANGED
@@ -77,7 +77,7 @@ function ie_rating_rollover(id,state)
77
  break;
78
 
79
  default:
80
- if(target_element.style.background != "url(" + WPSC_CORE_IMAGES_URL + "/gold-star.gif)")
81
  {
82
  target_element.style.background = previous_rating;
83
  }
@@ -92,7 +92,7 @@ var apply_rating=function(results)
92
  for(i=1;i<=outarr[1];i++)
93
  {
94
  id = "star"+outarr[0]+"and"+i+"_link";
95
- document.getElementById(id).style.background = "url(" + WPSC_CORE_IMAGES_URL + "/gold-star.gif)";
96
  }
97
 
98
  for(i=5;i>outarr[1];i--)
77
  break;
78
 
79
  default:
80
+ if(target_element.style.background != "url(" + WPSC_CORE_IMAGES_URL + "/gold-star.png)")
81
  {
82
  target_element.style.background = previous_rating;
83
  }
92
  for(i=1;i<=outarr[1];i++)
93
  {
94
  id = "star"+outarr[0]+"and"+i+"_link";
95
+ document.getElementById(id).style.background = "url(" + WPSC_CORE_IMAGES_URL + "/gold-star.png)";
96
  }
97
 
98
  for(i=5;i>outarr[1];i--)
wpsc-core/js/wp-e-commerce.js CHANGED
@@ -297,6 +297,7 @@ jQuery(document).ready(function ($) {
297
  // update the price when the variations are altered.
298
  jQuery( 'div.wpsc_variation_forms' ).on( 'change', '.wpsc_select_variation', function() {
299
  jQuery('option[value="0"]', this).attr('disabled', 'disabled');
 
300
  var parent_form = jQuery(this).closest("form.product_form");
301
  if ( parent_form.length === 0 )
302
  return;
@@ -311,7 +312,7 @@ jQuery(document).ready(function ($) {
311
  donation_price = jQuery('input#donation_price_' + prod_id),
312
  old_price = jQuery('#old_product_price_' + prod_id),
313
  save = jQuery('#yousave_' + prod_id),
314
- buynow = jQuery('#BB_BuyButtonForm' + prod_id);
315
 
316
  jQuery( document ).trigger( { type : 'wpsc_select_variation', response : response } );
317
 
@@ -342,6 +343,9 @@ jQuery(document).ready(function ($) {
342
  }
343
  }
344
  donation_price.val(response.numeric_price);
 
 
 
345
  }
346
  }, 'json' );
347
  });
@@ -608,17 +612,6 @@ function wpsc_set_profile_country(html_form_id, form_id) {
608
  }, 'json');
609
  }
610
 
611
- jQuery(document).ready(function(){
612
- jQuery('.wpsc_checkout_table input, .wpsc_checkout_table textarea').each(function(){
613
- var real_value = jQuery(this).val();
614
- value = jQuery('label[for="'+jQuery(this).attr('id')+'"]').text();
615
- if( jQuery.fn.inlineFieldLabel )
616
- jQuery(this).inlineFieldLabel({label:jQuery.trim(value)});
617
- if(real_value != '')
618
- jQuery(this).val(real_value).removeClass('intra-field-label');
619
- });
620
- });
621
-
622
  //Javascript for variations: bounce the variation box when nothing is selected and return false for add to cart button.
623
  jQuery(document).ready(function(){
624
  jQuery('.productcol, .textcol, .product_grid_item, .wpsc-add-to-cart-button').each(function(){
297
  // update the price when the variations are altered.
298
  jQuery( 'div.wpsc_variation_forms' ).on( 'change', '.wpsc_select_variation', function() {
299
  jQuery('option[value="0"]', this).attr('disabled', 'disabled');
300
+ self = this;
301
  var parent_form = jQuery(this).closest("form.product_form");
302
  if ( parent_form.length === 0 )
303
  return;
312
  donation_price = jQuery('input#donation_price_' + prod_id),
313
  old_price = jQuery('#old_product_price_' + prod_id),
314
  save = jQuery('#yousave_' + prod_id),
315
+ buynow = jQuery('#buy-now-product_' + prod_id);
316
 
317
  jQuery( document ).trigger( { type : 'wpsc_select_variation', response : response } );
318
 
343
  }
344
  }
345
  donation_price.val(response.numeric_price);
346
+
347
+ buynow.find('input[name="'+jQuery(self).prop('name')+'"]').val(jQuery(self).val());
348
+ buynow.find('input.wpsc-buy-now-button').prop('disabled', false);
349
  }
350
  }, 'json' );
351
  });
612
  }, 'json');
613
  }
614
 
 
 
 
 
 
 
 
 
 
 
 
615
  //Javascript for variations: bounce the variation box when nothing is selected and return false for add to cart button.
616
  jQuery(document).ready(function(){
617
  jQuery('.productcol, .textcol, .product_grid_item, .wpsc-add-to-cart-button').each(function(){
wpsc-core/wpsc-constants.php CHANGED
@@ -28,9 +28,9 @@ function wpsc_core_constants() {
28
  if(!defined('WPSC_URL'))
29
  define( 'WPSC_URL', plugins_url( '', __FILE__ ) );
30
  // Define Plugin version
31
- define( 'WPSC_VERSION', '3.8.11.1' );
32
- define( 'WPSC_MINOR_VERSION', '74e9456712' );
33
- define( 'WPSC_PRESENTABLE_VERSION', '3.8.11.1' );
34
  define( 'WPSC_DB_VERSION', 4 );
35
 
36
  // Define Debug Variables for developers
28
  if(!defined('WPSC_URL'))
29
  define( 'WPSC_URL', plugins_url( '', __FILE__ ) );
30
  // Define Plugin version
31
+ define( 'WPSC_VERSION', '3.8.12-beta' );
32
+ define( 'WPSC_MINOR_VERSION', '55f8cfa0d7' );
33
+ define( 'WPSC_PRESENTABLE_VERSION', '3.8.12-beta' );
34
  define( 'WPSC_DB_VERSION', 4 );
35
 
36
  // Define Debug Variables for developers
wpsc-core/wpsc-functions.php CHANGED
@@ -688,6 +688,9 @@ function _wpsc_pre_get_posts_reset_taxonomy_globals( $query ) {
688
  if ( ! get_option( 'use_pagination' ) )
689
  return;
690
 
 
 
 
691
  $query->set( 'posts_per_page', get_option( 'wpsc_products_per_page' ) );
692
 
693
  $post_type_object = get_post_type_object( 'wpsc-product' );
@@ -721,7 +724,7 @@ function wpsc_start_the_query() {
721
  if ( count( $wpsc_query_vars ) <= 1 ) {
722
  $post_type_object = get_post_type_object( 'wpsc-product' );
723
  $wpsc_query_vars = array(
724
- 'post_status' => current_user_can( $post_type_object->cap->edit_posts ) ? 'private,draft,pending,publish' : 'publish',
725
  'post_parent' => 0,
726
  'order' => apply_filters( 'wpsc_product_order', get_option( 'wpsc_product_order', 'ASC' ) )
727
  );
@@ -1179,8 +1182,7 @@ class wpsc_products_by_category {
1179
  }
1180
 
1181
  $post_type_object = get_post_type_object( 'wpsc-product' );
1182
- $permitted_post_statuses = current_user_can( $post_type_object->cap->edit_posts ) ? "'private', 'draft', 'pending', 'publish'" : "'publish'";
1183
-
1184
 
1185
  $whichcat .= " AND $wpdb->posts.post_status IN ($permitted_post_statuses) ";
1186
  $groupby = "{$wpdb->posts}.ID";
@@ -1907,10 +1909,10 @@ function wpsc_get_product_terms( $product_id, $tax, $field = '' ) {
1907
  * Returns page slug that corresponds to a given WPEC-specific shortcode.
1908
  *
1909
  * @since 3.8.10
1910
- *
1911
  * @uses wpsc_get_the_post_id_by_shortcode() Gets page ID of shortcode.
1912
  * @uses get_post_field() Returns post name of page ID.
1913
- *
1914
  * @param string $shortcode Shortcode of WPEC-specific page, e.g. '[productspage]''
1915
  * @return string Post slug
1916
  */
688
  if ( ! get_option( 'use_pagination' ) )
689
  return;
690
 
691
+ if ( ! is_page( wpsc_get_the_post_id_by_shortcode( '[productspage]' ) ) && ! $query->get( 'wpsc_product_category' ) )
692
+ return;
693
+
694
  $query->set( 'posts_per_page', get_option( 'wpsc_products_per_page' ) );
695
 
696
  $post_type_object = get_post_type_object( 'wpsc-product' );
724
  if ( count( $wpsc_query_vars ) <= 1 ) {
725
  $post_type_object = get_post_type_object( 'wpsc-product' );
726
  $wpsc_query_vars = array(
727
+ 'post_status' => apply_filters( 'wpsc_product_display_status', array( 'publish' ) ),
728
  'post_parent' => 0,
729
  'order' => apply_filters( 'wpsc_product_order', get_option( 'wpsc_product_order', 'ASC' ) )
730
  );
1182
  }
1183
 
1184
  $post_type_object = get_post_type_object( 'wpsc-product' );
1185
+ $permitted_post_statuses = "'" . implode( "', '", $query->query_vars['post_status'] ) . "'";
 
1186
 
1187
  $whichcat .= " AND $wpdb->posts.post_status IN ($permitted_post_statuses) ";
1188
  $groupby = "{$wpdb->posts}.ID";
1909
  * Returns page slug that corresponds to a given WPEC-specific shortcode.
1910
  *
1911
  * @since 3.8.10
1912
+ *
1913
  * @uses wpsc_get_the_post_id_by_shortcode() Gets page ID of shortcode.
1914
  * @uses get_post_field() Returns post name of page ID.
1915
+ *
1916
  * @param string $shortcode Shortcode of WPEC-specific page, e.g. '[productspage]''
1917
  * @return string Post slug
1918
  */
wpsc-core/wpsc-installer.php CHANGED
@@ -143,6 +143,7 @@ function wpsc_install() {
143
 
144
  add_option( 'postage_and_packaging', '0','', 'yes' );
145
  add_option( 'shipwire', '0', '', 'yes' );
 
146
 
147
  add_option( 'purch_log_email', '', '', 'yes' );
148
  add_option( 'return_email', '', '', 'yes' );
143
 
144
  add_option( 'postage_and_packaging', '0','', 'yes' );
145
  add_option( 'shipwire', '0', '', 'yes' );
146
+ add_option( 'shipwire_test_server', '0', '', 'yes' );
147
 
148
  add_option( 'purch_log_email', '', '', 'yes' );
149
  add_option( 'return_email', '', '', 'yes' );
wpsc-includes/ajax.functions.php CHANGED
@@ -35,9 +35,8 @@ function wpsc_add_to_cart() {
35
  $permitted_post_statuses = current_user_can( $post_type_object->cap->edit_posts ) ? array( 'private', 'draft', 'pending', 'publish' ) : array( 'publish' );
36
 
37
  /// sanitise submitted values
38
- $product_id = apply_filters( 'wpsc_add_to_cart_product_id', (int) $_POST['product_id'] );
39
-
40
- $product = get_post( $product_id );
41
 
42
  if ( ! in_array( $product->post_status, $permitted_post_statuses ) || 'wpsc-product' != $product->post_type )
43
  return false;
@@ -88,7 +87,6 @@ function wpsc_add_to_cart() {
88
 
89
  $cart_item = $wpsc_cart->set_item( $product_id, $parameters );
90
 
91
-
92
  if ( is_object( $cart_item ) ) {
93
  do_action( 'wpsc_add_to_cart', $product, $cart_item );
94
  $cart_messages[] = str_replace( "[product_name]", $cart_item->get_title(), __( 'You just added "[product_name]" to your cart.', 'wpsc' ) );
@@ -103,6 +101,7 @@ function wpsc_add_to_cart() {
103
  }
104
  }
105
 
 
106
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
107
 
108
  $json_response = array( 'cart_messages' => $cart_messages, 'product_id' => $product_id, 'cart_total' => wpsc_cart_total() );
@@ -234,8 +233,9 @@ function _wpsc_get_alternate_html() {
234
  add_query_arg(
235
  array( 'ajax' => 'true', 'wpsc_action' => 'wpsc_get_alternate_html', 'ajax' => 'true', 'wpsc_ajax_action' => 'add_to_cart' ), home_url() ),
236
  array( 'body' =>
237
- array( 'cart_messages' => $cart_messages, 'ajax' => 'true', 'wpsc_ajax_action' => 'add_to_cart', 'product_id' => $_REQUEST['product_id']
238
- )
 
239
  )
240
  )
241
  );
@@ -388,7 +388,7 @@ function wpsc_get_rating_count() {
388
  global $wpdb, $wpsc_cart;
389
  $prodid = $_POST['product_id'];
390
  $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) AS `count` FROM `" . WPSC_TABLE_PRODUCT_RATING . "` WHERE `productid` = %d", $prodid ) );
391
- echo $count . "," . $prodid;
392
  exit();
393
  }
394
 
@@ -526,7 +526,7 @@ function wpsc_update_location() {
526
  if ( wpsc_get_customer_meta( 'shipping_same_as_billing' ) && ( $delivery_country != $billing_country || $delivery_region != $billing_region ) )
527
  wpsc_update_customer_meta( 'shipping_same_as_billing', false );
528
 
529
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
530
  exit;
531
  }
532
 
@@ -888,8 +888,8 @@ if ( isset( $_REQUEST['wpsc_ajax_action'] ) && 'change_tax' == $_REQUEST['wpsc_a
888
  function _wpsc_change_profile_country() {
889
  global $wpdb;
890
 
891
- $country_field_id = $_REQUEST['form_id'];
892
- $country = $_REQUEST['country'];
893
 
894
  $sql = $wpdb->prepare( 'SELECT unique_name FROM `'.WPSC_TABLE_CHECKOUT_FORMS.'` WHERE `id`= %d', $country_field_id );
895
  $country_field_unique_name = $wpdb->get_var( $sql );
35
  $permitted_post_statuses = current_user_can( $post_type_object->cap->edit_posts ) ? array( 'private', 'draft', 'pending', 'publish' ) : array( 'publish' );
36
 
37
  /// sanitise submitted values
38
+ $product_id = apply_filters( 'wpsc_add_to_cart_product_id' , (int) $_POST['product_id'] );
39
+ $product = apply_filters( 'wpsc_add_to_cart_product_object', get_post( $product_id, OBJECT, 'display' ) );
 
40
 
41
  if ( ! in_array( $product->post_status, $permitted_post_statuses ) || 'wpsc-product' != $product->post_type )
42
  return false;
87
 
88
  $cart_item = $wpsc_cart->set_item( $product_id, $parameters );
89
 
 
90
  if ( is_object( $cart_item ) ) {
91
  do_action( 'wpsc_add_to_cart', $product, $cart_item );
92
  $cart_messages[] = str_replace( "[product_name]", $cart_item->get_title(), __( 'You just added "[product_name]" to your cart.', 'wpsc' ) );
101
  }
102
  }
103
 
104
+
105
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
106
 
107
  $json_response = array( 'cart_messages' => $cart_messages, 'product_id' => $product_id, 'cart_total' => wpsc_cart_total() );
233
  add_query_arg(
234
  array( 'ajax' => 'true', 'wpsc_action' => 'wpsc_get_alternate_html', 'ajax' => 'true', 'wpsc_ajax_action' => 'add_to_cart' ), home_url() ),
235
  array( 'body' =>
236
+ array(
237
+ 'cart_messages' => $cart_messages, 'ajax' => 'true', 'wpsc_ajax_action' => 'add_to_cart', 'product_id' => $_REQUEST['product_id']
238
+ )
239
  )
240
  )
241
  );
388
  global $wpdb, $wpsc_cart;
389
  $prodid = $_POST['product_id'];
390
  $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) AS `count` FROM `" . WPSC_TABLE_PRODUCT_RATING . "` WHERE `productid` = %d", $prodid ) );
391
+ echo $count . "," . absint( $prodid );
392
  exit();
393
  }
394
 
526
  if ( wpsc_get_customer_meta( 'shipping_same_as_billing' ) && ( $delivery_country != $billing_country || $delivery_region != $billing_region ) )
527
  wpsc_update_customer_meta( 'shipping_same_as_billing', false );
528
 
529
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && 'update_location' == $_REQUEST['action'] )
530
  exit;
531
  }
532
 
888
  function _wpsc_change_profile_country() {
889
  global $wpdb;
890
 
891
+ $country_field_id = absint( $_REQUEST['form_id'] );
892
+ $country = $_REQUEST['country'];
893
 
894
  $sql = $wpdb->prepare( 'SELECT unique_name FROM `'.WPSC_TABLE_CHECKOUT_FORMS.'` WHERE `id`= %d', $country_field_id );
895
  $country_field_unique_name = $wpdb->get_var( $sql );
wpsc-includes/cart.class.php CHANGED
@@ -288,7 +288,7 @@ function wpsc_cart_item_quantity_single_prod($id) {
288
  * @param int $prod_id Optional. Product ID.
289
  * @return int The maximum quantity that can be added to the cart.
290
  *
291
- * @uses apply_filters Calls 'wpsc_product_max_cart_quantity' passing product ID.
292
  */
293
  function wpsc_product_max_cart_quantity( $product_id = 0 ) {
294
  $product_id = absint( $product_id );
@@ -297,7 +297,7 @@ function wpsc_product_max_cart_quantity( $product_id = 0 ) {
297
 
298
  /**
299
  * Validate Product Cart Quantity
300
- * Checks that the quantity is within the permitted bounds and return a valid quantity.
301
  *
302
  * @since 3.8.10
303
  * @access public
@@ -1957,12 +1957,12 @@ class wpsc_cart_item {
1957
  $accepted_file_types['mime'][] = 'image/pjpeg'; // Added for IE compatibility
1958
  $accepted_file_types['mime'][] = 'image/x-png'; // Added for IE compatibility
1959
 
1960
-
1961
  $accepted_file_types['ext'][] = 'jpeg';
1962
  $accepted_file_types['ext'][] = 'jpg';
1963
  $accepted_file_types['ext'][] = 'gif';
1964
  $accepted_file_types['ext'][] = 'png';
1965
 
 
1966
 
1967
  $can_have_uploaded_image = get_product_meta($this->product_id,'product_metadata',true);
1968
  $product = get_post($this->product_id);
@@ -1975,7 +1975,10 @@ class wpsc_cart_item {
1975
  $name_parts = explode('.',basename($file_data['name']));
1976
  $extension = array_pop($name_parts);
1977
 
1978
- if(( (array_search($file_data['type'], $accepted_file_types['mime']) !== false) || (get_option('wpsc_check_mime_types') == 1) ) && (array_search($extension, $accepted_file_types['ext']) !== false) ) {
 
 
 
1979
 
1980
  if(is_file(WPSC_USER_UPLOADS_DIR.$file_data['name'])) {
1981
  $name_parts = explode('.',basename($file_data['name']));
288
  * @param int $prod_id Optional. Product ID.
289
  * @return int The maximum quantity that can be added to the cart.
290
  *
291
+ * @uses apply_filters Calls 'wpsc_product_max_cart_quantity' passing product ID.
292
  */
293
  function wpsc_product_max_cart_quantity( $product_id = 0 ) {
294
  $product_id = absint( $product_id );
297
 
298
  /**
299
  * Validate Product Cart Quantity
300
+ * Checks that the quantity is within the permitted bounds and return a valid quantity.
301
  *
302
  * @since 3.8.10
303
  * @access public
1957
  $accepted_file_types['mime'][] = 'image/pjpeg'; // Added for IE compatibility
1958
  $accepted_file_types['mime'][] = 'image/x-png'; // Added for IE compatibility
1959
 
 
1960
  $accepted_file_types['ext'][] = 'jpeg';
1961
  $accepted_file_types['ext'][] = 'jpg';
1962
  $accepted_file_types['ext'][] = 'gif';
1963
  $accepted_file_types['ext'][] = 'png';
1964
 
1965
+ $accepted_file_types = apply_filters( 'wpsc_customer_upload_accepted_file_types', $accepted_file_types );
1966
 
1967
  $can_have_uploaded_image = get_product_meta($this->product_id,'product_metadata',true);
1968
  $product = get_post($this->product_id);
1975
  $name_parts = explode('.',basename($file_data['name']));
1976
  $extension = array_pop($name_parts);
1977
 
1978
+ if ( ( (
1979
+ array_search( strtolower( $file_data['type'] ), $accepted_file_types['mime'] ) !== false ) ||
1980
+ get_option( 'wpsc_check_mime_types' ) == 1 ) &&
1981
+ array_search( strtolower( $extension ), $accepted_file_types['ext'] ) !== false ) {
1982
 
1983
  if(is_file(WPSC_USER_UPLOADS_DIR.$file_data['name'])) {
1984
  $name_parts = explode('.',basename($file_data['name']));
wpsc-includes/checkout.class.php CHANGED
@@ -691,8 +691,8 @@ class wpsc_checkout {
691
  case "address":
692
  case "delivery_address":
693
  case "textarea":
694
-
695
- $output .= "<textarea title='" . $this->checkout_item->unique_name . "' class='text' id='" . $this->form_element_id() . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' rows='3' cols='40' >" . esc_html( (string) $saved_form_data ) . "</textarea>";
696
  break;
697
 
698
  case "checkbox":
@@ -754,23 +754,24 @@ class wpsc_checkout {
754
  case "email":
755
  case "coupon":
756
  default:
 
757
  if ( $this->checkout_item->unique_name == 'shippingstate' ) {
758
  if ( wpsc_uses_shipping() && wpsc_has_regions($delivery_country) ) {
759
  $region_name = $wpdb->get_var( $wpdb->prepare( "SELECT `name` FROM `" . WPSC_TABLE_REGION_TAX . "` WHERE `id`= %d LIMIT 1", $delivery_region ) );
760
- $output = "<input title='" . $this->checkout_item->unique_name . "' type='hidden' id='" . $this->form_element_id() . "' class='shipping_region' name='collected_data[{$this->checkout_item->id}]' value='" . esc_attr( $delivery_region ) . "' size='4' /><span class='shipping_region_name'>" . esc_html( $region_name ) . "</span> ";
761
  } else {
762
  $disabled = '';
763
  if(wpsc_disregard_shipping_state_fields())
764
  $disabled = 'disabled = "disabled"';
765
- $output = "<input class='shipping_region text' title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' ".$disabled." />";
766
  }
767
  } elseif ( $this->checkout_item->unique_name == 'billingstate' ) {
768
  $disabled = '';
769
  if(wpsc_disregard_billing_state_fields())
770
  $disabled = 'disabled = "disabled"';
771
- $output = "<input class='billing_region text' title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' ".$disabled." />";
772
  } else {
773
- $output = "<input title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' class='text' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' />";
774
  }
775
 
776
  break;
691
  case "address":
692
  case "delivery_address":
693
  case "textarea":
694
+ $placeholder = apply_filters( 'wpsc_checkout_field_placeholder', apply_filters( 'wpsc_checkout_field_name', $this->checkout_item->name ), $this->checkout_item );
695
+ $output .= "<textarea title='" . $this->checkout_item->unique_name . "' class='text' id='" . $this->form_element_id() . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' placeholder='" . esc_attr( $placeholder ) . "' rows='3' cols='40' >" . esc_html( (string) $saved_form_data ) . "</textarea>";
696
  break;
697
 
698
  case "checkbox":
754
  case "email":
755
  case "coupon":
756
  default:
757
+ $placeholder = apply_filters( 'wpsc_checkout_field_placeholder', apply_filters( 'wpsc_checkout_field_name', $this->checkout_item->name ), $this->checkout_item );
758
  if ( $this->checkout_item->unique_name == 'shippingstate' ) {
759
  if ( wpsc_uses_shipping() && wpsc_has_regions($delivery_country) ) {
760
  $region_name = $wpdb->get_var( $wpdb->prepare( "SELECT `name` FROM `" . WPSC_TABLE_REGION_TAX . "` WHERE `id`= %d LIMIT 1", $delivery_region ) );
761
+ $output = "<input title='" . $this->checkout_item->unique_name . "' type='hidden' id='" . $this->form_element_id() . "' class='shipping_region' name='collected_data[{$this->checkout_item->id}]' placeholder='" . esc_attr( $placeholder ) . "' value='" . esc_attr( $delivery_region ) . "' size='4' /><span class='shipping_region_name'>" . esc_html( $region_name ) . "</span> ";
762
  } else {
763
  $disabled = '';
764
  if(wpsc_disregard_shipping_state_fields())
765
  $disabled = 'disabled = "disabled"';
766
+ $output = "<input class='shipping_region text' title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' placeholder='" . esc_attr( $placeholder ) . "' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' ".$disabled." />";
767
  }
768
  } elseif ( $this->checkout_item->unique_name == 'billingstate' ) {
769
  $disabled = '';
770
  if(wpsc_disregard_billing_state_fields())
771
  $disabled = 'disabled = "disabled"';
772
+ $output = "<input class='billing_region text' title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' placeholder='" . esc_attr( $placeholder ) . "' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' ".$disabled." />";
773
  } else {
774
+ $output = "<input title='" . $this->checkout_item->unique_name . "' type='text' id='" . $this->form_element_id() . "' class='text' placeholder='" . esc_attr( $placeholder ) . "' value='" . esc_attr( $saved_form_data ) . "' name='collected_data[{$this->checkout_item->id}]" . $an_array . "' />";
775
  }
776
 
777
  break;
wpsc-includes/coupons.class.php CHANGED
@@ -329,7 +329,7 @@ class wpsc_coupons {
329
  }
330
  }
331
 
332
- return true;
333
  }
334
 
335
  /**
329
  }
330
  }
331
 
332
+ return $compare_logic;
333
  }
334
 
335
  /**
wpsc-includes/display.functions.php CHANGED
@@ -15,36 +15,60 @@
15
  * @return string - html displaying one or more products
16
  */
17
  function wpsc_buy_now_button( $product_id, $replaced_shortcode = false ) {
18
- $product = get_post( $product_id );
19
- $supported_gateways = array('wpsc_merchant_paypal_standard','paypal_multiple');
20
- $selected_gateways = get_option( 'custom_gateway_options' );
 
 
 
 
21
  if ( $replaced_shortcode )
22
  ob_start();
23
 
24
- if ( in_array( 'wpsc_merchant_paypal_standard', (array)$selected_gateways ) ) {
25
  if ( $product_id > 0 ) {
26
- $post_meta = get_post_meta( $product_id, '_wpsc_product_metadata', true );
27
- $shipping = isset( $post_meta['shipping'] ) ? $post_meta['shipping']['local'] : '';
28
- $price = get_post_meta( $product_id, '_wpsc_price', true );
 
29
  $special_price = get_post_meta( $product_id, '_wpsc_special_price', true );
 
30
  if ( $special_price )
31
  $price = $special_price;
 
32
  if ( wpsc_uses_shipping ( ) ) {
33
  $handling = get_option( 'base_local_shipping' );
34
  } else {
35
  $handling = $shipping;
36
  }
37
 
38
- $src = _x( 'https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif', 'PayPal Buy Now Button', 'wpsc' );
39
- $src = apply_filters( 'wpsc_buy_now_button_src', $src );
40
- $classes = "wpsc-buy-now-form wpsc-buy-now-form-{$product_id}";
41
- $button_html = '<input class="wpsc-buy-now-button wpsc-buy-now-button-' . esc_attr( $product_id ) . '" type="image" name="submit" border="0" src=' . esc_url( $src ) . ' alt="' . esc_attr( 'PayPal - The safer, easier way to pay online', 'wpsc' ) . '" />';
 
 
 
 
 
 
 
 
42
  $button_html = apply_filters( 'wpsc_buy_now_button_html', $button_html, $product_id );
43
- ?>
44
- <form class="<?php echo esc_attr( $classes ); ?>" target="paypal" action="<?php echo esc_url( home_url() ); ?>" method="post">
45
  <input type="hidden" name="wpsc_buy_now_callback" value="1" />
46
  <input type="hidden" name="product_id" value="<?php echo esc_attr( $product_id ); ?>" />
47
- <?php if ( get_option( 'multi_add' ) ): ?>
 
 
 
 
 
 
 
 
 
48
  <label for="quantity"><?php esc_html_e( 'Quantity', 'wpsc' ); ?></label>
49
  <input type="text" size="4" id="quantity" name="quantity" value="" /><br />
50
  <?php else: ?>
@@ -70,20 +94,20 @@ function wpsc_also_bought( $product_id ) {
70
  if ( get_option( 'wpsc_also_bought' ) == 0 ) {
71
  return '';
72
  }
73
-
74
  // To be made customiseable in a future release
75
  $also_bought_limit = 3;
76
  $element_widths = 96;
77
  $image_display_height = 96;
78
  $image_display_width = 96;
79
-
80
  // Filter will be used by a plugin to provide 'Also Bought' functionality when this is deprecated from core.
81
  // Filter is currently private and should not be used by plugin/theme devs as it may only be temporary.
82
  $output = apply_filters( '_wpsc_also_bought', '', $product_id );
83
  if ( ! empty( $output ) ) {
84
  return $output;
85
  }
86
-
87
  // If above filter returns output then the following is ignore and can be deprecated in future.
88
  $also_bought = $wpdb->get_results( $wpdb->prepare( "SELECT `" . $wpdb->posts . "`.* FROM `" . WPSC_TABLE_ALSO_BOUGHT . "`, `" . $wpdb->posts . "` WHERE `selected_product`= %d AND `" . WPSC_TABLE_ALSO_BOUGHT . "`.`associated_product` = `" . $wpdb->posts . "`.`id` AND `" . $wpdb->posts . "`.`post_status` IN('publish','protected') ORDER BY `" . WPSC_TABLE_ALSO_BOUGHT . "`.`quantity` DESC LIMIT $also_bought_limit", $product_id ), ARRAY_A );
89
  if ( is_array( $also_bought ) && count( $also_bought ) > 0 ) {
@@ -338,25 +362,26 @@ function wpsc_obtain_the_title() {
338
  return $output.$seperator;
339
  }
340
 
 
 
 
341
  function wpsc_obtain_the_description() {
342
- global $wpdb, $wp_query, $wpsc_title_data;
343
  $output = null;
344
 
345
- if ( is_numeric( $wp_query->query_vars['category_id'] ) ) {
346
- $category_id = $wp_query->query_vars['category_id'];
347
- } else if ( $_GET['category'] ) {
348
- $category_id = absint( $_GET['category'] );
 
349
  }
350
 
351
- if ( is_numeric( $category_id ) ) {
352
- $output = wpsc_get_categorymeta( $category_id, 'description' );
 
 
353
  }
354
 
355
-
356
- if ( is_numeric( $_GET['product_id'] ) ) {
357
- $product_id = absint( $_GET['product_id'] );
358
- $output = $wpdb->get_var( $wpdb->prepare( "SELECT `post_content` FROM `" . $wpdb->posts . "` WHERE `id` = %d LIMIT 1", $product_id ) );
359
- }
360
  return $output;
361
  }
362
 
15
  * @return string - html displaying one or more products
16
  */
17
  function wpsc_buy_now_button( $product_id, $replaced_shortcode = false ) {
18
+
19
+ $product_id = absint($product_id);
20
+
21
+ $product = get_post( $product_id );
22
+ $supported_gateways = array( 'wpsc_merchant_paypal_standard', 'paypal_multiple' );
23
+ $selected_gateways = get_option( 'custom_gateway_options' );
24
+
25
  if ( $replaced_shortcode )
26
  ob_start();
27
 
28
+ if ( in_array( 'wpsc_merchant_paypal_standard', (array) $selected_gateways ) ) {
29
  if ( $product_id > 0 ) {
30
+
31
+ $post_meta = get_post_meta( $product_id, '_wpsc_product_metadata', true );
32
+ $shipping = isset( $post_meta['shipping'] ) ? $post_meta['shipping']['local'] : '';
33
+ $price = get_post_meta( $product_id, '_wpsc_price', true );
34
  $special_price = get_post_meta( $product_id, '_wpsc_special_price', true );
35
+
36
  if ( $special_price )
37
  $price = $special_price;
38
+
39
  if ( wpsc_uses_shipping ( ) ) {
40
  $handling = get_option( 'base_local_shipping' );
41
  } else {
42
  $handling = $shipping;
43
  }
44
 
45
+ $has_variants = wpsc_product_has_variations( $product_id );
46
+
47
+ $src = apply_filters( 'wpsc_buy_now_button_src', _x( 'https://www.paypal.com/en_US/i/btn/btn_buynow_LG.gif', 'PayPal Buy Now Button', 'wpsc' ) );
48
+ $classes = apply_filters( 'wpsc_buy_now_button_class', "wpsc-buy-now-form wpsc-buy-now-form-{$product_id}" );
49
+
50
+ $button_html = sprintf( '<input%1$s class="wpsc-buy-now-button wpsc-buy-now-button-%2$s" type="image" name="submit" border="0" src="%3$s" alt="%4$s" />',
51
+ disabled( $has_variants, true, false ),
52
+ esc_attr( $product_id ),
53
+ esc_url( $src ),
54
+ esc_attr__( 'PayPal - The safer, easier way to pay online', 'wpsc' )
55
+ );
56
+
57
  $button_html = apply_filters( 'wpsc_buy_now_button_html', $button_html, $product_id );
58
+ ?>
59
+ <form class="<?php echo esc_attr( sanitize_html_class( $classes, '' ) ); ?>" id="buy-now-product_<?php echo $product_id; ?>" target="paypal" action="<?php echo esc_url( home_url() ); ?>" method="post">
60
  <input type="hidden" name="wpsc_buy_now_callback" value="1" />
61
  <input type="hidden" name="product_id" value="<?php echo esc_attr( $product_id ); ?>" />
62
+ <?php
63
+ if ( $has_variants ) :
64
+ // grab the variation form fields here
65
+ $wpsc_variations = new wpsc_variations( $product_id );
66
+ while ( wpsc_have_variation_groups() ) : wpsc_the_variation_group();
67
+ printf('<input type="hidden" class="variation-value" name="variation[%1$d]" id="%2$s" value="0"/>', wpsc_vargrp_id(), wpsc_vargrp_form_id() );
68
+ endwhile;
69
+ endif; /* END wpsc_product_has_variations */
70
+ ?>
71
+ <?php if ( get_option( 'multi_add' ) ) : ?>
72
  <label for="quantity"><?php esc_html_e( 'Quantity', 'wpsc' ); ?></label>
73
  <input type="text" size="4" id="quantity" name="quantity" value="" /><br />
74
  <?php else: ?>
94
  if ( get_option( 'wpsc_also_bought' ) == 0 ) {
95
  return '';
96
  }
97
+
98
  // To be made customiseable in a future release
99
  $also_bought_limit = 3;
100
  $element_widths = 96;
101
  $image_display_height = 96;
102
  $image_display_width = 96;
103
+
104
  // Filter will be used by a plugin to provide 'Also Bought' functionality when this is deprecated from core.
105
  // Filter is currently private and should not be used by plugin/theme devs as it may only be temporary.
106
  $output = apply_filters( '_wpsc_also_bought', '', $product_id );
107
  if ( ! empty( $output ) ) {
108
  return $output;
109
  }
110
+
111
  // If above filter returns output then the following is ignore and can be deprecated in future.
112
  $also_bought = $wpdb->get_results( $wpdb->prepare( "SELECT `" . $wpdb->posts . "`.* FROM `" . WPSC_TABLE_ALSO_BOUGHT . "`, `" . $wpdb->posts . "` WHERE `selected_product`= %d AND `" . WPSC_TABLE_ALSO_BOUGHT . "`.`associated_product` = `" . $wpdb->posts . "`.`id` AND `" . $wpdb->posts . "`.`post_status` IN('publish','protected') ORDER BY `" . WPSC_TABLE_ALSO_BOUGHT . "`.`quantity` DESC LIMIT $also_bought_limit", $product_id ), ARRAY_A );
113
  if ( is_array( $also_bought ) && count( $also_bought ) > 0 ) {
362
  return $output.$seperator;
363
  }
364
 
365
+ /**
366
+ * Return category or product description depending on queried item
367
+ */
368
  function wpsc_obtain_the_description() {
369
+
370
  $output = null;
371
 
372
+ // Return Category Description
373
+ if ( is_numeric( get_query_var('category_id') ) ) {
374
+ $output = wpsc_get_categorymeta( get_query_var('category_id'), 'description' );
375
+ } else if ( ! empty($_GET['category']) ) {
376
+ $output = wpsc_get_categorymeta( absint( $_GET['category'] ), 'description' );
377
  }
378
 
379
+ // Return product content as description if product page
380
+ if ( !empty($_GET['product_id'] ) && is_numeric( $_GET['product_id'] ) ) {
381
+ $product = get_post(absint( $_GET['product_id'] ));
382
+ $output = $product->post_content;
383
  }
384
 
 
 
 
 
 
385
  return $output;
386
  }
387
 
wpsc-includes/nusoap/changelog DELETED
@@ -1,584 +0,0 @@
1
- 2003-07-21, version 0.6.5
2
- - soap_transport_http: SOAPAction header is quoted again, fixes problem w/ Weblogic Server
3
- - applied Jason Levitt patch for proper array serialization, fixes problem w/ Amazon shopping cart services
4
- - fixed null value serialization
5
- - applied patch from "BZC ToOn'S" - fixes wsdl serialization when no parameters
6
- - applied John's patch, implementing compression for the server
7
-
8
- 2003-07-22, version 0.6.5
9
- - soap_server: fixed bug causing charset encoding not to be passed to the parser
10
- - soap_fault: added default encoding to the fault serialization
11
- - soap_parser: changed the parser to pre-load the parent's result array when processing scalar values. This increases parsing speed.
12
-
13
- 2003-07-23, version 0.6.5
14
- - soap_base: fix code that overwrites user-supplied attributes in serialize_val
15
- - soap_base: use arrays-of-arrays rather than attempting multi-dimensional in serialize_val
16
- - xmlschema: emit import statements and qualify all elements with prefix in serializeSchema (better interop with validation tools)
17
- - soapclient: get xml character encoding from HTTP Content-Type header if provided, e.g. text/xml;charset="UTF-8"
18
- - soapclient: use headers in call if provided (previously ignored this parameter)
19
- - soap_server: in parse_request, if neither getallheaders nor $_SERVER are available, use $HTTP_SERVER_VARS to get SOAPAction and xml encoding
20
-
21
- 2003-07-24, version 0.6.5
22
- - soap_transport_http: apply patch from Steven Brown "if the server closes connection prematurely, nusoap would spin trying to read data that isn't there"
23
-
24
- 2003-07-25, version 0.6.5
25
- - wsdl: apply patch from Sven to workaround single schema limitation
26
- - wsdl: apply a variant of the patch from Holger to handle empty values for array by serializing an array with 0 elements
27
- - xmlschema: remove the redundant default namespace attribute on the schema element; everything in xsd is explicitly specified as being from xsd
28
- - soap_transport_http: fix setCredentials and add TODO comments in sendHTTPS about what to change if this setCredentials stays
29
-
30
- 2003-07-30, version 0.6.5
31
- - nusoap_base: change documentation of soap_defencoding to specify it is the encoding for outgoing messages
32
- - nusoap_base: only change &, <, > to entities, not all HTML entities
33
- - soap_transport_http: update the Content-Type header in sendRequest, since soap_defencoding could be changed after ctor is called
34
- - soap_server: use soap_defencoding instead of charset_encoding
35
- - soap_server: read encoding from _SERVER if available
36
- - nusoap_base: do entity translation for string parameters with an xsd type specified (thanks David Derr)
37
-
38
- 2003-07-31, version 0.6.5
39
- - soap_transport_http: add proxy authentication
40
- - soap_transport_http: build payload the same way for http and https
41
- - wsdl: add proxy authentication
42
- - soapclient: add proxy authentication
43
- - soapclient: allow proxy information in ctor, so that it can be used for wsdl
44
-
45
- 2003-08-01, version 0.6.5
46
- - soap_transport_http: close a persistent connection that's at EOF
47
- - soap_transport_http: prevent conflicts between setEncoding and usePersistentConnection
48
- - soap_transport_http: fix use of $headers instead of $this->incoming_headers in getResponse
49
- - soapclient: improve handling of persistent connections
50
- - soapclient: force xml_encoding to upper case
51
- - soap_server: let the Web server decide whether to close the connection (no Connection: close header)
52
- - soap_server: force xml_encoding to upper case
53
-
54
- 2003-08-04, version 0.6.5
55
- - soap_parser: use XML type information to pick a PHP data type; also decode base64
56
- - soap_server: read all HTTP headers when using _SERVER or HTTP_SERVER_VARS
57
- - soap_server: add gzip encoding support for outgoing messages
58
- - soap_transport_http: deflate is gzcompress/gzuncompress (cf. http://archive.develooper.com/libwww@perl.org/msg04650.html)
59
- - soap_transport_http: clean use of persistentConnection so it's always a set boolean
60
- - soapclient: add responseData member to access deflated/gunzipped payload
61
-
62
- 2003-08-05, version 0.6.5
63
- - soap_server: look multiple places when setting debug_flag
64
-
65
- 2003-08-07, version 0.6.5
66
- - nusoap_base: serialize specified type (e.g. ArrayOfString) even for simple array
67
- - wsdl: only specify encodingStyle in the input/output soap bindings when it is not empty (thanks Guillaume)
68
-
69
- 2003-08-15, version 0.6.5
70
- - soap_parser: fix parsing of elements with no XSD type specified
71
- - soap_parser: use PHP string type for XSD long and unsignedLong types
72
-
73
- 2003-08-16, version 0.6.5
74
- - soap_parser: fix code generating warning (thanks Torsten)
75
-
76
- 2003-08-19, version 0.6.5
77
- - soap_parser: fix another line of code generating a warning (thanks Torsten)
78
-
79
- 2003-08-22, version 0.6.5
80
- - soap_server: remove all '--' from debug_str; previous code changed '---' to '- --'
81
- - wsdl, soapclient, soap_parser: patch submitted by Mark Spavin as described by
82
- the following...
83
- > Changes for the multiple/nested imports from the wsdl file. This builds an
84
- > array of files not just the last one and also checks for relative paths to
85
- > the parent. This will then get the imported files from the remote site
86
- > instead of your local disk. Local wsdl files should still work (untested).
87
- >
88
- > Changes for multiple encoding sytles as previously posted
89
-
90
- 2003-08-24, version 0.6.5
91
- - wsdl, soapclient: fix some PHP notices from previous update
92
-
93
- 2003-08-26, version 0.6.5
94
- - wsdl: support multiple SOAP ports
95
- - soapclient, soap_server: when no charset is specified, use UTF-8, even though HTTP specifies US-ASCII.
96
- - soap_transport_http: do not prepend $host with 'ssl://' for https (is this required for older cURL versions?)
97
-
98
- 2003-08-27, version 0.6.5
99
- - soap_server: support compressed request messages (thanks John Huong)
100
- - soap_parser: deserialize Apache Vector as an array
101
- - xmlschema: use $this->typemap in getPHPType (which is not used)
102
- - soapclient, wsdl: check for WSDL errors after serializing parameters
103
- - nusoap_base: add serialization of Apache Map (when not using WSDL)
104
- - wsdl: add serialization of Apache Map (when using WSDL)
105
- - wsdl: only change &, <, > to entities, not all HTML entities
106
-
107
- 2003-08-28, version 0.6.5
108
- - soap_transport_http: disable cURL verification of peer and server (formerly the cURL default)
109
- - soap_transport_http: mingle cURL code with straight http, so sendHTTP is no longer needed
110
-
111
- 2003-08-29, version 0.6.6
112
- - soap_transport_http: add setContentType
113
- - soapclient: call setContentType using new getHTTPContentType and getHTTPContentTypeCharset
114
-
115
- 2003-09-05, version 0.6.6
116
- - wsdl: add some more code to handle null/nil values (but there's still a way to go)
117
-
118
- 2003-10-21, version 0.6.6
119
- - soap_transport_http: only include port in Host header if it was specified in the URL
120
- - soap_transport_http: add some code to use OpenSSL for PHP ssl:// scheme, but comment out since it's not ready
121
- - soap_server: use $_SERVER['PHP_SELF'] if $GLOBALS['PHP_SELF'] is not set
122
- - wsdl: add WSDL request and response and transport debug to debug
123
- - wsdl: handle custom type extending xmlschema namespace (GLUE ... Thanks Matt)
124
- - soap_parser: add param to docs
125
- - soapclient: add getHTTPBody, getHTTPContentType, getHTTPContentTypeCharset (anticipating MIME subclass)
126
-
127
- 2003-10-28, version 0.6.6
128
- - nusoap_base: add expandEntities method
129
- - wsdl: use expandEntities
130
- - soap_fault: use expandEntities
131
- - soap_transport_http: Allow credentials to be included in URL, rather than requiring setCredentials
132
- - soap_transport_http: Merge HTTP headers that span multiple lines
133
- - soap_parser: Properly set errors in ctor
134
- - soapclient: Pass headers to parseResponse and parse them in that method
135
-
136
- 2003-10-30, version 0.6.6
137
- - xmlschema: Add some information for the related type to an element
138
-
139
- 2003-12-09, version 0.6.6
140
- - nusoap_base: Add some namespace methods previously in xmlschema
141
- - xmlschema: Improve parsing of complexType, element and simpleType
142
- - xmlschema: Improve serialization
143
- - xmlschema: Track imports
144
- - xmlschema: Track elementFormDefault and form attributes
145
- - wsdl: Support multiple <schema> (note that setting $server->wsdl->schemaTargetNamespace no longer does anything! Use configureWSDL instead.)
146
- - wsdl: Use form attribute of element to control namespace specification
147
- - wsdl: Support chained imports (A imports B which imports C)
148
- - wsdl: Include port in endpoint address when serializing
149
- - soap_server: Fix use of style (rpc|document) and use (encoded|literal)
150
- - soap_server: Support _SERVER[CONTENT_TYPE] in addition to _SERVER[HTTP_CONTENT_TYPE]
151
- - soap_server: Support wsdl with multiple <schema>
152
- - soap_client: Remove a var_dump
153
- - soap_client: Add style and use parameters to call method to support doc/lit without WSDL
154
- - soap_transport_http: Check that $this->fp exists when doing persistent connections
155
-
156
- 2003-12-17, version 0.6.6
157
- - soap_server: pass namespaces to xmlschema constructor
158
- - wsdl: post-process after all imports
159
- - wsdl: remove some debug, add some error handling
160
- - xmlschema: allow enclosing namespaces to be specified in constructor
161
- - xmlschema: improve handling of compositors and simple types
162
-
163
- 2004-01-08, version 0.6.6
164
- - soap_server: when requested WSDL is in a file, return to client using passthru (thanks Ingo Fischer)
165
- - soapclient: have proxy inherit more client state
166
- - soapclient: allow timeout and response timeout to be specified in the constructor
167
- - wsdl: allow timeout and response timeout to be specified in the constructor
168
- - soap_transport_http: allow response timeout to be specified in send and sendHTTPS
169
-
170
- 2004-01-28, version 0.6.6
171
- - wsdl: add namespace for array and scalar when form is qualified
172
- - wsdl: fix a bug in which data type of complexType elements were ignored in serialization
173
- - wsdl: enhance handling of URLs with file scheme
174
- - wsdl: add addSimpleType
175
- - xmlschema: add addSimpleType
176
- - xmlschema: always set phpType elements
177
- - soapclient: allow a wsdl instance to be specified in constructor
178
- - soap_server: allow a wsdl instance to be specified in constructor (not tested!)
179
- - soap_server: fix default SOAPAction created in register method
180
- - soap_transport_http: accept chunking with LF separators in addition to CRLF.
181
- - wsdlcache: added class
182
- - nusoapmime: fix comments
183
-
184
- 2004-02-23, version 0.6.6
185
- - soap_transport_http: don't try to unchunk cURL data, since cURL already does it
186
- - soap_transport_http: append CVS revision to version in User-Agent
187
- - wsdl: serialize boolean as true|false, not 1|0, to agree with XML Schema
188
- - soap_server: always exit() after returning WSDL
189
- - soap_server: use the WSDL URL scheme as the default endpoint URL scheme
190
- - soap_server: append CVS revision to version in X-SOAP-Server
191
- - nusoap_base: add (CVS) revision
192
- - wsdlcache: synchronize using a per-WSDL lock file (Thanks Ingo)
193
- - wsdlcache: add cache lifetime, after which cache contents are invalidated (Thanks Ingo)
194
-
195
- 2004-03-15, version 0.6.6
196
- - nusoap_base: add isArraySimpleOrStruct method
197
- - soap_server: improve WSDL URL scheme determination
198
- - soap_server: only deflate/gzip payloads > 1024 bytes
199
- - soap_server: fix parameter order in fault method (always used as faultcode, faultstring)
200
- - soap_server: refactor parse_request into multiple functions (for sanity)
201
- - soap_server: set the namespace on the Response element to the same as the request
202
- - soap_server: name the return value element 'return' by default
203
- - soap_server: added and documented data fields, so that service programmers can use them if desired
204
- - soap_parser: standardize parsing error message
205
- - soap_parser: fix document and responseHeaders so they are the correct XML text (as documented)
206
- - soap_transport_http: fix read from persistent connection
207
- - soapclient: clean up debugging for persistent connection
208
- - wsdl: enforce correct naming of messages parts when an associative array is used for parameters
209
- - wsdl: better serialization of null values
210
- - wsdl: standardize parsing error message
211
- - xmlschema: standardize parsing error message
212
-
213
- 2004-03-24, version 0.6.7
214
- - soap_transport_http: add digest authentication (based on code by Kevin A. Miller)
215
- - xmlschema: improve parsing of import elements
216
- - wsdl: do schema imports even if there are no wsdl imports
217
-
218
- 2004-04-12, version 0.6.7
219
- - wsdl: serialize multiple elements when maxOccurs="unbounded" and value is an array
220
- - wsdl: serialize soapval values (used to force an XML type, e.g. when WSDL uses an abstract type)
221
- - nusoapmime: do not require nusoap.php (it is now the programmer's responsibility)
222
-
223
- 2004-04-21, version 0.6.7
224
- - soap_parser: parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element)
225
- - soap_server: do not wrap response in a response element for a document style service
226
-
227
- 2004-04-30, version 0.6.7
228
- - soap_transport_http: allow digest auth params to be separated by "," as well as ", "
229
- - soap_transport_http: re-initialize incoming headers for each response
230
- - soap_server: add methodreturnisliteralxml property to allow service function to return XML as a string
231
- - soapclient: improve rpc/literal support
232
- - soapclient: allow XML string as call params in addition to array
233
- - soapclient: support document style and literal encoding when not using WSDL
234
-
235
- 2004-05-05, version 0.6.7
236
- - wsdl: serialize PHP objects for WSDL XML Schema complexTypes, in addition to associative arrays
237
- - wsdl: fix WSDL generation when there is no encodingStyle
238
- - soap_transport_http: suppress fsockopen warnings
239
- - soap_transport_http: detect socket timeouts when reading (0 bytes returned)
240
- - soap_transport_http: read chunked content "in-line" so it works on a persistent connection
241
- - nusoap_base: serialize boolean as true|false, not 1|0, to agree with XML Schema
242
- - nusoap_base: serialize array of struct differently than array of array
243
-
244
- 2004-06-25, version 0.6.8
245
- - soap_server: prefer gzip to deflate, since IE does not like our deflate
246
- - soap_server: move webDescription to the wsdl class
247
- - soap_server: allow class and instance method calls for service (thanks Ingo Fischer and Roland Knall)
248
- - wsdl: get webDescription from the soap_server class
249
- - wsdl: allow compression from the server
250
- - wsdl: fix serialization of soapval without a type
251
- - wsdl: propagate debug value from query string to SOAP endpoint in programmatic WSDL generation
252
- - nusoap_base: add anyType, anySimpleType for 2001 XML Schema
253
- - nusoap_base: provide additional debug functions
254
- - soap_transport_http: ignore Content-Length when chunked encoding is used
255
- - soap_transport_http: remove ':' from username for Basic authentication (cf. RFC 2617)
256
- - soap_transport_http: urldecode username and password taken from URL
257
- - soap_transport_http: use raw inflate/deflate for IE/IIS compatibility, rather than having Zlib headers according to HTTP 1.1 spec
258
- - soap_transport_http: attempt to handle the case when both the service application and Web server compress the response
259
- - soapclient: when creating proxy methods, replace '.' in operation name with '__' in function name
260
- - soapclient: initialize requestHeaders in proxy
261
- - general: use new debug methods; never access debug_str directly
262
-
263
- 2004-09-30, version 0.6.8
264
- - soapclient: do not allow getProxy call when WSDL is not used
265
- - soapclient: use ISO-8859-1 as the charset if not specified in the Content-Type header
266
- - soapclient: when an empty string is specified for the call namespace, do not put the method element in a namespace
267
- - soapclient: let soap_transport_http check for SSL support
268
- - soapclient: have proxy inherit soap_defencoding from the client from which it is generated
269
- - soapclient: do not assume that 'ns1' is an unused namespace prefix; always generate namespace prefixes randomly
270
- - soap_parser: compare any encoding in the XML declaration to the charset from the HTTP Content-Type header (thanks Ingo Fischer)
271
- - soap_parser: improve parse repeated element name into an array (de-serializes doc/lit array into a PHP array when there is more than 1 array element)
272
- - soap_server: use ISO-8859-1 as the charset if not specified in the Content-Type header
273
- - soap_server: allow suppression of automatic UTF-8 decoding
274
- - soap_server: fix a bug when call_user_func_array() is used
275
- - soap_transport_http: correct digest authentication through a proxy
276
- - wsdl: serialize SOAP-ENC types similarly to XSD types
277
- - xmlschema: force unprefixed type into default namespace
278
- - xmlschema: fix serialization of definition of simple types
279
-
280
- 2004-10-01, version 0.6.8
281
- - soap_parser: handle default namespace attributes
282
- - soap_server: add default_utf8 field
283
- - soap_server: support literal encoding (with RPC style)
284
- - soap_transport_http: parse HTTP status and generate error for 300, 302-307, 400, 401-417, 501-505 (thanks for the idea Ghislain)
285
- - soap_transport_http: follow HTTP redirection (HTTP status 301 and Location header) (thanks for the idea Ghislain)
286
- - xmlschema: allow any attributes to be specified in an element of a complexType, e.g., abstract, default, form, minOccurs, maxOccurs, nillable (thanks Jirka Pech for the original patch)
287
-
288
- 2004-10-02, version 0.6.8
289
- - soapclient: read/write cookies (thanks Ingo)
290
- - soap_server: change faultcode on non-resendable faults to Client
291
- - soap_transport_http: read/write cookies (thanks Ingo)
292
-
293
- 2004-10-05, version 0.6.8
294
- - wsdl: add addElement method
295
- - wsdl: support the document style in the register method
296
- - xmlschema: parse unnamed simpleTypes, rather than ignoring them
297
- - xmlschema: include untyped elements when parsing a complexType
298
- - xmlschema: add addElement method
299
-
300
- 2004-10-14, version 0.6.8
301
- - soapclient: support client certificates
302
- - soap_parser: deserialize attributes, prefixing names with "!"
303
- - soap_server: notify the client with HTML when WSDL is requested but not supported by service
304
- - soap_transport_http: support client certificates
305
- - wsdl: support defaults for elements of a complexType
306
- - wsdl: serialize elements from complexType extension base
307
- - wsdl: serialize data (associative array elements) as attributes according to XML Schema
308
- - xmlschema: record extension base if present for a complexType
309
-
310
- 2004-12-15, version 0.6.8
311
- - nusoap_base: add 2000 XML Schema (rare, but used by Akamai)
312
- - soap_parser: avoid deserializing more common attributes that are not data
313
- - soap_parser: be lax when HTTP specifies ISO-8859-1 (the default) and XML specifies UTF-8 (the norm)
314
- - soap_server: account for the fact that get_class_methods returns methods in all lower case (thanks Steve Haldane)
315
- - soap_transport_http: parse digest info that includes '=' in the data (thanks Jinsuk Kim)
316
- - wsdl: feably handle some cases for literal serialization of form="unqualified" elements
317
- - wsdl: don't serialize the decimal portion of a PHP double when the XML type is long
318
- - wsdl: fix serialization of attributes for complexType that is an extension
319
- - wsdlcache: enhance diagnostics
320
- - xmlschema: handle untyped elements
321
- - xmlschema: handle WSDL for SOAP Array that uses the base attribute plus a sequence of element
322
-
323
- 2005-01-22, version 0.6.8
324
- - wsdl: allow an element in one schema to have a type from another schema
325
-
326
- 2005-01-24, version 0.6.8
327
- - xmlschema: correctly parse nested complexType definitions
328
-
329
- 2005-02-14, version 0.6.8
330
- - nusoap_base: fix a bug in which attributes were sometimes not serialized with a value
331
- - nusoap_base: improve serialization of null values (thanks Dominique Stender)
332
- - soap_parser: parse null values by handling the nil attribute (thanks Dominique Stender)
333
- - soap_server: set character encoding for a fault to be the same as for the server (thanks Mark Scott)
334
- - soap_server: correctly check for null value returned from method when WSDL is used (without WSDL, cannot distinguish whether NULL or void return is desired)
335
- - soapclient: for document style, call should always return an array rooted at the response part (all bets are off when there are multiple parts)
336
- - xmlschema: save enumeration values parsed from WSDL
337
-
338
- 2005-02-10, version 0.6.9
339
- - soapclient: only set SOAP headers when they are specified in call params (so setHeaders still works)
340
-
341
- 2005-04-04, version 0.6.9
342
- - soap_server: use get_class instead of is_a (thanks Thomas Noel)
343
- - soapclient: use get_class instead of is_a (thanks Thomas Noel)
344
- - soapclient: add setEndpoint method
345
- - soap_transport_http: fix client certificates (thanks Doug Anarino and Eryan Eriobowo)
346
-
347
- 2005-04-29, version 0.6.9
348
- - nusoap_base: add global variable and methods for setting debug level
349
- - nusoap_base: use xsd:anyType instead of xsd:ur-type to serialize arrays with multiple element types (thanks Ingo Fischer)
350
- - nusoap_base: expand entities in attributes (thanks Gaetano Giunta)
351
- - soapclient: call parent constructor
352
- - soapval: call parent constructor
353
- - soap_fault: call parent constructor
354
- - soap_parser: call parent constructor
355
- - soap_server: assume get_class_methods always returns lower case for PHP 4.x only
356
- - soap_server: call parent constructor
357
- - soap_transport_http: do nothing in setEncoding if gzdeflate is not present (thanks Franck Touanen for pointing this out)
358
- - soap_transport_http: fix check for server request for digest authentication (thanks Mark Spavin)
359
- - soap_transport_http: call parent constructor
360
- - wsdl: fix documentation page popup of one method after another (thanks Owen)
361
- - wsdl: call parent constructor
362
- - wsdl: expand entities in attributes (thanks Gaetano Giunta)
363
- - xmlschema: call parent constructor
364
-
365
- 2005-06-03, version 0.6.9
366
- - nusoap_base: serialize empty arrays as having elements xsd:anyType[0]
367
- - nusoap_base: add encodingStyle parameter to serializeEnvelope
368
- - nusoap_base: serialize xsi:type with nil values
369
- - nusoap_base: improve debug and comments
370
- - soap_parser: correctly parse an empty array to an empty array, not an empty string
371
- - soap_parser: improve debug and comments
372
- - soap_server: specify encodingStyle for envelope when WSDL is used
373
- - soapclient: factor out new getProxyClassCode method
374
- - soapclient: specify encodingStyle for envelope
375
- - soapclient: improve debug and comments
376
- - wsdl: add namespace for Apache SOAP types if a variable of such type is serialized
377
- - wsdl: serialize nil value for nillable elements when no value is provided
378
- - wsdl: serialize xsi:type with nil values
379
- - wsdl: copy attributes as well as elements to an element from its complexType
380
- - wsdl: specify encodingStyle for operations
381
- - wsdl: improve debug and comments
382
- - xmlschema: improve debug and comments
383
-
384
- 2005-06-03, version 0.7.0
385
- - nusoap_base: improve debug and comments
386
- - nusoap_base: fix version, which should have been 0.7.0 since 2005-03-04
387
-
388
- 2005-06-06, version 0.7.1
389
- - nusoap_base: adjust numeric element names for serialization, instead of forcing them to 'soapVal'
390
- - nusoapmime: add type=text/xml to multipart/related (thanks Emmanuel Cordonnier)
391
- - soap_fault: fix serialization of detail
392
- - soap_server: check required parameters for register method
393
- - soap_server: when getallheaders is used, massage header names
394
- - soap_server: use SOAPAction to determine operation when doc/lit service does not wrap parameters in an element with the method name (thanks Peter Hrastnik)
395
- - soap_transport_http: correctly handle multiple HTTP/1.1 100 responses for https (thanks Jan Slabon)
396
- - wsdl: fixed documentation for addComplexType (thanks Csintalan �d�m)
397
- - wsdl: serialize array data when maxOccurs = 'unbounded' OR maxOccurs > 1 (thanks Dominique Schreckling)
398
- - wsdl: when serializing a string == 'false' as a boolean, set the value to false
399
- - wsdl: when serializing a complexType, require the PHP value supplied to be an array
400
-
401
- 2005-07-01, version 0.7.1
402
- - nusoap_base: Allow SOAP headers to be supplied as an array like parameters
403
- - soap_parser: de-serialize simpleContent that accompanies complexContent
404
- - soap_server: append debug information when programmatically-defined WSDL is returned
405
- - soap_transport_http: Add debug when an outgoing header is set
406
- - soapclient: Allow SOAP headers to be supplied as an array like parameters
407
- - xmlschema: serialize attributes more generally, rather than assuming they are for SOAP 1.1 Array
408
- - wsdl: when serializing, look up types by namespace, not prefix (simple programmatic doc/lit WSDL now seems to work)
409
- - wsdl: process namespace declarations first when parsing an element
410
-
411
- 2005-07-27, version 0.7.1
412
- - nusoap_base: do not override supplied element name with class name when serializing an object in serialize_val
413
- - nusoap_base: remove http://soapinterop.org/xsd (si) from namespaces array
414
- - nusoapmime: add nusoapservermime class to implement MIME attachments on the server
415
- - soap_fault: improve documentation
416
- - soap_server: improve documentation
417
- - soap_server: make consistent use of _SERVER and HTTP_SERVER_VARS
418
- - soap_server: make all incoming HTTP header keys lower case
419
- - soap_server: add hook functions to support subclassing for MIME attachments
420
- - soap_transport_http: remove an unnecessary global statement
421
- - soapclient: when creating a proxy, make $params within each function an associative array
422
- - soapval: improve documentation
423
- - wsdl: when serializing complexType elements, used typed serialization if there is either a type or a reference for the element
424
- - wsdl: allow PHP objects to be serialized as SOAP structs in serializeType
425
- - wsdl: for WSDL and XML Schema imports, don't forget to use the TCP port number (thanks Luca GIOPPO)
426
- - wsdl: make consistent use of _SERVER and HTTP_SERVER_VARS
427
- - xmlschema: improve documentation
428
-
429
- 2005-07-31, version 0.7.2
430
- - nusoap_base: correctly serialize attributes in serialize_val (thanks Hidran Arias)
431
- - soap_parser: when resolving references, do not assume that buildVal returns an array (thanks Akshell)
432
- - soap_parser: removed decode_entities, which does not work (thanks Martin Sarsale)
433
- - soap_server: fix a bug parsing headers from _SERVER and HTTP_SERVER_VARS (thanks Bert Catsburg)
434
- - soap_server: parse all "headers" from HTTP_SERVER_VARS (not just HTTP_*)
435
- - soap_server: use PHP_SELF instead of SCRIPT_NAME for WSDL endpoint
436
- - soap_server: when generating a fault while debug_flag is true, put debug into faultdetail
437
- - wsdl: add enumeration parameter to addSimpleType
438
- - xmlschema: add enumeration parameter to addSimpleType
439
-
440
- 2006-02-02, version 0.7.2
441
- - soapclient: initialize paramArrayStr to improve proxy generation
442
- - soap_parser: handle PHP5 soapclient's incorrect transmission of WSDL-described SOAP encoded arrays.
443
- - soap_server: don't assume _SERVER['HTTPS'] is set; try HTTP_SERVER_VARS['HTTPS'] if it is not
444
- - soap_server: "flatten out" the parameter array to call_user_func_array (thanks Andr� Mamitzsch)
445
- - soap_server: make thrown exceptions conform to specs
446
- - wsdl: use serialize_val to serialize an array when the XSD type is soapenc:Array (JBoss/Axis does this)
447
- - wsdl: change formatting of serialized XML for the WSDL
448
- - xmlschema: change formatting of namespaces when serializing XML for the schema
449
-
450
- 2006-04-07, version 0.7.2
451
- - soap_server: if methodparams is not an array, call call_user_func_array with an empty array (thanks Eric Grossi)
452
- - wsdl: distinguish parts with element specified from those with type specified by suffixing element names with ^
453
- - wsdl: do a case-insensitive match on schema URI when looking for type
454
- - xmlschema: only get element (not type) when name has ^ suffix
455
-
456
- 2006-05-16, version 0.7.2
457
- - soapclient: add getHeader to get parsed SOAP Header
458
- - soap_parser: check status when receiving Header or Body element
459
- - soap_parser: add soapheader
460
- - soap_server: add requestHeader with parsed SOAP Header
461
-
462
- 2006-06-15, version 0.7.2
463
- - wsdl: fix bug in addComplexType (thanks Maarten Meijer)
464
- - soap_transport_http: change cURL message
465
-
466
- 2007-03-19, version 0.7.2
467
- - soapclient: declare as nusoapclient, then also subclass soapclient if SOAP extension not loaded
468
- - soapclientmime: declare as nusoapclientmime, then also subclass soapclientmime if SOAP extension not loaded
469
-
470
- 2007-03-28, version 0.7.2
471
- - nusoap_base: fix serialization of a soapval when its value is a soapval
472
- - soapval: fix serialization of a soapval when its value is a soapval
473
- - soapval: add __toString (cf. http://article.gmane.org/gmane.comp.php.nusoap.general/2776)
474
- - nusoapclient: use lazy retrieval of WSDL instead of always getting it in the constructor
475
- - nusoapclient: fix getProxy that was broken in last revision
476
- - wsdl: add ability to set authorization credentials and retrieve WSDL outside of constructor
477
-
478
- 2007-04-05, version 0.7.2
479
- - nusoapclientmime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
480
- - nusoapclientmime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
481
- - nusoapservermime: don't rely exclusively on Content-Disposition to distinguish the root part from attachment; also check Content-Type (thanks Ben Bosman)
482
- - nusoapservermime: obey RFC 2045 Section 5.1 (thanks Chris Butler)
483
- - nusoap_base: remove extra whitespace from some XML elements
484
- - nusoap_base: allow SOAP headers to be specified as an associative array (thanks Unique)
485
- - nusoap_base: implement __toString
486
- - nusoap_base: improve doc accuracy and consistency (thanks Martin K?gler)
487
- - iso8601_to_timestamp: avoid problem with negative hours after calculation, etc. (thanks Guntram Trebs)
488
- - nusoapclient: support user-settable cURL options (thanks Ciprian Popovici)
489
- - nusoapclient: call SOAP 1.2 binding operations if no SOAP 1.1 present (there is no reason to believe this will always work!)
490
- - nusoapclient: improve doc accuracy and consistency (thanks Martin K?gler)
491
- - soap_server: don't try to use eval to call function when any parameter is an object
492
- - soap_server: don't print return value within debug string; returned objects would need __toString in PHP 5.2
493
- - soap_server: use URL scheme for WSDL access as the scheme in SOAPAction
494
- - soap_server: strip port number from server name (some FastCGI implementations include port in server name)
495
- - soap_transport_http: support user-settable cURL options (thanks Ciprian Popovici)
496
- - soap_transport_http: use cURL for NTLM authentication
497
- - soap_transport_http: make digest authentication work for GET as well as POST
498
- - soap_transport_http: improve doc accuracy and consistency (thanks Martin K?gler)
499
- - soapval: remove __toString
500
- - wsdl: set operation style if necessary, but do not override one already provided (thanks Raffaele Capobianco)
501
- - wsdl: check SOAP 1.2 binding operations if no SOAP 1.1 present
502
- - wsdl: improve doc accuracy and consistency (thanks Martin K?gler)
503
- - xmlschema: fix simpleType serialization
504
- - xmlschema: improve doc accuracy and consistency (thanks Martin K?gler)
505
-
506
- 2007-04-09, version 0.7.2
507
- - nusoapclient: set decode_utf8 when creating a proxy (thanks Dmitri Dmitrienko)
508
- - nusoapclient: rename class to nusoap_client
509
- - soap_fault: also provide a class named nusoap_fault
510
- - soap_parser: also provide a class named nusoap_parser
511
- - soap_server: also provide a class named nusoap_server
512
- - soap_transport_http: skip HTTP responses 301 and 401 when using cURL
513
- - soap_transport_http: don't force HTTP Connection header when using cURL
514
- - soap_transport_http: don't set HTTP Host and Content-Length headers when using cURL
515
- - soap_transport_http: support CURLOPT_SSLCERTPASSWD (thanks David Blanco)
516
- - wsdl: support user-settable cURL options (thanks Ciprian Popovici)
517
- - wsdl: serialize parameters for non-SOAP 1.1 binding operations (there is no reason to believe this will always work!)
518
- - xmlschema: also provide a class named nusoap_xmlschema
519
- - nusoapclientmime: rename class to nusoap_client_mime
520
- - nusoapservermime: rename class to nusoap_server_mime
521
-
522
- 2007-04-11, version 0.7.2
523
- - nusoap_client: enable cURL usage to be forced (thanks Giunta Gaetano)
524
- - soap_transport_http: enable cURL proxy usage (thanks Giunta Gaetano)
525
- - soap_transport_http: enable cURL usage to be forced (thanks Giunta Gaetano)
526
- - soap_transport_http: use cURL's HTTP authentication options for basic, digest
527
- - wsdl: enable cURL usage to be forced (thanks Giunta Gaetano)
528
-
529
- 2007-04-12, version 0.7.2
530
- - nusoap_client: add debug
531
- - nusoap_xmlschema: don't add elements of complexTypes to elements array (thanks Heiko Hund)
532
- - soap_transport_http: set cURL connection timeout if supported
533
- - soap_transport_http: add debug when setting cURL option
534
- - soap_transport_http: fix digest authentication broken in previous revision
535
- - wsdl: add debug
536
- - wsdlcache: address some issues with non-existing cache-files and PHP Warnings which came in such cases (thanks Ingo Fischer)
537
- - wsdlcache: change class name to nusoap_wsdlcache
538
-
539
- 2007-04-13, version 0.7.2
540
- - wsdl: wrap parameters if unwrapped values are supplied and WSDL specifies Microsoft-style wrapping
541
-
542
- 2007-04-16, version 0.7.2
543
- - nusoap_base: avoid warning in getDebugAsXMLComment
544
- - nusoap_client: small debug change
545
- - nusoap_client_mime: set responseData when the root part is found
546
-
547
- 2007-04-17, version 0.7.2
548
- - soap_transport_http: improve detection of undefined cURL options (thanks Ingo Fischer)
549
-
550
- 2007-05-28, version 0.7.2
551
- - soap_transport_http: support digest authentication opaque feature (cf. RFC 2617) (thanks Daniel Lacroix)
552
- - soap_transport_http: check safe_mode and open_basedir before setting CURLOPT_FOLLOWLOCATION
553
- - soap_transport_http: skip "HTTP/1.0 200 Connection established" header when cURL returns it (thanks Raimund Jacob)
554
- - nusoap_client: improve handling when getProxy is called and WSDL is not being used
555
- - nusoap_base: add comments about which specifications are used/implemented by NuSOAP
556
- - nusoap_xmlschema: create names for unnamed types that are unique by scope within XML Schema
557
-
558
- 2007-06-11, version 0.7.2
559
- - wsdl: wrap return value if unwrapped value is supplied and WSDL specifies Microsoft-style wrapping
560
-
561
- 2007-06-22, version 0.7.2
562
- - nusoap_xmlschema: fix serialization of simpleType restriction (thanks Rizwan Tejpar)
563
-
564
- 2007-07-30, version 0.7.2
565
- - nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
566
- - nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
567
-
568
- 2007-10-21, version 0.7.2
569
- - nusoap_server: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
570
- - nusoap_client: Per http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735, rpc/literal accessor elements should not be in a namespace (thanks Kostas Kalevras)
571
-
572
- 2007-10-26, version 0.7.2
573
- - nusoap_server: Fix munging of _SERVER variables that start with HTTP_ (thanks Thomas Wieczorek)
574
-
575
- 2007-10-30, version 0.7.2
576
- - nusoap_xmlschema: Serialize values for elementFormDefault, attributeFormDefault
577
- - wsdl: Improve consistency between doc/lit schema auto-wrapping and client's parsed schema
578
- - nusoap_server: Correct bug that placed encodingType in Envelope for doc/lit
579
- - nusoap_server: Specify elementFormDefault for schema within doc/lit wsdl
580
-
581
- 2007-10-31, version 0.7.2
582
- - wsdl: Fix typo in parametersMatchWrapped (thanks Sam Stepanyan)
583
- - soap_transport_http: Fix three typos in setProxy (thanks Sam Stepanyan)
584
- - nusoap_xmlschema: Fix typo in serializeTypeDef (thanks Sam Stepanyan)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.nusoap_base.php DELETED
@@ -1,984 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soap_fault.php DELETED
@@ -1,90 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soap_parser.php DELETED
@@ -1,639 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soap_server.php DELETED
@@ -1,1073 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soap_transport_http.php DELETED
@@ -1,1305 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soap_val.php DELETED
@@ -1,107 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.soapclient.php DELETED
@@ -1,977 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.wsdl.php DELETED
@@ -1,1904 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.wsdlcache.php DELETED
@@ -1,209 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/class.xmlschema.php DELETED
@@ -1,938 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/nusoap.php DELETED
@@ -1,7993 +0,0 @@
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
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wpsc-includes/nusoap/nusoapmime.php DELETED
@@ -1,501 +0,0 @@
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
-