Version Description
-
*
Download this release
Release Info
Developer | hannanstd |
Plugin | گرویتی فرم فارسی |
Version | 2.3.0 |
Comparing to | |
See all releases |
Code changes from version 2.1.6 to 2.3.0
- assets/css/admin.rtl.css +0 -69
- assets/css/font-admin.css +27 -0
- assets/css/font-face-shabnam.css +7 -0
- assets/css/font-face-vazir.css +7 -0
- assets/css/font-face-yekan.css +7 -0
- assets/css/font.droidsans.css +0 -16
- assets/css/font.yekan.css +0 -29
- assets/css/print.rtl.css +0 -1
- assets/css/rtl-admin.css +127 -0
- assets/css/rtl-print.css +13 -0
- assets/fonts/BYekan.eot +0 -0
- assets/fonts/BYekan.ttf +0 -0
- assets/fonts/BYekan.woff +0 -0
- assets/fonts/LICENSE +51 -0
- assets/fonts/Shabnam.eot +0 -0
- assets/fonts/Shabnam.ttf +0 -0
- assets/fonts/Shabnam.woff +0 -0
- assets/fonts/Shabnam.woff2 +0 -0
- assets/fonts/Vazir.eot +0 -0
- assets/fonts/Vazir.ttf +0 -0
- assets/fonts/Vazir.woff +0 -0
- assets/fonts/Vazir.woff2 +0 -0
- assets/images/Gravity_Forms_fa.png +0 -0
- assets/images/logo.png +0 -0
- assets/js/iran-cities-full.js +0 -0
- assets/js/iran-cities-full.min.js +0 -0
- assets/js/{jalali.date.picker.js → jalali-datepicker.js} +0 -0
- assets/js/melli-code.js +0 -539
- assets/js/melli-code.min.js +0 -1
- assets/js/national_id.js +546 -0
- assets/js/national_id.min.js +1 -0
- assets/js/shamsi_chart.js +0 -0
- includes/{class-iran-cities.php → class-address.php} +97 -101
- includes/class-admin.php +131 -0
- includes/class-core.php +198 -0
- includes/class-currencies.php +71 -0
- includes/class-deprecated.php +657 -0
- includes/class-jalali-date.php +133 -252
- includes/class-live-preview.php +148 -142
- includes/class-melli-code.php +0 -434
- includes/class-merge-tag.php +672 -0
- includes/class-multi-page-navi.php +167 -0
- includes/class-multipage-navigation.php +0 -160
- includes/class-national-id.php +434 -0
- includes/class-news-letter.php +0 -50
- includes/class-payments.php +499 -0
- includes/class-post-content-merge-tags.php +0 -249
- includes/class-pre-submission.php +0 -194
- includes/class-settings.php +418 -0
- includes/class-snippets.php +62 -73
- includes/class-subtotal-calc.php +0 -245
- includes/class-transaction-id.php +58 -0
- includes/class-wpp-gravity-forms.php +0 -116
- includes/lib/jalali.php +755 -0
- includes/lib/nusoap-php5.3.php +8484 -0
- includes/lib/nusoap-php7.php +7208 -0
assets/css/admin.rtl.css
DELETED
@@ -1,69 +0,0 @@
|
|
1 |
-
#gf_merge_tag_list a{
|
2 |
-
font-family:tahoma !important;
|
3 |
-
}
|
4 |
-
#toplevel_page_gf_edit_forms a,#toplevel_page_gf_edit_forms .wp-menu-name,.newform_notice,.gatewayset p,.gatewayset td,h1,h2,h3,h4,h5,h6,h2 span,h3 span,label,#no-fields span,.group-header,#gf_form_toolbar a,.gform_tabs a,td a,td a strong,td strong a,th,.add-new-h2,.button,.stat b,.gresults-chart-wrapper *,div.gresults-results-filter-section-label,div.gresults-results-field-label,#gresults-results td,#gresults-results th,#gresults-results tr,h2 a{
|
5 |
-
font-weight:normal !important;
|
6 |
-
}
|
7 |
-
h4,h5,h6 {
|
8 |
-
font-size:16px !important;
|
9 |
-
}
|
10 |
-
.group-header {
|
11 |
-
font-size:16px !important;
|
12 |
-
font-weight:normal !important;
|
13 |
-
}
|
14 |
-
.row-title,#toplevel_page_gf_edit_forms .wp-menu-name,.newform_notice{
|
15 |
-
font-size:16px !important;
|
16 |
-
}
|
17 |
-
a.gf_toolbar_active ,.gform_tabs a,label{
|
18 |
-
font-size:13px !important;
|
19 |
-
}
|
20 |
-
div.gf_entry_detail_pagination {
|
21 |
-
top:-10px !important;
|
22 |
-
}
|
23 |
-
#TB_ajaxContent,#TB_title {
|
24 |
-
text-align:right !important;
|
25 |
-
}
|
26 |
-
#gresults-results{
|
27 |
-
margin-right:0px !important;
|
28 |
-
margin-left:300px !important;
|
29 |
-
}
|
30 |
-
div#gf_nofield_1_instructions, div#gf_nofield_2_instructions, div#gf_nofield_3_instructions, div#gf_nofield_4_instructions, div#gf_nofield_5_instructions {
|
31 |
-
background-image: url("../images/Gravity_Forms_fa.png") !important;
|
32 |
-
}
|
33 |
-
.gf_nofield_3_instructions_copy_bottom {
|
34 |
-
margin-left:-163px !important;
|
35 |
-
}
|
36 |
-
.gf_nofield_4_instructions_copy_bottom {
|
37 |
-
margin-top:13px !important;
|
38 |
-
margin-left:-220px !important;
|
39 |
-
}
|
40 |
-
#gf_user_form .left_header ,.metaname , .metavalue{
|
41 |
-
float:right !important;
|
42 |
-
}
|
43 |
-
.gf_dashboard_form_title_header{
|
44 |
-
text-align:right !important;
|
45 |
-
}
|
46 |
-
.gf_dashboard_view td i{
|
47 |
-
font-style:normal !important;
|
48 |
-
}
|
49 |
-
.gfur-form-select {
|
50 |
-
margin-right:415px !important;
|
51 |
-
}
|
52 |
-
optgroup {
|
53 |
-
font-style:normal !important;
|
54 |
-
}
|
55 |
-
.choice_with_value_and_price label {
|
56 |
-
margin: 0 60px 0 0 !important;
|
57 |
-
padding-left: 26px !important;
|
58 |
-
}
|
59 |
-
.choice_with_price .gfield_choice_header_label ,.choice_with_value .gfield_choice_header_label {
|
60 |
-
margin: 0 69px 0 99px !important;
|
61 |
-
}
|
62 |
-
.ui-tabs .ui-tabs-nav li {
|
63 |
-
margin-left: 0.2em !important;
|
64 |
-
margin-right: 0 !important;
|
65 |
-
float: right !important;
|
66 |
-
}
|
67 |
-
div#gf_nofield_1_instructions span, div#gf_nofield_2_instructions span, div#gf_nofield_3_instructions span, div#gf_nofield_4_instructions span, div#gf_nofield_5_instructions span {
|
68 |
-
line-height: 2.5rem !important;
|
69 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/font-admin.css
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*, body, html {
|
2 |
+
font-family: tahoma, serif;
|
3 |
+
}
|
4 |
+
|
5 |
+
input, li, ul, select, textarea, #gf_merge_tag_list a {
|
6 |
+
font-family: tahoma, serif !important;
|
7 |
+
}
|
8 |
+
|
9 |
+
#toplevel_page_gf_edit_forms a,
|
10 |
+
#toplevel_page_gf_edit_forms .wp-menu-name,
|
11 |
+
.newform_notice, .gatewayset p,
|
12 |
+
.gatewayset td, h1, h2, h3, h4, h5, h6, h2 span, h3 span, label,
|
13 |
+
#no-fields span, .group-header, #gf_form_toolbar a, .gform_tabs a, td a, td a strong, td strong a, th,
|
14 |
+
.add-new-h2, .button, .stat b, .gresults-chart-wrapper *, div.gresults-results-filter-section-label,
|
15 |
+
div.gresults-results-field-label, #gresults-results td, #gresults-results th, #gresults-results tr, h2 a,
|
16 |
+
.field_hover div.gf-pagebreak-container div.gf-pagebreak-text-main span,
|
17 |
+
.field_selected div.gf-pagebreak-container div.gf-pagebreak-text-main span,
|
18 |
+
.gf-pagebreak-text-after,
|
19 |
+
.gf-pagebreak-text-before, div.gf-pagebreak-text-main span,
|
20 |
+
.field_type li input, .add-buttons-title,
|
21 |
+
.field_type li input, .add-buttons-title,
|
22 |
+
.entry-detail-view td, .entry-detail-view td *,
|
23 |
+
.gf_dashboard_view td i,
|
24 |
+
.gforms_settings_wrap td, .gforms_settings_wrap th, .gforms_settings_wrap th strong, .gforms_settings_wrap td strong,
|
25 |
+
#entry_list_form tbody *{
|
26 |
+
font-family: GFPersian, serif !important;
|
27 |
+
}
|
assets/css/font-face-shabnam.css
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@font-face {
|
2 |
+
font-family: 'GFPersian';
|
3 |
+
src: url('../fonts/Shabnam.eot');
|
4 |
+
src: url('../fonts/Shabnam.woff') format('woff'), url('../fonts/Shabnam.ttf') format('truetype');
|
5 |
+
font-weight: normal;
|
6 |
+
font-style: normal;
|
7 |
+
}
|
assets/css/font-face-vazir.css
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@font-face {
|
2 |
+
font-family: 'GFPersian';
|
3 |
+
src: url('../fonts/Vazir.eot');
|
4 |
+
src: url('../fonts/Vazir.woff') format('woff'), url('../fonts/Vazir.ttf') format('truetype');
|
5 |
+
font-weight: normal;
|
6 |
+
font-style: normal;
|
7 |
+
}
|
assets/css/font-face-yekan.css
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@font-face {
|
2 |
+
font-family: 'GFPersian';
|
3 |
+
src: url('../fonts/BYekan.eot');
|
4 |
+
src: url('../fonts/BYekan.woff') format('woff'), url('../fonts/BYekan.ttf') format('truetype');
|
5 |
+
font-weight: normal;
|
6 |
+
font-style: normal;
|
7 |
+
}
|
assets/css/font.droidsans.css
DELETED
@@ -1,16 +0,0 @@
|
|
1 |
-
#toplevel_page_gf_edit_forms a,#toplevel_page_gf_edit_forms .wp-menu-name,.newform_notice,.gatewayset p,.gatewayset td,h1,h2,h3,h4,h5,h6,h2 span,h3 span,label,#no-fields span,.group-header,#gf_form_toolbar a,.gform_tabs a,td a,td a strong,td strong a,th,.add-new-h2,.button,.stat b,.gresults-chart-wrapper *,div.gresults-results-filter-section-label,div.gresults-results-field-label,#gresults-results td,#gresults-results th,#gresults-results tr,h2 a{
|
2 |
-
font-family:DroidNaskh !important;
|
3 |
-
font-weight:normal !important;
|
4 |
-
}
|
5 |
-
.field_hover div.gf-pagebreak-container div.gf-pagebreak-text-main span, .field_selected div.gf-pagebreak-container div.gf-pagebreak-text-main span ,.gf-pagebreak-text-after, .gf-pagebreak-text-before,div.gf-pagebreak-text-main span{
|
6 |
-
font-family:DroidNaskh !important;
|
7 |
-
}
|
8 |
-
.field_type li input,.add-buttons-title{
|
9 |
-
font-family:DroidNaskh !important;
|
10 |
-
}
|
11 |
-
.field_type li input,.add-buttons-title{
|
12 |
-
font-family:DroidNaskh !important;
|
13 |
-
}
|
14 |
-
.gf_dashboard_view td i{
|
15 |
-
font-family:DroidNaskh !important;
|
16 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/font.yekan.css
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
@font-face {
|
2 |
-
font-family: 'BYekan';
|
3 |
-
src: url('../fonts/BYekan.eot');
|
4 |
-
src: url('../fonts/BYekan.woff') format('woff'), url('../fonts/BYekan.ttf') format('truetype');
|
5 |
-
font-weight: normal;
|
6 |
-
font-style: normal;
|
7 |
-
}
|
8 |
-
*,body,html {
|
9 |
-
font-family:tahoma;
|
10 |
-
}
|
11 |
-
input,li,ul,select,textarea,#gf_merge_tag_list a{
|
12 |
-
font-family:tahoma !important;
|
13 |
-
}
|
14 |
-
#toplevel_page_gf_edit_forms a,#toplevel_page_gf_edit_forms .wp-menu-name,.newform_notice,.gatewayset p,.gatewayset td,h1,h2,h3,h4,h5,h6,h2 span,h3 span,label,#no-fields span,.group-header,#gf_form_toolbar a,.gform_tabs a,td a,td a strong,td strong a,th,.add-new-h2,.button,.stat b,.gresults-chart-wrapper *,div.gresults-results-filter-section-label,div.gresults-results-field-label,#gresults-results td,#gresults-results th,#gresults-results tr,h2 a{
|
15 |
-
font-family:BYekan !important;
|
16 |
-
font-weight:normal !important;
|
17 |
-
}
|
18 |
-
.field_hover div.gf-pagebreak-container div.gf-pagebreak-text-main span, .field_selected div.gf-pagebreak-container div.gf-pagebreak-text-main span ,.gf-pagebreak-text-after, .gf-pagebreak-text-before,div.gf-pagebreak-text-main span{
|
19 |
-
font-family:BYekan !important;
|
20 |
-
}
|
21 |
-
.field_type li input,.add-buttons-title{
|
22 |
-
font-family:BYekan !important;
|
23 |
-
}
|
24 |
-
.field_type li input,.add-buttons-title{
|
25 |
-
font-family:BYekan !important;
|
26 |
-
}
|
27 |
-
.gf_dashboard_view td i{
|
28 |
-
font-family:BYekan !important;
|
29 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/css/print.rtl.css
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
*,html,body,table,thead,tr,th,td,div {direction: rtl !important;text-align: right !important;font-family:Tahoma !important;}
|
|
assets/css/rtl-admin.css
ADDED
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#gf_merge_tag_list a {
|
2 |
+
font-family: tahoma, serif !important;
|
3 |
+
}
|
4 |
+
|
5 |
+
#toplevel_page_gf_edit_forms a, #toplevel_page_gf_edit_forms .wp-menu-name, .newform_notice, .gatewayset p, .gatewayset td, h1, h2, h3, h4, h5, h6, h2 span, h3 span, label, #no-fields span, .group-header, #gf_form_toolbar a, .gform_tabs a, td a, td a strong, td strong a, th, .add-new-h2, .button, .stat b, .gresults-chart-wrapper *, div.gresults-results-filter-section-label, div.gresults-results-field-label, #gresults-results td, #gresults-results th, #gresults-results tr, h2 a {
|
6 |
+
font-weight: normal !important;
|
7 |
+
}
|
8 |
+
|
9 |
+
h4, h5, h6 {
|
10 |
+
font-size: 16px !important;
|
11 |
+
}
|
12 |
+
|
13 |
+
.group-header {
|
14 |
+
font-size: 16px !important;
|
15 |
+
font-weight: normal !important;
|
16 |
+
}
|
17 |
+
|
18 |
+
.row-title, #toplevel_page_gf_edit_forms .wp-menu-name, .newform_notice {
|
19 |
+
font-size: 16px !important;
|
20 |
+
}
|
21 |
+
|
22 |
+
a.gf_toolbar_active, .gform_tabs a, label {
|
23 |
+
font-size: 13px !important;
|
24 |
+
}
|
25 |
+
|
26 |
+
div.gf_entry_detail_pagination {
|
27 |
+
top: -10px !important;
|
28 |
+
}
|
29 |
+
|
30 |
+
#TB_ajaxContent, #TB_title {
|
31 |
+
text-align: right !important;
|
32 |
+
}
|
33 |
+
|
34 |
+
#gresults-results {
|
35 |
+
margin-right: 0px !important;
|
36 |
+
margin-left: 300px !important;
|
37 |
+
}
|
38 |
+
|
39 |
+
div#gf_nofield_1_instructions, div#gf_nofield_2_instructions, div#gf_nofield_3_instructions, div#gf_nofield_4_instructions, div#gf_nofield_5_instructions {
|
40 |
+
background-image: url("../images/Gravity_Forms_fa.png") !important;
|
41 |
+
}
|
42 |
+
|
43 |
+
.gf_nofield_3_instructions_copy_bottom {
|
44 |
+
margin-left: -163px !important;
|
45 |
+
}
|
46 |
+
|
47 |
+
.gf_nofield_4_instructions_copy_bottom {
|
48 |
+
margin-top: 13px !important;
|
49 |
+
margin-left: -220px !important;
|
50 |
+
}
|
51 |
+
|
52 |
+
#gf_user_form .left_header, .metaname, .metavalue {
|
53 |
+
float: right !important;
|
54 |
+
}
|
55 |
+
|
56 |
+
.gf_dashboard_form_title_header {
|
57 |
+
text-align: right !important;
|
58 |
+
}
|
59 |
+
|
60 |
+
.gf_dashboard_view td i {
|
61 |
+
font-style: normal !important;
|
62 |
+
}
|
63 |
+
|
64 |
+
.gfur-form-select {
|
65 |
+
margin-right: 415px !important;
|
66 |
+
}
|
67 |
+
|
68 |
+
optgroup {
|
69 |
+
font-style: normal !important;
|
70 |
+
}
|
71 |
+
|
72 |
+
.choice_with_value_and_price label {
|
73 |
+
margin: 0 60px 0 0 !important;
|
74 |
+
padding-left: 26px !important;
|
75 |
+
}
|
76 |
+
|
77 |
+
.choice_with_price .gfield_choice_header_label, .choice_with_value .gfield_choice_header_label {
|
78 |
+
margin: 0 69px 0 99px !important;
|
79 |
+
}
|
80 |
+
|
81 |
+
.ui-tabs .ui-tabs-nav li {
|
82 |
+
margin-left: 0.2em !important;
|
83 |
+
margin-right: 0 !important;
|
84 |
+
float: right !important;
|
85 |
+
}
|
86 |
+
|
87 |
+
div#gf_nofield_1_instructions span, div#gf_nofield_2_instructions span, div#gf_nofield_3_instructions span, div#gf_nofield_4_instructions span, div#gf_nofield_5_instructions span {
|
88 |
+
line-height: 2.5rem !important;
|
89 |
+
}
|
90 |
+
|
91 |
+
.calculation_setting .gf_calculation_buttons input, html[dir="rtl"] body.wp-admin .calculation_setting .gf_calculation_buttons input,
|
92 |
+
.calculation_setting textarea, html[dir="rtl"] body.wp-admin .calculation_setting textarea,
|
93 |
+
.css_class_setting input, html[dir="rtl"] body.wp-admin .css_class_setting input,
|
94 |
+
.prepopulate_field_setting input, html[dir="rtl"] body.wp-admin .prepopulate_field_setting input,
|
95 |
+
#form_page_querystring {
|
96 |
+
direction: ltr !important;
|
97 |
+
text-align: left !important;
|
98 |
+
}
|
99 |
+
|
100 |
+
.mt-gform_notification_message, .mt-form_confirmation_message {
|
101 |
+
margin-right: -30px !important;
|
102 |
+
}
|
103 |
+
|
104 |
+
.entry-detail-view td ul {
|
105 |
+
padding-right: 15px;
|
106 |
+
}
|
107 |
+
|
108 |
+
#entry_filters {
|
109 |
+
float: right;
|
110 |
+
}
|
111 |
+
|
112 |
+
#entry_search_button {
|
113 |
+
float: left;
|
114 |
+
}
|
115 |
+
|
116 |
+
#entry_list_form .subsubsub {
|
117 |
+
float: right !important;
|
118 |
+
clear: both;
|
119 |
+
}
|
120 |
+
|
121 |
+
#edit_payment_status_details * {
|
122 |
+
font-size: 12px !important;
|
123 |
+
}
|
124 |
+
|
125 |
+
#notes .actions input.button {
|
126 |
+
width: 100px !important;
|
127 |
+
}
|
assets/css/rtl-print.css
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*, html, body, table, thead, tr, th, td, div {
|
2 |
+
direction: rtl !important;
|
3 |
+
text-align: right !important;
|
4 |
+
font-family: Tahoma, serif;
|
5 |
+
}
|
6 |
+
ul {
|
7 |
+
padding-right: 10px !important;
|
8 |
+
}
|
9 |
+
|
10 |
+
div.note-avatar {
|
11 |
+
margin-left: 15px;
|
12 |
+
float: right;
|
13 |
+
}
|
assets/fonts/BYekan.eot
CHANGED
File without changes
|
assets/fonts/BYekan.ttf
CHANGED
File without changes
|
assets/fonts/BYekan.woff
CHANGED
File without changes
|
assets/fonts/LICENSE
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Changes by Saber Rastikerdar are in public domain.
|
2 |
+
Glyphs and data from Roboto font are licensed under the Apache License, Version 2.0.
|
3 |
+
|
4 |
+
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
5 |
+
|
6 |
+
Bitstream Vera Fonts Copyright
|
7 |
+
------------------------------
|
8 |
+
|
9 |
+
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
10 |
+
a trademark of Bitstream, Inc.
|
11 |
+
|
12 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 |
+
of the fonts accompanying this license ("Fonts") and associated
|
14 |
+
documentation files (the "Font Software"), to reproduce and distribute the
|
15 |
+
Font Software, including without limitation the rights to use, copy, merge,
|
16 |
+
publish, distribute, and/or sell copies of the Font Software, and to permit
|
17 |
+
persons to whom the Font Software is furnished to do so, subject to the
|
18 |
+
following conditions:
|
19 |
+
|
20 |
+
The above copyright and trademark notices and this permission notice shall
|
21 |
+
be included in all copies of one or more of the Font Software typefaces.
|
22 |
+
|
23 |
+
The Font Software may be modified, altered, or added to, and in particular
|
24 |
+
the designs of glyphs or characters in the Fonts may be modified and
|
25 |
+
additional glyphs or characters may be added to the Fonts, only if the fonts
|
26 |
+
are renamed to names not containing either the words "Bitstream" or the word
|
27 |
+
"Vera".
|
28 |
+
|
29 |
+
This License becomes null and void to the extent applicable to Fonts or Font
|
30 |
+
Software that has been modified and is distributed under the "Bitstream
|
31 |
+
Vera" names.
|
32 |
+
|
33 |
+
The Font Software may be sold as part of a larger software package but no
|
34 |
+
copy of one or more of the Font Software typefaces may be sold by itself.
|
35 |
+
|
36 |
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
37 |
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
38 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
39 |
+
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
40 |
+
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
41 |
+
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
42 |
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
43 |
+
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
44 |
+
FONT SOFTWARE.
|
45 |
+
|
46 |
+
Except as contained in this notice, the names of Gnome, the Gnome
|
47 |
+
Foundation, and Bitstream Inc., shall not be used in advertising or
|
48 |
+
otherwise to promote the sale, use or other dealings in this Font Software
|
49 |
+
without prior written authorization from the Gnome Foundation or Bitstream
|
50 |
+
Inc., respectively. For further information, contact: fonts at gnome dot
|
51 |
+
org.
|
assets/fonts/Shabnam.eot
ADDED
Binary file
|
assets/fonts/Shabnam.ttf
ADDED
Binary file
|
assets/fonts/Shabnam.woff
ADDED
Binary file
|
assets/fonts/Shabnam.woff2
ADDED
Binary file
|
assets/fonts/Vazir.eot
ADDED
Binary file
|
assets/fonts/Vazir.ttf
ADDED
Binary file
|
assets/fonts/Vazir.woff
ADDED
Binary file
|
assets/fonts/Vazir.woff2
ADDED
Binary file
|
assets/images/Gravity_Forms_fa.png
CHANGED
File without changes
|
assets/images/logo.png
ADDED
Binary file
|
assets/js/iran-cities-full.js
CHANGED
File without changes
|
assets/js/iran-cities-full.min.js
CHANGED
File without changes
|
assets/js/{jalali.date.picker.js → jalali-datepicker.js}
RENAMED
File without changes
|
assets/js/melli-code.js
DELETED
@@ -1,539 +0,0 @@
|
|
1 |
-
function cityName_by_melliCode_hannanstd (code){
|
2 |
-
if (code == "169")cityN = "استان آذربایجان شرقی - شهر آذر شهر";
|
3 |
-
if (code == "170")cityN = "استان آذربایجان شرقی - شهر اسکو";
|
4 |
-
if (code == "149" || code == "150")cityN = "استان آذربایجان شرقی - شهر اهر";
|
5 |
-
if (code == "171")cityN = "استان آذربایجان شرقی - شهر بستان آباد";
|
6 |
-
if (code == "168")cityN = "استان آذربایجان شرقی - شهر بناب";
|
7 |
-
if (code == "136" || code == "137" || code == "138")cityN = "استان آذربایجان شرقی - شهر تبریز";
|
8 |
-
if (code == "545")cityN = "استان آذربایجان شرقی - شهر ترکمانچای";
|
9 |
-
if (code == "505")cityN = "استان آذربایجان شرقی - شهر جلفا";
|
10 |
-
if (code == "636")cityN = "استان آذربایجان شرقی - شهر چاروایماق";
|
11 |
-
if (code == "164" || code == "165")cityN = "استان آذربایجان شرقی - شهر سراب";
|
12 |
-
if (code == "172")cityN = "استان آذربایجان شرقی - شهر شبستر";
|
13 |
-
if (code == "623")cityN = "استان آذربایجان شرقی - شهر صوفیان";
|
14 |
-
if (code == "506")cityN = "استان آذربایجان شرقی - شهر عجب شیر";
|
15 |
-
if (code == "519")cityN = "استان آذربایجان شرقی - شهر کلیبر";
|
16 |
-
if (code == "154" || code == "155")cityN = "استان آذربایجان شرقی - شهر مراغه";
|
17 |
-
if (code == "567")cityN = "استان آذربایجان شرقی - شهر ورزقان";
|
18 |
-
if (code == "173")cityN = "استان آذربایجان شرقی - شهر هریس";
|
19 |
-
if (code == "159" || code == "160")cityN = "استان آذربایجان شرقی - شهر هشترود";
|
20 |
-
if (code == "604")cityN = "استان آذربایجان شرقی - شهر هوراند";
|
21 |
-
if (code == "274" || code == "275")cityN = "استان آذربایجان غربی - شهر ارومیه";
|
22 |
-
if (code == "295")cityN = "استان آذربایجان غربی - شهر اشنویه";
|
23 |
-
if (code == "637")cityN = "استان آذربایجان غربی - شهر انزل";
|
24 |
-
if (code == "292")cityN = "استان آذربایجان غربی - شهر بوکان";
|
25 |
-
if (code == "492")cityN = "استان آذربایجان غربی - شهر پلدشت";
|
26 |
-
if (code == "289")cityN = "استان آذربایجان غربی - شهر پیرانشهر";
|
27 |
-
if (code == "677")cityN = "استان آذربایجان غربی - شهر تخت سلیمان";
|
28 |
-
if (code == "294")cityN = "استان آذربایجان غربی - شهر تکاب";
|
29 |
-
if (code == "493")cityN = "استان آذربایجان غربی - شهر چایپاره";
|
30 |
-
if (code == "279" || code == "280")cityN = "استان آذربایجان غربی - شهر خوی";
|
31 |
-
if (code == "288")cityN = "استان آذربایجان غربی - شهر سردشت";
|
32 |
-
if (code == "284" || code == "285")cityN = "استان آذربایجان غربی - شهر سلماس";
|
33 |
-
if (code == "638")cityN = "استان آذربایجان غربی - شهر سیلوانه";
|
34 |
-
if (code == "291")cityN = "استان آذربایجان غربی - شهر سیه چشمه(چالدران)";
|
35 |
-
if (code == "640")cityN = "استان آذربایجان غربی - شهر شوط";
|
36 |
-
if (code == "293")cityN = "استان آذربایجان غربی - شهر شاهین دژ";
|
37 |
-
if (code == "675")cityN = "استان آذربایجان غربی - شهر کشاورز";
|
38 |
-
if (code == "282" || code == "283")cityN = "استان آذربایجان غربی - شهر ماکو";
|
39 |
-
if (code == "286" || code == "287")cityN = "استان آذربایجان غربی - شهر مهاباد";
|
40 |
-
if (code == "296" || code == "297")cityN = "استان آذربایجان غربی - شهر میاندوآب";
|
41 |
-
if (code == "290")cityN = "استان آذربایجان غربی - شهر نقده";
|
42 |
-
if (code == "400" || code == "401")cityN = "استان همدان - شهر اسدآباد";
|
43 |
-
if (code == "404" || code == "405")cityN = "استان همدان - شهر بهار";
|
44 |
-
if (code == "397")cityN = "استان همدان - شهر تویسرکان";
|
45 |
-
if (code == "398" || code == "399")cityN = "استان همدان - شهر رزن";
|
46 |
-
if (code == "647")cityN = "استان همدان - شهر شراء و پیشخوار";
|
47 |
-
if (code == "502")cityN = "استان همدان - شهر فامنین";
|
48 |
-
if (code == "584")cityN = "استان همدان - شهر قلقل رود";
|
49 |
-
if (code == "402" || code == "403")cityN = "استان همدان - شهر کبودرآهنگ";
|
50 |
-
if (code == "392" || code == "393")cityN = "استان همدان - شهر ملایر";
|
51 |
-
if (code == "395" || code == "396")cityN = "استان همدان - شهر نهاوند";
|
52 |
-
if (code == "386" || code == "387")cityN = "استان همدان - شهر همدان";
|
53 |
-
if (code == "503")cityN = "استان یزد - شهر ابرکوه";
|
54 |
-
if (code == "444")cityN = "استان یزد - شهر اردکان";
|
55 |
-
if (code == "551")cityN = "استان یزد - شهر اشکذر";
|
56 |
-
if (code == "447")cityN = "استان یزد - شهر بافق";
|
57 |
-
if (code == "561")cityN = "استان یزد - شهر بهاباد";
|
58 |
-
if (code == "445")cityN = "استان یزد - شهر تفت";
|
59 |
-
if (code == "718")cityN = "استان یزد - شهر دستگردان";
|
60 |
-
if (code == "083")cityN = "استان یزد - شهر طبس";
|
61 |
-
if (code == "446")cityN = "استان یزد - شهر مهریز";
|
62 |
-
if (code == "448")cityN = "استان یزد - شهر میبد";
|
63 |
-
if (code == "552")cityN = "استان یزد - شهر نیر";
|
64 |
-
if (code == "543")cityN = "استان یزد - شهر هرات و مروست";
|
65 |
-
if (code == "442" || code == "443")cityN = "استان یزد - شهر یزد";
|
66 |
-
if (code == "051")cityN = "استان مرکزی - شهر آشتیان";
|
67 |
-
if (code == "052" || code == "053")cityN = "استان مرکزی - شهر اراک";
|
68 |
-
if (code == "058")cityN = "استان مرکزی - شهر تفرش";
|
69 |
-
if (code == "055")cityN = "استان مرکزی - شهر خمین";
|
70 |
-
if (code == "617")cityN = "استان مرکزی - شهر خنداب";
|
71 |
-
if (code == "057")cityN = "استان مرکزی - شهر دلیجان";
|
72 |
-
if (code == "618")cityN = "استان مرکزی - شهر زرند مرکزی";
|
73 |
-
if (code == "059" || code == "060")cityN = "استان مرکزی - شهر ساوه";
|
74 |
-
if (code == "061" || code == "062")cityN = "استان مرکزی - شهر سربند";
|
75 |
-
if (code == "544")cityN = "استان مرکزی - شهر فراهان";
|
76 |
-
if (code == "056")cityN = "استان مرکزی - شهر محلات";
|
77 |
-
if (code == "571")cityN = "استان مرکزی - شهر وفس";
|
78 |
-
if (code == "593")cityN = "استان مرکزی - شهر هندودر";
|
79 |
-
if (code == "667")cityN = "استان هرمزگان - شهر ابوموسی";
|
80 |
-
if (code == "348")cityN = "استان هرمزگان - شهر بستک";
|
81 |
-
if (code == "586")cityN = "استان هرمزگان - شهر بشاگرد";
|
82 |
-
if (code == "338" || code == "339")cityN = "استان هرمزگان - شهر بندرعباس";
|
83 |
-
if (code == "343" || code == "344")cityN = "استان هرمزگان - شهر بندرلنگه";
|
84 |
-
if (code == "346")cityN = "استان هرمزگان - شهر جاسک";
|
85 |
-
if (code == "337")cityN = "استان هرمزگان - شهر حاجی آباد";
|
86 |
-
if (code == "554")cityN = "استان هرمزگان - شهر خمیر";
|
87 |
-
if (code == "469")cityN = "استان هرمزگان - شهر رودان";
|
88 |
-
if (code == "537")cityN = "استان هرمزگان - شهر فین";
|
89 |
-
if (code == "345")cityN = "استان هرمزگان - شهر قشم";
|
90 |
-
if (code == "470")cityN = "استان هرمزگان - شهر گاوبندی";
|
91 |
-
if (code == "341" || code == "342")cityN = "استان هرمزگان - شهر میناب";
|
92 |
-
if (code == "483" || code == "484")cityN = "استان لرستان - شهر ازنا";
|
93 |
-
if (code == "557")cityN = "استان لرستان - شهر اشترینان";
|
94 |
-
if (code == "418")cityN = "استان لرستان - شهر الشتر";
|
95 |
-
if (code == "416" || code == "417")cityN = "استان لرستان - شهر الیگودرز";
|
96 |
-
if (code == "412" || code == "413")cityN = "استان لرستان - شهر بروجرد";
|
97 |
-
if (code == "592")cityN = "استان لرستان - شهر پاپی";
|
98 |
-
if (code == "612")cityN = "استان لرستان - شهر چغلوندی";
|
99 |
-
if (code == "613")cityN = "استان لرستان - شهر چگنی";
|
100 |
-
if (code == "406" || code == "407")cityN = "استان لرستان - شهر خرم آباد";
|
101 |
-
if (code == "421")cityN = "استان لرستان - شهر دورود";
|
102 |
-
if (code == "598")cityN = "استان لرستان - شهر رومشکان";
|
103 |
-
if (code == "419")cityN = "استان لرستان - شهر کوهدشت";
|
104 |
-
if (code == "385")cityN = "استان لرستان - شهر ملاوی(پلدختر)";
|
105 |
-
if (code == "420")cityN = "استان لرستان - شهر نورآباد(دلفان)";
|
106 |
-
if (code == "528")cityN = "استان لرستان - شهر ویسیان";
|
107 |
-
if (code == "213" || code == "214")cityN = "استان مازندران - شهر آمل";
|
108 |
-
if (code == "205" || code == "206")cityN = "استان مازندران - شهر بابل";
|
109 |
-
if (code == "498")cityN = "استان مازندران - شهر بابل";
|
110 |
-
if (code == "568")cityN = "استان مازندران - شهر بندپی";
|
111 |
-
if (code == "711")cityN = "استان مازندران - شهر بندپی شرقی";
|
112 |
-
if (code == "217" || code == "218")cityN = "استان مازندران - شهر بهشهر";
|
113 |
-
if (code == "221")cityN = "استان مازندران - شهر تنکابن";
|
114 |
-
if (code == "582")cityN = "استان مازندران - شهر جویبار";
|
115 |
-
if (code == "483")cityN = "استان مازندران - شهر چالوس";
|
116 |
-
if (code == "625")cityN = "استان مازندران - شهر چمستان";
|
117 |
-
if (code == "576")cityN = "استان مازندران - شهر چهاردانگه";
|
118 |
-
if (code == "578")cityN = "استان مازندران - شهر دودانگه";
|
119 |
-
if (code == "227")cityN = "استان مازندران - شهر رامسر";
|
120 |
-
if (code == "208" || code == "209")cityN = "استان مازندران - شهر ساری";
|
121 |
-
if (code == "225")cityN = "استان مازندران - شهر سوادکوه";
|
122 |
-
if (code == "577")cityN = "استان مازندران - شهر شیرگاه";
|
123 |
-
if (code == "712")cityN = "استان مازندران - شهر عباس آباد";
|
124 |
-
if (code == "215" || code == "216")cityN = "استان مازندران - شهر قائمشهر";
|
125 |
-
if (code == "626")cityN = "استان مازندران - شهر کجور";
|
126 |
-
if (code == "627")cityN = "استان مازندران - شهر کلاردشت";
|
127 |
-
if (code == "579")cityN = "استان مازندران - شهر گلوگاه";
|
128 |
-
if (code == "713")cityN = "استان مازندران - شهر میاندورود";
|
129 |
-
if (code == "499")cityN = "استان مازندران - شهر نکاء";
|
130 |
-
if (code == "222")cityN = "استان مازندران - شهر نور";
|
131 |
-
if (code == "219" || code == "220")cityN = "استان مازندران - شهر نوشهر";
|
132 |
-
if (code == "500" || code == "501")cityN = "استان مازندران - شهر هراز و محمودآباد";
|
133 |
-
if (code == "623")cityN = "استان گلستان - شهر آزادشهر";
|
134 |
-
if (code == "497")cityN = "استان گلستان - شهر آق قلا";
|
135 |
-
if (code == "223")cityN = "استان گلستان - شهر بندرترکمن";
|
136 |
-
if (code == "689")cityN = "استان گلستان - شهر بندرگز";
|
137 |
-
if (code == "487")cityN = "استان گلستان - شهر رامیان";
|
138 |
-
if (code == "226")cityN = "استان گلستان - شهر علی آباد";
|
139 |
-
if (code == "224")cityN = "استان گلستان - شهر کردکوی";
|
140 |
-
if (code == "386")cityN = "استان گلستان - شهر کلاله";
|
141 |
-
if (code == "211" || code == "212")cityN = "استان گلستان - شهر گرگان";
|
142 |
-
if (code == "628")cityN = "استان گلستان - شهر گمیشان";
|
143 |
-
if (code == "202" || code == "203")cityN = "استان گلستان - شهر گنبد کاووس";
|
144 |
-
if (code == "531")cityN = "استان گلستان - شهر مراوه تپه";
|
145 |
-
if (code == "288")cityN = "استان گلستان - شهر مینودشت";
|
146 |
-
if (code == "261")cityN = "استان گیلان - شهر آستارا";
|
147 |
-
if (code == "273")cityN = "استان گیلان - شهر آستانه";
|
148 |
-
if (code == "630")cityN = "استان گیلان - شهر املش";
|
149 |
-
if (code == "264")cityN = "استان گیلان - شهر بندرانزلی";
|
150 |
-
if (code == "518")cityN = "استان گیلان - شهر خمام";
|
151 |
-
if (code == "631")cityN = "استان گیلان - شهر رحیم آباد";
|
152 |
-
if (code == "258" || code == "259")cityN = "استان گیلان - شهر رشت";
|
153 |
-
if (code == "570")cityN = "استان گیلان - شهر رضوانشهر";
|
154 |
-
if (code == "265")cityN = "استان گیلان - شهر رودبار";
|
155 |
-
if (code == "268" || code == "269")cityN = "استان گیلان - شهر رودسر";
|
156 |
-
if (code == "653")cityN = "استان گیلان - شهر سنگر";
|
157 |
-
if (code == "517")cityN = "استان گیلان - شهر سیاهکل";
|
158 |
-
if (code == "569")cityN = "استان گیلان - شهر شفت";
|
159 |
-
if (code == "267")cityN = "استان گیلان - شهر صومعه سرا";
|
160 |
-
if (code == "262" || code == "263")cityN = "استان گیلان - شهر طالش";
|
161 |
-
if (code == "593")cityN = "استان گیلان - شهر عمارلو";
|
162 |
-
if (code == "266")cityN = "استان گیلان - شهر فومن";
|
163 |
-
if (code == "693")cityN = "استان گیلان - شهر کوچصفهان";
|
164 |
-
if (code == "271" || code == "272")cityN = "استان گیلان - شهر لاهیجان";
|
165 |
-
if (code == "694")cityN = "استان گیلان - شهر لشت نشاء";
|
166 |
-
if (code == "270")cityN = "استان گیلان - شهر لنگرود";
|
167 |
-
if (code == "516")cityN = "استان گیلان - شهر ماسال و شاندرمن";
|
168 |
-
if (code == "333" || code == "334")cityN = "استان کرمانشاه - شهر اسلام آباد";
|
169 |
-
if (code == "691")cityN = "استان کرمانشاه - شهر باینگان";
|
170 |
-
if (code == "322" || code == "323")cityN = "استان کرمانشاه - شهر پاوه";
|
171 |
-
if (code == "595")cityN = "استان کرمانشاه - شهر ثلاث باباجانی";
|
172 |
-
if (code == "395")cityN = "استان کرمانشاه - شهر جوانرود";
|
173 |
-
if (code == "641")cityN = "استان کرمانشاه - شهر حمیل";
|
174 |
-
if (code == "596")cityN = "استان کرمانشاه - شهر روانسر";
|
175 |
-
if (code == "336")cityN = "استان کرمانشاه - شهر سرپل ذهاب";
|
176 |
-
if (code == "335")cityN = "استان کرمانشاه - شهر سنقر";
|
177 |
-
if (code == "496")cityN = "استان کرمانشاه - شهر صحنه";
|
178 |
-
if (code == "337")cityN = "استان کرمانشاه - شهر قصرشیرین";
|
179 |
-
if (code == "324" || code == "325")cityN = "استان کرمانشاه - شهر کرمانشاه";
|
180 |
-
if (code == "394")cityN = "استان کرمانشاه - شهر کرند";
|
181 |
-
if (code == "330")cityN = "استان کرمانشاه - شهر کنگاور";
|
182 |
-
if (code == "332")cityN = "استان کرمانشاه - شهر گیلانغرب";
|
183 |
-
if (code == "331")cityN = "استان کرمانشاه - شهر هرسین";
|
184 |
-
if (code == "687")cityN = "استان کهکیلویه و بویراحمد - شهر باشت";
|
185 |
-
if (code == "422" || code == "423")cityN = "استان کهکیلویه و بویراحمد - شهر بویراحمد(یاسوج)";
|
186 |
-
if (code == "599")cityN = "استان کهکیلویه و بویراحمد - شهر بهمنی";
|
187 |
-
if (code == "600")cityN = "استان کهکیلویه و بویراحمد - شهر چاروسا";
|
188 |
-
if (code == "688")cityN = "استان کهکیلویه و بویراحمد - شهر دروهان";
|
189 |
-
if (code == "424" || code == "425")cityN = "استان کهکیلویه و بویراحمد - شهر کهکیلویه(دهدشت)";
|
190 |
-
if (code == "426")cityN = "استان کهکیلویه و بویراحمد - شهر گچساران(دوگنبدان)";
|
191 |
-
if (code == "550")cityN = "استان کهکیلویه و بویراحمد - شهر لنده";
|
192 |
-
if (code == "697")cityN = "استان کهکیلویه و بویراحمد - شهر مارگون";
|
193 |
-
if (code == "384")cityN = "استان کردستان - شهر بانه";
|
194 |
-
if (code == "377" || code == "378")cityN = "استان کردستان - شهر بیجار";
|
195 |
-
if (code == "558")cityN = "استان کردستان - شهر دهگلان";
|
196 |
-
if (code == "385")cityN = "استان کردستان - شهر دیواندره";
|
197 |
-
if (code == "646")cityN = "استان کردستان - شهر سروآباد";
|
198 |
-
if (code == "375" || code == "376")cityN = "استان کردستان - شهر سقز";
|
199 |
-
if (code == "372" || code == "373")cityN = "استان کردستان - شهر سنندج";
|
200 |
-
if (code == "379" || code == "380")cityN = "استان کردستان - شهر قروه";
|
201 |
-
if (code == "383")cityN = "استان کردستان - شهر کامیاران";
|
202 |
-
if (code == "674")cityN = "استان کردستان - شهر کرانی";
|
203 |
-
if (code == "381" || code == "382")cityN = "استان کردستان - شهر مریوان";
|
204 |
-
if (code == "676")cityN = "استان کردستان - شهر نمشیر";
|
205 |
-
if (code == "722")cityN = "استان کرمان - شهر ارزونیه";
|
206 |
-
if (code == "542")cityN = "استان کرمان - شهر انار";
|
207 |
-
if (code == "312" || code == "313")cityN = "استان کرمان - شهر بافت";
|
208 |
-
if (code == "317")cityN = "استان کرمان - شهر بردسیر";
|
209 |
-
if (code == "310" || code == "311")cityN = "استان کرمان - شهر بم";
|
210 |
-
if (code == "302" || code == "303")cityN = "استان کرمان - شهر جیرفت";
|
211 |
-
if (code == "583")cityN = "استان کرمان - شهر رابر";
|
212 |
-
if (code == "321")cityN = "استان کرمان - شهر راور";
|
213 |
-
if (code == "382")cityN = "استان کرمان - شهر راین";
|
214 |
-
if (code == "304" || code == "305")cityN = "استان کرمان - شهر رفسنجان";
|
215 |
-
if (code == "536")cityN = "استان کرمان - شهر رودبار کهنوج";
|
216 |
-
if (code == "605")cityN = "استان کرمان - شهر ریگان";
|
217 |
-
if (code == "308" || code == "309")cityN = "استان کرمان - شهر زرند";
|
218 |
-
if (code == "306" || code == "307")cityN = "استان کرمان - شهر سیرجان";
|
219 |
-
if (code == "319")cityN = "استان کرمان - شهر شهداد";
|
220 |
-
if (code == "313" || code == "314")cityN = "استان کرمان - شهر شهربابک";
|
221 |
-
if (code == "606")cityN = "استان کرمان - شهر عنبرآباد";
|
222 |
-
if (code == "320")cityN = "استان کرمان - شهر فهرج";
|
223 |
-
if (code == "698")cityN = "استان کرمان - شهر قلعه گنج";
|
224 |
-
if (code == "298" || code == "299")cityN = "استان کرمان - شهر کرمان";
|
225 |
-
if (code == "535")cityN = "استان کرمان - شهر کوهبنان";
|
226 |
-
if (code == "315" || code == "316")cityN = "استان کرمان - شهر کهنوج";
|
227 |
-
if (code == "318")cityN = "استان کرمان - شهر گلباف";
|
228 |
-
if (code == "607")cityN = "استان کرمان - شهر ماهان";
|
229 |
-
if (code == "608")cityN = "استان کرمان - شهر منوجان";
|
230 |
-
if (code == "508")cityN = "استان قزوین - شهر آبیک";
|
231 |
-
if (code == "538")cityN = "استان قزوین - شهر آوج";
|
232 |
-
if (code == "728")cityN = "استان قزوین - شهر البرز";
|
233 |
-
if (code == "509")cityN = "استان قزوین - شهر بوئین زهرا";
|
234 |
-
if (code == "438" || code == "439")cityN = "استان قزوین - شهر تاکستان";
|
235 |
-
if (code == "580")cityN = "استان قزوین - شهر رودبار الموت";
|
236 |
-
if (code == "590")cityN = "استان قزوین - شهر رودبار شهرستان";
|
237 |
-
if (code == "559")cityN = "استان قزوین - شهر ضیاءآباد";
|
238 |
-
if (code == "588")cityN = "استان قزوین - شهر طارم سفلی";
|
239 |
-
if (code == "431" || code == "432")cityN = "استان قزوین - شهر قزوین";
|
240 |
-
if (code == "037" || code == "038")cityN = "استان قم - شهر قم";
|
241 |
-
if (code == "702")cityN = "استان قم - شهر کهک";
|
242 |
-
if (code == "240" || code == "241")cityN = "استان فارس - شهر آباده";
|
243 |
-
if (code == "670")cityN = "استان فارس - شهر آباده طشک";
|
244 |
-
if (code == "648")cityN = "استان فارس - شهر ارسنجان";
|
245 |
-
if (code == "252")cityN = "استان فارس - شهر استهبان";
|
246 |
-
if (code == "678")cityN = "استان فارس - شهر اشکنان";
|
247 |
-
if (code == "253")cityN = "استان فارس - شهر اقلید";
|
248 |
-
if (code == "649")cityN = "استان فارس - شهر اوز";
|
249 |
-
if (code == "513")cityN = "استان فارس - شهر بوانات";
|
250 |
-
if (code == "546")cityN = "استان فارس - شهر بیضا";
|
251 |
-
if (code == "671")cityN = "استان فارس - شهر جویم";
|
252 |
-
if (code == "246" || code == "247")cityN = "استان فارس - شهر جهرم";
|
253 |
-
if (code == "654")cityN = "استان فارس - شهر حاجی آباد(زرین دشت)";
|
254 |
-
if (code == "548")cityN = "استان فارس - شهر خرامه";
|
255 |
-
if (code == "547")cityN = "استان فارس - شهر خشت و کمارج";
|
256 |
-
if (code == "655")cityN = "استان فارس - شهر خفر";
|
257 |
-
if (code == "248" || code == "249")cityN = "استان فارس - شهر داراب";
|
258 |
-
if (code == "253")cityN = "استان فارس - شهر سپیدان";
|
259 |
-
if (code == "514")cityN = "استان فارس - شهر سروستان";
|
260 |
-
if (code == "665")cityN = "استان فارس - شهر سعادت آباد";
|
261 |
-
if (code == "673")cityN = "استان فارس - شهر شیبکوه";
|
262 |
-
if (code == "228" || code == "229" || code == "230")cityN = "استان فارس - شهر شیراز";
|
263 |
-
if (code == "679")cityN = "استان فارس - شهر فراشبند";
|
264 |
-
if (code == "256" || code == "257")cityN = "استان فارس - شهر فسا";
|
265 |
-
if (code == "244" || code == "245")cityN = "استان فارس - شهر فیروزآباد";
|
266 |
-
if (code == "681")cityN = "استان فارس - شهر قنقری(خرم بید)";
|
267 |
-
if (code == "723")cityN = "استان فارس - شهر قیروکارزین";
|
268 |
-
if (code == "236" || code == "237")cityN = "استان فارس - شهر کازرون";
|
269 |
-
if (code == "683")cityN = "استان فارس - شهر کوار";
|
270 |
-
if (code == "656")cityN = "استان فارس - شهر کراش";
|
271 |
-
if (code == "250" || code == "251")cityN = "استان فارس - شهر لارستان";
|
272 |
-
if (code == "515")cityN = "استان فارس - شهر لامرد";
|
273 |
-
if (code == "242" || code == "243")cityN = "استان فارس - شهر مرودشت";
|
274 |
-
if (code == "238" || code == "239")cityN = "استان فارس - شهر ممسنی";
|
275 |
-
if (code == "657")cityN = "استان فارس - شهر مهر";
|
276 |
-
if (code == "255")cityN = "استان فارس - شهر نی ریز";
|
277 |
-
if (code == "684")cityN = "استان سمنان - شهر ایوانکی";
|
278 |
-
if (code == "700")cityN = "استان سمنان - شهر بسطام";
|
279 |
-
if (code == "642")cityN = "استان سمنان - شهر بیارجمند";
|
280 |
-
if (code == "457")cityN = "استان سمنان - شهر دامغان";
|
281 |
-
if (code == "456")cityN = "استان سمنان - شهر سمنان";
|
282 |
-
if (code == "458" || code == "459")cityN = "استان سمنان - شهر شاهرود";
|
283 |
-
if (code == "460")cityN = "استان سمنان - شهر گرمسار";
|
284 |
-
if (code == "530")cityN = "استان سمنان - شهر مهدیشهر";
|
285 |
-
if (code == "520")cityN = "استان سمنان - شهر میامی";
|
286 |
-
if (code == "358" || code == "359")cityN = "استان سیستان و بلوچستان - شهر ایرانشهر";
|
287 |
-
if (code == "682")cityN = "استان سیستان و بلوچستان - شهر بزمان";
|
288 |
-
if (code == "703")cityN = "استان سیستان و بلوچستان - شهر بمپور";
|
289 |
-
if (code == "364" || code == "365")cityN = "استان سیستان و بلوچستان - شهر چابهار";
|
290 |
-
if (code == "371")cityN = "استان سیستان و بلوچستان - شهر خاش";
|
291 |
-
if (code == "701")cityN = "استان سیستان و بلوچستان - شهر دشتیاری";
|
292 |
-
if (code == "720")cityN = "استان سیستان و بلوچستان - شهر راسک";
|
293 |
-
if (code == "366" || code == "367")cityN = "استان سیستان و بلوچستان - شهر زابل";
|
294 |
-
if (code == "704")cityN = "استان سیستان و بلوچستان - شهر زابلی";
|
295 |
-
if (code == "361" || code == "362")cityN = "استان سیستان و بلوچستان - شهر زاهدان";
|
296 |
-
if (code == "369" || code == "370")cityN = "استان سیستان و بلوچستان - شهر سراوان";
|
297 |
-
if (code == "635")cityN = "استان سیستان و بلوچستان - شهر سرباز";
|
298 |
-
if (code == "668")cityN = "استان سیستان و بلوچستان - شهر سیب و سوران";
|
299 |
-
if (code == "533")cityN = "استان سیستان و بلوچستان - شهر شهرکی و ناروئی(زهک)";
|
300 |
-
if (code == "705")cityN = "استان سیستان و بلوچستان - شهر شیب آب";
|
301 |
-
if (code == "699")cityN = "استان سیستان و بلوچستان - شهر فنوج";
|
302 |
-
if (code == "669")cityN = "استان سیستان و بلوچستان - شهر قصرقند";
|
303 |
-
if (code == "725")cityN = "استان سیستان و بلوچستان - شهر کنارک";
|
304 |
-
if (code == "597")cityN = "استان سیستان و بلوچستان - شهر لاشار(اسپکه)";
|
305 |
-
if (code == "611")cityN = "استان سیستان و بلوچستان - شهر میرجاوه";
|
306 |
-
if (code == "525")cityN = "استان سیستان و بلوچستان - شهر نیک شهر";
|
307 |
-
if (code == "181")cityN = "استان خوزستان - شهر آبادان";
|
308 |
-
if (code == "527")cityN = "استان خوزستان - شهر آغاجاری";
|
309 |
-
if (code == "585")cityN = "استان خوزستان - شهر اروندکنار";
|
310 |
-
if (code == "685")cityN = "استان خوزستان - شهر امیدیه";
|
311 |
-
if (code == "663")cityN = "استان خوزستان - شهر اندیکا";
|
312 |
-
if (code == "192" || code == "193")cityN = "استان خوزستان - شهر اندیمشک";
|
313 |
-
if (code == "174" || code == "175")cityN = "استان خوزستان - شهر اهواز";
|
314 |
-
if (code == "183" || code == "184")cityN = "استان خوزستان - شهر ایذه";
|
315 |
-
if (code == "481")cityN = "استان خوزستان - شهر باغ ملک";
|
316 |
-
if (code == "706")cityN = "استان خوزستان - شهر بندر امام خمینی";
|
317 |
-
if (code == "194" || code == "195")cityN = "استان خوزستان - شهر بندرماهشهر";
|
318 |
-
if (code == "185" || code == "186")cityN = "استان خوزستان - شهر بهبهان";
|
319 |
-
if (code == "182")cityN = "استان خوزستان - شهر خرمشهر";
|
320 |
-
if (code == "199" || code == "200")cityN = "استان خوزستان - شهر دزفول";
|
321 |
-
if (code == "198")cityN = "استان خوزستان - شهر دشت آزادگان";
|
322 |
-
if (code == "662")cityN = "استان خوزستان - شهر رامشیر";
|
323 |
-
if (code == "190" || code == "191")cityN = "استان خوزستان - شهر رامهرمز";
|
324 |
-
if (code == "692")cityN = "استان خوزستان - شهر سردشت";
|
325 |
-
if (code == "189")cityN = "استان خوزستان - شهر شادگان";
|
326 |
-
if (code == "707")cityN = "استان خوزستان - شهر شاوور";
|
327 |
-
if (code == "526")cityN = "استان خوزستان - شهر شوش";
|
328 |
-
if (code == "187" || code == "188")cityN = "استان خوزستان - شهر شوشتر";
|
329 |
-
if (code == "729")cityN = "استان خوزستان - شهر گتوند";
|
330 |
-
if (code == "730")cityN = "استان خوزستان - شهر لالی";
|
331 |
-
if (code == "196" || code == "197")cityN = "استان خوزستان - شهر مسجدسلیمان";
|
332 |
-
if (code == "661")cityN = "استان خوزستان - شهر هندیجان";
|
333 |
-
if (code == "680")cityN = "استان خوزستان - شهر هویزه";
|
334 |
-
if (code == "643")cityN = "استان خراسان رضوی - شهر احمدآباد";
|
335 |
-
if (code == "562")cityN = "استان خراسان رضوی - شهر بجستان";
|
336 |
-
if (code == "572")cityN = "استان خراسان رضوی - شهر بردسکن";
|
337 |
-
if (code == "074")cityN = "استان خراسان رضوی - شهر تایباد";
|
338 |
-
if (code == "644")cityN = "استان خراسان رضوی - شهر تخت جلگه";
|
339 |
-
if (code == "072" || code == "073")cityN = "استان خراسان رضوی - شهر تربت جام";
|
340 |
-
if (code == "069" || code == "070")cityN = "استان خراسان رضوی - شهر تربت حیدریه";
|
341 |
-
if (code == "521")cityN = "استان خراسان رضوی - شهر جغتای";
|
342 |
-
if (code == "573")cityN = "استان خراسان رضوی - شهر جوین";
|
343 |
-
if (code == "522")cityN = "استان خراسان رضوی - شهر چناران";
|
344 |
-
if (code == "724")cityN = "استان خراسان رضوی - شهر خلیل آباد";
|
345 |
-
if (code == "076")cityN = "استان خراسان رضوی - شهر خواف";
|
346 |
-
if (code == "077")cityN = "استان خراسان رضوی - شهر درگز";
|
347 |
-
if (code == "650")cityN = "استان خراسان رضوی - شهر رشتخوار";
|
348 |
-
if (code == "574")cityN = "استان خراسان رضوی - شهر زبرخان";
|
349 |
-
if (code == "078" || code == "079")cityN = "استان خراسان رضوی - شهر سبزوار";
|
350 |
-
if (code == "081")cityN = "استان خراسان رضوی - شهر سرخس";
|
351 |
-
if (code == "084")cityN = "استان خراسان رضوی - شهر فریمان";
|
352 |
-
if (code == "651")cityN = "استان خراسان رضوی - شهر فیض آباد";
|
353 |
-
if (code == "086" || code == "087")cityN = "استان خراسان رضوی - شهر قوچان";
|
354 |
-
if (code == "089" || code == "090")cityN = "استان خراسان رضوی - شهر کاشمر";
|
355 |
-
if (code == "553")cityN = "استان خراسان رضوی - شهر کلات";
|
356 |
-
if (code == "091")cityN = "استان خراسان رضوی - شهر گناباد";
|
357 |
-
if (code == "092" || code == "093" || code == "094")cityN = "استان خراسان رضوی - شهر مشهد";
|
358 |
-
if (code == "097")cityN = "استان خراسان رضوی - شهر مشهد منطقه2";
|
359 |
-
if (code == "098")cityN = "استان خراسان رضوی - شهر مشهد منطقه3";
|
360 |
-
if (code == "096")cityN = "استان خراسان رضوی - شهر مشهد منطقه1";
|
361 |
-
if (code == "105" || code == "106")cityN = "استان خراسان رضوی - شهر نیشابور";
|
362 |
-
if (code == "063")cityN = "استان خراسان شمالی - شهر اسفراین";
|
363 |
-
if (code == "067" || code == "068")cityN = "استان خراسان شمالی - شهر بجنورد";
|
364 |
-
if (code == "075")cityN = "استان خراسان شمالی - شهر جاجرم";
|
365 |
-
if (code == "591")cityN = "استان خراسان شمالی - شهر رازوجرکلان";
|
366 |
-
if (code == "082")cityN = "استان خراسان شمالی - شهر شیروان";
|
367 |
-
if (code == "635")cityN = "استان خراسان شمالی - شهر فاروج";
|
368 |
-
if (code == "524")cityN = "استان خراسان شمالی - شهر مانه و سملقان";
|
369 |
-
if (code == "468")cityN = "استان چهارمحال و بختیاری - شهر اردل";
|
370 |
-
if (code == "465")cityN = "استان چهارمحال و بختیاری - شهر بروجن";
|
371 |
-
if (code == "461" || code == "462")cityN = "استان چهارمحال و بختیاری - شهر شهرکرد";
|
372 |
-
if (code == "467")cityN = "استان چهارمحال و بختیاری - شهر فارسان";
|
373 |
-
if (code == "555")cityN = "استان چهارمحال و بختیاری - شهر کوهرنگ";
|
374 |
-
if (code == "633")cityN = "استان چهارمحال و بختیاری - شهر کیار";
|
375 |
-
if (code == "629")cityN = "استان چهارمحال و بختیاری - شهر گندمان";
|
376 |
-
if (code == "466")cityN = "استان چهارمحال و بختیاری - شهر لردگان";
|
377 |
-
if (code == "696")cityN = "استان چهارمحال و بختیاری - شهر میانکوه";
|
378 |
-
if (code == "721")cityN = "استان خراسان جنوبی - شهر بشرویه";
|
379 |
-
if (code == "064" || code == "065")cityN = "استان خراسان جنوبی - شهر بیرجند";
|
380 |
-
if (code == "523")cityN = "استان خراسان جنوبی - شهر درمیان";
|
381 |
-
if (code == "652")cityN = "استان خراسان جنوبی - شهر زیرکوه";
|
382 |
-
if (code == "719")cityN = "استان خراسان جنوبی - شهر سرایان";
|
383 |
-
if (code == "716")cityN = "استان خراسان جنوبی - شهر سربیشه";
|
384 |
-
if (code == "085")cityN = "استان خراسان جنوبی - شهر فردوس";
|
385 |
-
if (code == "088")cityN = "استان خراسان جنوبی - شهر قائنات";
|
386 |
-
if (code == "563")cityN = "استان خراسان جنوبی - شهر نهبندان";
|
387 |
-
if (code == "529")cityN = "استان بوشهر - شهر بندر دیلم";
|
388 |
-
if (code == "353")cityN = "استان بوشهر - شهر بندر گناوه";
|
389 |
-
if (code == "349" || code == "350")cityN = "استان بوشهر - شهر بوشهر";
|
390 |
-
if (code == "355")cityN = "استان بوشهر - شهر تنگستان";
|
391 |
-
if (code == "609")cityN = "استان بوشهر - شهر جم";
|
392 |
-
if (code == "351" || code == "352")cityN = "استان بوشهر - شهر دشتستان";
|
393 |
-
if (code == "354")cityN = "استان بوشهر - شهر دشتی";
|
394 |
-
if (code == "732")cityN = "استان بوشهر - شهر دلوار";
|
395 |
-
if (code == "357")cityN = "استان بوشهر - شهر دیر";
|
396 |
-
if (code == "532")cityN = "استان بوشهر - شهر سعد آباد";
|
397 |
-
if (code == "610")cityN = "استان بوشهر - شهر شبانکاره";
|
398 |
-
if (code == "356")cityN = "استان بوشهر - شهر کنگان";
|
399 |
-
if (code == "556")cityN = "استان تهران - شهر اسلامشهر";
|
400 |
-
if (code == "658")cityN = "استان تهران - شهر پاکدشت";
|
401 |
-
if (code == "001" || code == "002" || code == "003" || code == "004" || code == "005" || code == "006" || code == "007" || code == "008")cityN = "استان تهران - شهر تهران مرکزی";
|
402 |
-
if (code == "011")cityN = "استان تهران - شهر تهران جنوب";
|
403 |
-
if (code == "020")cityN = "استان تهران - شهر تهران شرق";
|
404 |
-
if (code == "025")cityN = "استان تهران - شهر تهرانشمال";
|
405 |
-
if (code == "015")cityN = "استان تهران - شهر تهران غرب";
|
406 |
-
if (code == "043")cityN = "استان تهران - شهر دماوند";
|
407 |
-
if (code == "666")cityN = "استان تهران - شهر رباط کریم";
|
408 |
-
if (code == "489")cityN = "استان تهران - شهر ساوجبلاغ";
|
409 |
-
if (code == "044" || code == "045")cityN = "استان تهران - شهر شمیران";
|
410 |
-
if (code == "048" || code == "049")cityN = "استان تهران - شهر شهرری";
|
411 |
-
if (code == "490" || code == "491")cityN = "استان تهران - شهر شهریار";
|
412 |
-
if (code == "695")cityN = "استان تهران - شهر طالقان";
|
413 |
-
if (code == "659")cityN = "استان تهران - شهر فیروزکوه";
|
414 |
-
if (code == "031" || code == "032")cityN = "استان تهران - شهر کرج";
|
415 |
-
if (code == "664")cityN = "استان تهران - شهر کهریزک";
|
416 |
-
if (code == "717")cityN = "استان تهران - شهر نظرآباد";
|
417 |
-
if (code == "041" || code == "042")cityN = "استان تهران - شهر ورامین";
|
418 |
-
if (code == "471" || code == "472")cityN = " امور خارجه - امور خارجه";
|
419 |
-
if (code == "454")cityN = "استان ایلام - شهر آبدانان";
|
420 |
-
if (code == "581")cityN = "استان ایلام - شهر ارکوازی(ملکشاهی)";
|
421 |
-
if (code == "449" || code == "450")cityN = "استان ایلام - شهر ایلام";
|
422 |
-
if (code == "616")cityN = "استان ایلام - شهر ایوان";
|
423 |
-
if (code == "534")cityN = "استان ایلام - شهر بدره";
|
424 |
-
if (code == "455")cityN = "استان ایلام - شهر دره شهر";
|
425 |
-
if (code == "451")cityN = "استان ایلام - شهر دهلران";
|
426 |
-
if (code == "726")cityN = "استان ایلام - شهر زرین آباد";
|
427 |
-
if (code == "634")cityN = "استان ایلام - شهر شیروان لومار";
|
428 |
-
if (code == "453")cityN = "استان ایلام - شهر شیروان و چرداول";
|
429 |
-
if (code == "727")cityN = "استان ایلام - شهر موسیان";
|
430 |
-
if (code == "452")cityN = "استان ایلام - شهر مهران";
|
431 |
-
if (code == "145" || code == "146")cityN = "استان اردبیل - شهر اردبیل";
|
432 |
-
if (code == "731")cityN = "استان اردبیل - شهر ارشق";
|
433 |
-
if (code == "690")cityN = "استان اردبیل - شهر انگوت";
|
434 |
-
if (code == "601")cityN = "استان اردبیل - شهر بیله سوار";
|
435 |
-
if (code == "504")cityN = "استان اردبیل - شهر پارس آباد";
|
436 |
-
if (code == "163")cityN = "استان اردبیل - شهر خلخال";
|
437 |
-
if (code == "714")cityN = "استان اردبیل - شهر خورش رستم";
|
438 |
-
if (code == "715")cityN = "استان اردبیل - شهر سرعین";
|
439 |
-
if (code == "566")cityN = "استان اردبیل - شهر سنجبد(کوثر)";
|
440 |
-
if (code == "166" || code == "167")cityN = "استان اردبیل - شهر مشکین شهر";
|
441 |
-
if (code == "161" || code == "162")cityN = "استان اردبیل - شهر مغان";
|
442 |
-
if (code == "686")cityN = "استان اردبیل - شهر نمین";
|
443 |
-
if (code == "603")cityN = "استان اردبیل - شهر نیر";
|
444 |
-
if (code == "619")cityN = "استان اصفهان - شهر آران و بیدگل";
|
445 |
-
if (code == "118")cityN = "استان اصفهان - شهر اردستان";
|
446 |
-
if (code == "127" || code == "128" || code == "129")cityN = "استان اصفهان - شهر اصفهان";
|
447 |
-
if (code == "620")cityN = "استان اصفهان - شهر باغ بهادران";
|
448 |
-
if (code == "621")cityN = "استان اصفهان - شهر بوئین و میاندشت";
|
449 |
-
if (code == "549")cityN = "استان اصفهان - شهر تیران و کرون";
|
450 |
-
if (code == "564")cityN = "استان اصفهان - شهر جرقویه";
|
451 |
-
if (code == "575")cityN = "استان اصفهان - شهر چادگان";
|
452 |
-
if (code == "113" || code == "114")cityN = "استان اصفهان - شهر خمینی شهر";
|
453 |
-
if (code == "122")cityN = "استان اصفهان - شهر خوانسار";
|
454 |
-
if (code == "540")cityN = "استان اصفهان - شهر خور و بیابانک";
|
455 |
-
if (code == "660")cityN = "استان اصفهان - شهر دولت آباد";
|
456 |
-
if (code == "120")cityN = "استان اصفهان - شهر سمیرم";
|
457 |
-
if (code == "512")cityN = "استان اصفهان - شهر سمیرم سفلی (دهاقان)";
|
458 |
-
if (code == "510" || code == "511")cityN = "استان اصفهان - شهر شاهین شهر";
|
459 |
-
if (code == "119")cityN = "استان اصفهان - شهر شهرضا";
|
460 |
-
if (code == "115")cityN = "استان اصفهان - شهر فریدن";
|
461 |
-
if (code == "112")cityN = "استان اصفهان - شهر فریدونشهر";
|
462 |
-
if (code == "110" || code == "111")cityN = "استان اصفهان - شهر فلاورجان";
|
463 |
-
if (code == "125" || code == "126")cityN = "استان اصفهان - شهر کاشان";
|
464 |
-
if (code == "565")cityN = "استان اصفهان - شهر کوهپایه";
|
465 |
-
if (code == "121")cityN = "استان اصفهان - شهر گلپایگان";
|
466 |
-
if (code == "116" || code == "117")cityN = "استان اصفهان - شهر لنجان(زرینشهر)";
|
467 |
-
if (code == "541")cityN = "استان اصفهان - شهر مبارکه";
|
468 |
-
if (code == "622")cityN = "استان اصفهان - شهر میمه";
|
469 |
-
if (code == "124")cityN = "استان اصفهان - شهر نائین";
|
470 |
-
if (code == "108" || code == "109")cityN = "استان اصفهان - شهر نجف آباد";
|
471 |
-
if (code == "123")cityN = "استان اصفهان - شهر نطنز";
|
472 |
-
if (code == "427" || code == "428")cityN = "استان زنجان - شهر زنجان";
|
473 |
-
if (code == "507")cityN = "استان آذربایجان شرقی - شهر ملکان";
|
474 |
-
if (code == "158")cityN = "استان آذربایجان شرقی - شهر مرند";
|
475 |
-
if (code == "152" || code == "153")cityN = "استان آذربایجان شرقی - شهر میانه";
|
476 |
-
if (code == "615")cityN = "استان قزوین - شهر ابهر و خرمدره";
|
477 |
-
return cityN;
|
478 |
-
}
|
479 |
-
|
480 |
-
function melli_code_function(melli_code , field_id , message1 , message2 , message3 , is_seperate , show_city ) {
|
481 |
-
|
482 |
-
document.getElementById("city_" + field_id).innerHTML = '';
|
483 |
-
|
484 |
-
if (melli_code.value == '')
|
485 |
-
return false;
|
486 |
-
|
487 |
-
melli_code.value = melli_code.value.replace("-", "").replace("-", "");
|
488 |
-
|
489 |
-
if (melli_code.value.length == 8)
|
490 |
-
melli_code.value = '00' + melli_code.value;
|
491 |
-
|
492 |
-
if (melli_code.value.length == 9)
|
493 |
-
melli_code.value = '0' + melli_code.value;
|
494 |
-
|
495 |
-
if (isNaN(melli_code.value)) {
|
496 |
-
document.getElementById("city_" + field_id).innerHTML = message1;
|
497 |
-
return false;
|
498 |
-
}
|
499 |
-
|
500 |
-
if (melli_code.value.length > 10 || melli_code.value.length < 8) {
|
501 |
-
document.getElementById("city_" + field_id).innerHTML = message2;
|
502 |
-
return false;
|
503 |
-
}
|
504 |
-
|
505 |
-
var pre_check = ["0000000000", "1111111111", "2222222222", "3333333333", "4444444444", "5555555555", "6666666666", "7777777777", "8888888888", "9999999999"];
|
506 |
-
var indexOf = pre_check.indexOf(melli_code.value);
|
507 |
-
if (indexOf != '-1') {
|
508 |
-
document.getElementById("city_" + field_id).innerHTML = message3;
|
509 |
-
return false;
|
510 |
-
}
|
511 |
-
|
512 |
-
city = melli_code.value.substring(0, 3);
|
513 |
-
c = parseInt(melli_code.value.charAt(9));
|
514 |
-
n = parseInt(melli_code.value.charAt(0)) * 10 +
|
515 |
-
parseInt(melli_code.value.charAt(1)) * 9 +
|
516 |
-
parseInt(melli_code.value.charAt(2)) * 8 +
|
517 |
-
parseInt(melli_code.value.charAt(3)) * 7 +
|
518 |
-
parseInt(melli_code.value.charAt(4)) * 6 +
|
519 |
-
parseInt(melli_code.value.charAt(5)) * 5 +
|
520 |
-
parseInt(melli_code.value.charAt(6)) * 4 +
|
521 |
-
parseInt(melli_code.value.charAt(7)) * 3 +
|
522 |
-
parseInt(melli_code.value.charAt(8)) * 2;
|
523 |
-
r = n - parseInt(n / 11) * 11;
|
524 |
-
|
525 |
-
if ((r == 0 && r == c) || (r == 1 && c == 1) || (r > 1 && c == 11 - r)) {
|
526 |
-
if(is_seperate) {
|
527 |
-
if (melli_code.value.length == 10)
|
528 |
-
melli_code.value = melli_code.value.substring(0, 3) + "-" + melli_code.value.substring(3, 9) + "-" + melli_code.value.substring(9, 10);
|
529 |
-
}
|
530 |
-
if(show_city) {
|
531 |
-
document.getElementById("city_" + field_id).innerHTML = cityName_by_melliCode_hannanstd(city);
|
532 |
-
return true;
|
533 |
-
}
|
534 |
-
}
|
535 |
-
else {
|
536 |
-
document.getElementById("city_" + field_id).innerHTML = message3;
|
537 |
-
return false;
|
538 |
-
}
|
539 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assets/js/melli-code.min.js
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
function cityName_by_melliCode_hannanstd(t){return"169"==t&&(cityN="استان آذربایجان شرقی - شهر آذر شهر"),"170"==t&&(cityN="استان آذربایجان شرقی - شهر اسکو"),("149"==t||"150"==t)&&(cityN="استان آذربایجان شرقی - شهر اهر"),"171"==t&&(cityN="استان آذربایجان شرقی - شهر بستان آباد"),"168"==t&&(cityN="استان آذربایجان شرقی - شهر بناب"),("136"==t||"137"==t||"138"==t)&&(cityN="استان آذربایجان شرقی - شهر تبریز"),"545"==t&&(cityN="استان آذربایجان شرقی - شهر ترکمانچای"),"505"==t&&(cityN="استان آذربایجان شرقی - شهر جلفا"),"636"==t&&(cityN="استان آذربایجان شرقی - شهر چاروایماق"),("164"==t||"165"==t)&&(cityN="استان آذربایجان شرقی - شهر سراب"),"172"==t&&(cityN="استان آذربایجان شرقی - شهر شبستر"),"623"==t&&(cityN="استان آذربایجان شرقی - شهر صوفیان"),"506"==t&&(cityN="استان آذربایجان شرقی - شهر عجب شیر"),"519"==t&&(cityN="استان آذربایجان شرقی - شهر کلیبر"),("154"==t||"155"==t)&&(cityN="استان آذربایجان شرقی - شهر مراغه"),"567"==t&&(cityN="استان آذربایجان شرقی - شهر ورزقان"),"173"==t&&(cityN="استان آذربایجان شرقی - شهر هریس"),("159"==t||"160"==t)&&(cityN="استان آذربایجان شرقی - شهر هشترود"),"604"==t&&(cityN="استان آذربایجان شرقی - شهر هوراند"),("274"==t||"275"==t)&&(cityN="استان آذربایجان غربی - شهر ارومیه"),"295"==t&&(cityN="استان آذربایجان غربی - شهر اشنویه"),"637"==t&&(cityN="استان آذربایجان غربی - شهر انزل"),"292"==t&&(cityN="استان آذربایجان غربی - شهر بوکان"),"492"==t&&(cityN="استان آذربایجان غربی - شهر پلدشت"),"289"==t&&(cityN="استان آذربایجان غربی - شهر پیرانشهر"),"677"==t&&(cityN="استان آذربایجان غربی - شهر تخت سلیمان"),"294"==t&&(cityN="استان آذربایجان غربی - شهر تکاب"),"493"==t&&(cityN="استان آذربایجان غربی - شهر چایپاره"),("279"==t||"280"==t)&&(cityN="استان آذربایجان غربی - شهر خوی"),"288"==t&&(cityN="استان آذربایجان غربی - شهر سردشت"),("284"==t||"285"==t)&&(cityN="استان آذربایجان غربی - شهر سلماس"),"638"==t&&(cityN="استان آذربایجان غربی - شهر سیلوانه"),"291"==t&&(cityN="استان آذربایجان غربی - شهر سیه چشمه(چالدران)"),"640"==t&&(cityN="استان آذربایجان غربی - شهر شوط"),"293"==t&&(cityN="استان آذربایجان غربی - شهر شاهین دژ"),"675"==t&&(cityN="استان آذربایجان غربی - شهر کشاورز"),("282"==t||"283"==t)&&(cityN="استان آذربایجان غربی - شهر ماکو"),("286"==t||"287"==t)&&(cityN="استان آذربایجان غربی - شهر مهاباد"),("296"==t||"297"==t)&&(cityN="استان آذربایجان غربی - شهر میاندوآب"),"290"==t&&(cityN="استان آذربایجان غربی - شهر نقده"),("400"==t||"401"==t)&&(cityN="استان همدان - شهر اسدآباد"),("404"==t||"405"==t)&&(cityN="استان همدان - شهر بهار"),"397"==t&&(cityN="استان همدان - شهر تویسرکان"),("398"==t||"399"==t)&&(cityN="استان همدان - شهر رزن"),"647"==t&&(cityN="استان همدان - شهر شراء و پیشخوار"),"502"==t&&(cityN="استان همدان - شهر فامنین"),"584"==t&&(cityN="استان همدان - شهر قلقل رود"),("402"==t||"403"==t)&&(cityN="استان همدان - شهر کبودرآهنگ"),("392"==t||"393"==t)&&(cityN="استان همدان - شهر ملایر"),("395"==t||"396"==t)&&(cityN="استان همدان - شهر نهاوند"),("386"==t||"387"==t)&&(cityN="استان همدان - شهر همدان"),"503"==t&&(cityN="استان یزد - شهر ابرکوه"),"444"==t&&(cityN="استان یزد - شهر اردکان"),"551"==t&&(cityN="استان یزد - شهر اشکذر"),"447"==t&&(cityN="استان یزد - شهر بافق"),"561"==t&&(cityN="استان یزد - شهر بهاباد"),"445"==t&&(cityN="استان یزد - شهر تفت"),"718"==t&&(cityN="استان یزد - شهر دستگردان"),"083"==t&&(cityN="استان یزد - شهر طبس"),"446"==t&&(cityN="استان یزد - شهر مهریز"),"448"==t&&(cityN="استان یزد - شهر میبد"),"552"==t&&(cityN="استان یزد - شهر نیر"),"543"==t&&(cityN="استان یزد - شهر هرات و مروست"),("442"==t||"443"==t)&&(cityN="استان یزد - شهر یزد"),"051"==t&&(cityN="استان مرکزی - شهر آشتیان"),("052"==t||"053"==t)&&(cityN="استان مرکزی - شهر اراک"),"058"==t&&(cityN="استان مرکزی - شهر تفرش"),"055"==t&&(cityN="استان مرکزی - شهر خمین"),"617"==t&&(cityN="استان مرکزی - شهر خنداب"),"057"==t&&(cityN="استان مرکزی - شهر دلیجان"),"618"==t&&(cityN="استان مرکزی - شهر زرند مرکزی"),("059"==t||"060"==t)&&(cityN="استان مرکزی - شهر ساوه"),("061"==t||"062"==t)&&(cityN="استان مرکزی - شهر سربند"),"544"==t&&(cityN="استان مرکزی - شهر فراهان"),"056"==t&&(cityN="استان مرکزی - شهر محلات"),"571"==t&&(cityN="استان مرکزی - شهر وفس"),"593"==t&&(cityN="استان مرکزی - شهر هندودر"),"667"==t&&(cityN="استان هرمزگان - شهر ابوموسی"),"348"==t&&(cityN="استان هرمزگان - شهر بستک"),"586"==t&&(cityN="استان هرمزگان - شهر بشاگرد"),("338"==t||"339"==t)&&(cityN="استان هرمزگان - شهر بندرعباس"),("343"==t||"344"==t)&&(cityN="استان هرمزگان - شهر بندرلنگه"),"346"==t&&(cityN="استان هرمزگان - شهر جاسک"),"337"==t&&(cityN="استان هرمزگان - شهر حاجی آباد"),"554"==t&&(cityN="استان هرمزگان - شهر خمیر"),"469"==t&&(cityN="استان هرمزگان - شهر رودان"),"537"==t&&(cityN="استان هرمزگان - شهر فین"),"345"==t&&(cityN="استان هرمزگان - شهر قشم"),"470"==t&&(cityN="استان هرمزگان - شهر گاوبندی"),("341"==t||"342"==t)&&(cityN="استان هرمزگان - شهر میناب"),("483"==t||"484"==t)&&(cityN="استان لرستان - شهر ازنا"),"557"==t&&(cityN="استان لرستان - شهر اشترینان"),"418"==t&&(cityN="استان لرستان - شهر الشتر"),("416"==t||"417"==t)&&(cityN="استان لرستان - شهر الیگودرز"),("412"==t||"413"==t)&&(cityN="استان لرستان - شهر بروجرد"),"592"==t&&(cityN="استان لرستان - شهر پاپی"),"612"==t&&(cityN="استان لرستان - شهر چغلوندی"),"613"==t&&(cityN="استان لرستان - شهر چگنی"),("406"==t||"407"==t)&&(cityN="استان لرستان - شهر خرم آباد"),"421"==t&&(cityN="استان لرستان - شهر دورود"),"598"==t&&(cityN="استان لرستان - شهر رومشکان"),"419"==t&&(cityN="استان لرستان - شهر کوهدشت"),"385"==t&&(cityN="استان لرستان - شهر ملاوی(پلدختر)"),"420"==t&&(cityN="استان لرستان - شهر نورآباد(دلفان)"),"528"==t&&(cityN="استان لرستان - شهر ویسیان"),("213"==t||"214"==t)&&(cityN="استان مازندران - شهر آمل"),("205"==t||"206"==t)&&(cityN="استان مازندران - شهر بابل"),"498"==t&&(cityN="استان مازندران - شهر بابل"),"568"==t&&(cityN="استان مازندران - شهر بندپی"),"711"==t&&(cityN="استان مازندران - شهر بندپی شرقی"),("217"==t||"218"==t)&&(cityN="استان مازندران - شهر بهشهر"),"221"==t&&(cityN="استان مازندران - شهر تنکابن"),"582"==t&&(cityN="استان مازندران - شهر جویبار"),"483"==t&&(cityN="استان مازندران - شهر چالوس"),"625"==t&&(cityN="استان مازندران - شهر چمستان"),"576"==t&&(cityN="استان مازندران - شهر چهاردانگه"),"578"==t&&(cityN="استان مازندران - شهر دودانگه"),"227"==t&&(cityN="استان مازندران - شهر رامسر"),("208"==t||"209"==t)&&(cityN="استان مازندران - شهر ساری"),"225"==t&&(cityN="استان مازندران - شهر سوادکوه"),"577"==t&&(cityN="استان مازندران - شهر شیرگاه"),"712"==t&&(cityN="استان مازندران - شهر عباس آباد"),("215"==t||"216"==t)&&(cityN="استان مازندران - شهر قائمشهر"),"626"==t&&(cityN="استان مازندران - شهر کجور"),"627"==t&&(cityN="استان مازندران - شهر کلاردشت"),"579"==t&&(cityN="استان مازندران - شهر گلوگاه"),"713"==t&&(cityN="استان مازندران - شهر میاندورود"),"499"==t&&(cityN="استان مازندران - شهر نکاء"),"222"==t&&(cityN="استان مازندران - شهر نور"),("219"==t||"220"==t)&&(cityN="استان مازندران - شهر نوشهر"),("500"==t||"501"==t)&&(cityN="استان مازندران - شهر هراز و محمودآباد"),"623"==t&&(cityN="استان گلستان - شهر آزادشهر"),"497"==t&&(cityN="استان گلستان - شهر آق قلا"),"223"==t&&(cityN="استان گلستان - شهر بندرترکمن"),"689"==t&&(cityN="استان گلستان - شهر بندرگز"),"487"==t&&(cityN="استان گلستان - شهر رامیان"),"226"==t&&(cityN="استان گلستان - شهر علی آباد"),"224"==t&&(cityN="استان گلستان - شهر کردکوی"),"386"==t&&(cityN="استان گلستان - شهر کلاله"),("211"==t||"212"==t)&&(cityN="استان گلستان - شهر گرگان"),"628"==t&&(cityN="استان گلستان - شهر گمیشان"),("202"==t||"203"==t)&&(cityN="استان گلستان - شهر گنبد کاووس"),"531"==t&&(cityN="استان گلستان - شهر مراوه تپه"),"288"==t&&(cityN="استان گلستان - شهر مینودشت"),"261"==t&&(cityN="استان گیلان - شهر آستارا"),"273"==t&&(cityN="استان گیلان - شهر آستانه"),"630"==t&&(cityN="استان گیلان - شهر املش"),"264"==t&&(cityN="استان گیلان - شهر بندرانزلی"),"518"==t&&(cityN="استان گیلان - شهر خمام"),"631"==t&&(cityN="استان گیلان - شهر رحیم آباد"),("258"==t||"259"==t)&&(cityN="استان گیلان - شهر رشت"),"570"==t&&(cityN="استان گیلان - شهر رضوانشهر"),"265"==t&&(cityN="استان گیلان - شهر رودبار"),("268"==t||"269"==t)&&(cityN="استان گیلان - شهر رودسر"),"653"==t&&(cityN="استان گیلان - شهر سنگر"),"517"==t&&(cityN="استان گیلان - شهر سیاهکل"),"569"==t&&(cityN="استان گیلان - شهر شفت"),"267"==t&&(cityN="استان گیلان - شهر صومعه سرا"),("262"==t||"263"==t)&&(cityN="استان گیلان - شهر طالش"),"593"==t&&(cityN="استان گیلان - شهر عمارلو"),"266"==t&&(cityN="استان گیلان - شهر فومن"),"693"==t&&(cityN="استان گیلان - شهر کوچصفهان"),("271"==t||"272"==t)&&(cityN="استان گیلان - شهر لاهیجان"),"694"==t&&(cityN="استان گیلان - شهر لشت نشاء"),"270"==t&&(cityN="استان گیلان - شهر لنگرود"),"516"==t&&(cityN="استان گیلان - شهر ماسال و شاندرمن"),("333"==t||"334"==t)&&(cityN="استان کرمانشاه - شهر اسلام آباد"),"691"==t&&(cityN="استان کرمانشاه - شهر باینگان"),("322"==t||"323"==t)&&(cityN="استان کرمانشاه - شهر پاوه"),"595"==t&&(cityN="استان کرمانشاه - شهر ثلاث باباجانی"),"395"==t&&(cityN="استان کرمانشاه - شهر جوانرود"),"641"==t&&(cityN="استان کرمانشاه - شهر حمیل"),"596"==t&&(cityN="استان کرمانشاه - شهر روانسر"),"336"==t&&(cityN="استان کرمانشاه - شهر سرپل ذهاب"),"335"==t&&(cityN="استان کرمانشاه - شهر سنقر"),"496"==t&&(cityN="استان کرمانشاه - شهر صحنه"),"337"==t&&(cityN="استان کرمانشاه - شهر قصرشیرین"),("324"==t||"325"==t)&&(cityN="استان کرمانشاه - شهر کرمانشاه"),"394"==t&&(cityN="استان کرمانشاه - شهر کرند"),"330"==t&&(cityN="استان کرمانشاه - شهر کنگاور"),"332"==t&&(cityN="استان کرمانشاه - شهر گیلانغرب"),"331"==t&&(cityN="استان کرمانشاه - شهر هرسین"),"687"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر باشت"),("422"==t||"423"==t)&&(cityN="استان کهکیلویه و بویراحمد - شهر بویراحمد(یاسوج)"),"599"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر بهمنی"),"600"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر چاروسا"),"688"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر دروهان"),("424"==t||"425"==t)&&(cityN="استان کهکیلویه و بویراحمد - شهر کهکیلویه(دهدشت)"),"426"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر گچساران(دوگنبدان)"),"550"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر لنده"),"697"==t&&(cityN="استان کهکیلویه و بویراحمد - شهر مارگون"),"384"==t&&(cityN="استان کردستان - شهر بانه"),("377"==t||"378"==t)&&(cityN="استان کردستان - شهر بیجار"),"558"==t&&(cityN="استان کردستان - شهر دهگلان"),"385"==t&&(cityN="استان کردستان - شهر دیواندره"),"646"==t&&(cityN="استان کردستان - شهر سروآباد"),("375"==t||"376"==t)&&(cityN="استان کردستان - شهر سقز"),("372"==t||"373"==t)&&(cityN="استان کردستان - شهر سنندج"),("379"==t||"380"==t)&&(cityN="استان کردستان - شهر قروه"),"383"==t&&(cityN="استان کردستان - شهر کامیاران"),"674"==t&&(cityN="استان کردستان - شهر کرانی"),("381"==t||"382"==t)&&(cityN="استان کردستان - شهر مریوان"),"676"==t&&(cityN="استان کردستان - شهر نمشیر"),"722"==t&&(cityN="استان کرمان - شهر ارزونیه"),"542"==t&&(cityN="استان کرمان - شهر انار"),("312"==t||"313"==t)&&(cityN="استان کرمان - شهر بافت"),"317"==t&&(cityN="استان کرمان - شهر بردسیر"),("310"==t||"311"==t)&&(cityN="استان کرمان - شهر بم"),("302"==t||"303"==t)&&(cityN="استان کرمان - شهر جیرفت"),"583"==t&&(cityN="استان کرمان - شهر رابر"),"321"==t&&(cityN="استان کرمان - شهر راور"),"382"==t&&(cityN="استان کرمان - شهر راین"),("304"==t||"305"==t)&&(cityN="استان کرمان - شهر رفسنجان"),"536"==t&&(cityN="استان کرمان - شهر رودبار کهنوج"),"605"==t&&(cityN="استان کرمان - شهر ریگان"),("308"==t||"309"==t)&&(cityN="استان کرمان - شهر زرند"),("306"==t||"307"==t)&&(cityN="استان کرمان - شهر سیرجان"),"319"==t&&(cityN="استان کرمان - شهر شهداد"),("313"==t||"314"==t)&&(cityN="استان کرمان - شهر شهربابک"),"606"==t&&(cityN="استان کرمان - شهر عنبرآباد"),"320"==t&&(cityN="استان کرمان - شهر فهرج"),"698"==t&&(cityN="استان کرمان - شهر قلعه گنج"),("298"==t||"299"==t)&&(cityN="استان کرمان - شهر کرمان"),"535"==t&&(cityN="استان کرمان - شهر کوهبنان"),("315"==t||"316"==t)&&(cityN="استان کرمان - شهر کهنوج"),"318"==t&&(cityN="استان کرمان - شهر گلباف"),"607"==t&&(cityN="استان کرمان - شهر ماهان"),"608"==t&&(cityN="استان کرمان - شهر منوجان"),"508"==t&&(cityN="استان قزوین - شهر آبیک"),"538"==t&&(cityN="استان قزوین - شهر آوج"),"728"==t&&(cityN="استان قزوین - شهر البرز"),"509"==t&&(cityN="استان قزوین - شهر بوئین زهرا"),("438"==t||"439"==t)&&(cityN="استان قزوین - شهر تاکستان"),"580"==t&&(cityN="استان قزوین - شهر رودبار الموت"),"590"==t&&(cityN="استان قزوین - شهر رودبار شهرستان"),"559"==t&&(cityN="استان قزوین - شهر ضیاءآباد"),"588"==t&&(cityN="استان قزوین - شهر طارم سفلی"),("431"==t||"432"==t)&&(cityN="استان قزوین - شهر قزوین"),("037"==t||"038"==t)&&(cityN="استان قم - شهر قم"),"702"==t&&(cityN="استان قم - شهر کهک"),("240"==t||"241"==t)&&(cityN="استان فارس - شهر آباده"),"670"==t&&(cityN="استان فارس - شهر آباده طشک"),"648"==t&&(cityN="استان فارس - شهر ارسنجان"),"252"==t&&(cityN="استان فارس - شهر استهبان"),"678"==t&&(cityN="استان فارس - شهر اشکنان"),"253"==t&&(cityN="استان فارس - شهر اقلید"),"649"==t&&(cityN="استان فارس - شهر اوز"),"513"==t&&(cityN="استان فارس - شهر بوانات"),"546"==t&&(cityN="استان فارس - شهر بیضا"),"671"==t&&(cityN="استان فارس - شهر جویم"),("246"==t||"247"==t)&&(cityN="استان فارس - شهر جهرم"),"654"==t&&(cityN="استان فارس - شهر حاجی آباد(زرین دشت)"),"548"==t&&(cityN="استان فارس - شهر خرامه"),"547"==t&&(cityN="استان فارس - شهر خشت و کمارج"),"655"==t&&(cityN="استان فارس - شهر خفر"),("248"==t||"249"==t)&&(cityN="استان فارس - شهر داراب"),"253"==t&&(cityN="استان فارس - شهر سپیدان"),"514"==t&&(cityN="استان فارس - شهر سروستان"),"665"==t&&(cityN="استان فارس - شهر سعادت آباد"),"673"==t&&(cityN="استان فارس - شهر شیبکوه"),("228"==t||"229"==t||"230"==t)&&(cityN="استان فارس - شهر شیراز"),"679"==t&&(cityN="استان فارس - شهر فراشبند"),("256"==t||"257"==t)&&(cityN="استان فارس - شهر فسا"),("244"==t||"245"==t)&&(cityN="استان فارس - شهر فیروزآباد"),"681"==t&&(cityN="استان فارس - شهر قنقری(خرم بید)"),"723"==t&&(cityN="استان فارس - شهر قیروکارزین"),("236"==t||"237"==t)&&(cityN="استان فارس - شهر کازرون"),"683"==t&&(cityN="استان فارس - شهر کوار"),"656"==t&&(cityN="استان فارس - شهر کراش"),("250"==t||"251"==t)&&(cityN="استان فارس - شهر لارستان"),"515"==t&&(cityN="استان فارس - شهر لامرد"),("242"==t||"243"==t)&&(cityN="استان فارس - شهر مرودشت"),("238"==t||"239"==t)&&(cityN="استان فارس - شهر ممسنی"),"657"==t&&(cityN="استان فارس - شهر مهر"),"255"==t&&(cityN="استان فارس - شهر نی ریز"),"684"==t&&(cityN="استان سمنان - شهر ایوانکی"),"700"==t&&(cityN="استان سمنان - شهر بسطام"),"642"==t&&(cityN="استان سمنان - شهر بیارجمند"),"457"==t&&(cityN="استان سمنان - شهر دامغان"),"456"==t&&(cityN="استان سمنان - شهر سمنان"),("458"==t||"459"==t)&&(cityN="استان سمنان - شهر شاهرود"),"460"==t&&(cityN="استان سمنان - شهر گرمسار"),"530"==t&&(cityN="استان سمنان - شهر مهدیشهر"),"520"==t&&(cityN="استان سمنان - شهر میامی"),("358"==t||"359"==t)&&(cityN="استان سیستان و بلوچستان - شهر ایرانشهر"),"682"==t&&(cityN="استان سیستان و بلوچستان - شهر بزمان"),"703"==t&&(cityN="استان سیستان و بلوچستان - شهر بمپور"),("364"==t||"365"==t)&&(cityN="استان سیستان و بلوچستان - شهر چابهار"),"371"==t&&(cityN="استان سیستان و بلوچستان - شهر خاش"),"701"==t&&(cityN="استان سیستان و بلوچستان - شهر دشتیاری"),"720"==t&&(cityN="استان سیستان و بلوچستان - شهر راسک"),("366"==t||"367"==t)&&(cityN="استان سیستان و بلوچستان - شهر زابل"),"704"==t&&(cityN="استان سیستان و بلوچستان - شهر زابلی"),("361"==t||"362"==t)&&(cityN="استان سیستان و بلوچستان - شهر زاهدان"),("369"==t||"370"==t)&&(cityN="استان سیستان و بلوچستان - شهر سراوان"),"635"==t&&(cityN="استان سیستان و بلوچستان - شهر سرباز"),"668"==t&&(cityN="استان سیستان و بلوچستان - شهر سیب و سوران"),"533"==t&&(cityN="استان سیستان و بلوچستان - شهر شهرکی و ناروئی(زهک)"),"705"==t&&(cityN="استان سیستان و بلوچستان - شهر شیب آب"),"699"==t&&(cityN="استان سیستان و بلوچستان - شهر فنوج"),"669"==t&&(cityN="استان سیستان و بلوچستان - شهر قصرقند"),"725"==t&&(cityN="استان سیستان و بلوچستان - شهر کنارک"),"597"==t&&(cityN="استان سیستان و بلوچستان - شهر لاشار(اسپکه)"),"611"==t&&(cityN="استان سیستان و بلوچستان - شهر میرجاوه"),"525"==t&&(cityN="استان سیستان و بلوچستان - شهر نیک شهر"),"181"==t&&(cityN="استان خوزستان - شهر آبادان"),"527"==t&&(cityN="استان خوزستان - شهر آغاجاری"),"585"==t&&(cityN="استان خوزستان - شهر اروندکنار"),"685"==t&&(cityN="استان خوزستان - شهر امیدیه"),"663"==t&&(cityN="استان خوزستان - شهر اندیکا"),("192"==t||"193"==t)&&(cityN="استان خوزستان - شهر اندیمشک"),("174"==t||"175"==t)&&(cityN="استان خوزستان - شهر اهواز"),("183"==t||"184"==t)&&(cityN="استان خوزستان - شهر ایذه"),"481"==t&&(cityN="استان خوزستان - شهر باغ ملک"),"706"==t&&(cityN="استان خوزستان - شهر بندر امام خمینی"),("194"==t||"195"==t)&&(cityN="استان خوزستان - شهر بندرماهشهر"),("185"==t||"186"==t)&&(cityN="استان خوزستان - شهر بهبهان"),"182"==t&&(cityN="استان خوزستان - شهر خرمشهر"),("199"==t||"200"==t)&&(cityN="استان خوزستان - شهر دزفول"),"198"==t&&(cityN="استان خوزستان - شهر دشت آزادگان"),"662"==t&&(cityN="استان خوزستان - شهر رامشیر"),("190"==t||"191"==t)&&(cityN="استان خوزستان - شهر رامهرمز"),"692"==t&&(cityN="استان خوزستان - شهر سردشت"),"189"==t&&(cityN="استان خوزستان - شهر شادگان"),"707"==t&&(cityN="استان خوزستان - شهر شاوور"),"526"==t&&(cityN="استان خوزستان - شهر شوش"),("187"==t||"188"==t)&&(cityN="استان خوزستان - شهر شوشتر"),"729"==t&&(cityN="استان خوزستان - شهر گتوند"),"730"==t&&(cityN="استان خوزستان - شهر لالی"),("196"==t||"197"==t)&&(cityN="استان خوزستان - شهر مسجدسلیمان"),"661"==t&&(cityN="استان خوزستان - شهر هندیجان"),"680"==t&&(cityN="استان خوزستان - شهر هویزه"),"643"==t&&(cityN="استان خراسان رضوی - شهر احمدآباد"),"562"==t&&(cityN="استان خراسان رضوی - شهر بجستان"),"572"==t&&(cityN="استان خراسان رضوی - شهر بردسکن"),"074"==t&&(cityN="استان خراسان رضوی - شهر تایباد"),"644"==t&&(cityN="استان خراسان رضوی - شهر تخت جلگه"),("072"==t||"073"==t)&&(cityN="استان خراسان رضوی - شهر تربت جام"),("069"==t||"070"==t)&&(cityN="استان خراسان رضوی - شهر تربت حیدریه"),"521"==t&&(cityN="استان خراسان رضوی - شهر جغتای"),"573"==t&&(cityN="استان خراسان رضوی - شهر جوین"),"522"==t&&(cityN="استان خراسان رضوی - شهر چناران"),"724"==t&&(cityN="استان خراسان رضوی - شهر خلیل آباد"),"076"==t&&(cityN="استان خراسان رضوی - شهر خواف"),"077"==t&&(cityN="استان خراسان رضوی - شهر درگز"),"650"==t&&(cityN="استان خراسان رضوی - شهر رشتخوار"),"574"==t&&(cityN="استان خراسان رضوی - شهر زبرخان"),("078"==t||"079"==t)&&(cityN="استان خراسان رضوی - شهر سبزوار"),"081"==t&&(cityN="استان خراسان رضوی - شهر سرخس"),"084"==t&&(cityN="استان خراسان رضوی - شهر فریمان"),"651"==t&&(cityN="استان خراسان رضوی - شهر فیض آباد"),("086"==t||"087"==t)&&(cityN="استان خراسان رضوی - شهر قوچان"),("089"==t||"090"==t)&&(cityN="استان خراسان رضوی - شهر کاشمر"),"553"==t&&(cityN="استان خراسان رضوی - شهر کلات"),"091"==t&&(cityN="استان خراسان رضوی - شهر گناباد"),("092"==t||"093"==t||"094"==t)&&(cityN="استان خراسان رضوی - شهر مشهد"),"097"==t&&(cityN="استان خراسان رضوی - شهر مشهد منطقه2"),"098"==t&&(cityN="استان خراسان رضوی - شهر مشهد منطقه3"),"096"==t&&(cityN="استان خراسان رضوی - شهر مشهد منطقه1"),("105"==t||"106"==t)&&(cityN="استان خراسان رضوی - شهر نیشابور"),"063"==t&&(cityN="استان خراسان شمالی - شهر اسفراین"),("067"==t||"068"==t)&&(cityN="استان خراسان شمالی - شهر بجنورد"),"075"==t&&(cityN="استان خراسان شمالی - شهر جاجرم"),"591"==t&&(cityN="استان خراسان شمالی - شهر رازوجرکلان"),"082"==t&&(cityN="استان خراسان شمالی - شهر شیروان"),"635"==t&&(cityN="استان خراسان شمالی - شهر فاروج"),"524"==t&&(cityN="استان خراسان شمالی - شهر مانه و سملقان"),"468"==t&&(cityN="استان چهارمحال و بختیاری - شهر اردل"),"465"==t&&(cityN="استان چهارمحال و بختیاری - شهر بروجن"),("461"==t||"462"==t)&&(cityN="استان چهارمحال و بختیاری - شهر شهرکرد"),"467"==t&&(cityN="استان چهارمحال و بختیاری - شهر فارسان"),"555"==t&&(cityN="استان چهارمحال و بختیاری - شهر کوهرنگ"),"633"==t&&(cityN="استان چهارمحال و بختیاری - شهر کیار"),"629"==t&&(cityN="استان چهارمحال و بختیاری - شهر گندمان"),"466"==t&&(cityN="استان چهارمحال و بختیاری - شهر لردگان"),"696"==t&&(cityN="استان چهارمحال و بختیاری - شهر میانکوه"),"721"==t&&(cityN="استان خراسان جنوبی - شهر بشرویه"),("064"==t||"065"==t)&&(cityN="استان خراسان جنوبی - شهر بیرجند"),"523"==t&&(cityN="استان خراسان جنوبی - شهر درمیان"),"652"==t&&(cityN="استان خراسان جنوبی - شهر زیرکوه"),"719"==t&&(cityN="استان خراسان جنوبی - شهر سرایان"),"716"==t&&(cityN="استان خراسان جنوبی - شهر سربیشه"),"085"==t&&(cityN="استان خراسان جنوبی - شهر فردوس"),"088"==t&&(cityN="استان خراسان جنوبی - شهر قائنات"),"563"==t&&(cityN="استان خراسان جنوبی - شهر نهبندان"),"529"==t&&(cityN="استان بوشهر - شهر بندر دیلم"),"353"==t&&(cityN="استان بوشهر - شهر بندر گناوه"),("349"==t||"350"==t)&&(cityN="استان بوشهر - شهر بوشهر"),"355"==t&&(cityN="استان بوشهر - شهر تنگستان"),"609"==t&&(cityN="استان بوشهر - شهر جم"),("351"==t||"352"==t)&&(cityN="استان بوشهر - شهر دشتستان"),"354"==t&&(cityN="استان بوشهر - شهر دشتی"),"732"==t&&(cityN="استان بوشهر - شهر دلوار"),"357"==t&&(cityN="استان بوشهر - شهر دیر"),"532"==t&&(cityN="استان بوشهر - شهر سعد آباد"),"610"==t&&(cityN="استان بوشهر - شهر شبانکاره"),"356"==t&&(cityN="استان بوشهر - شهر کنگان"),"556"==t&&(cityN="استان تهران - شهر اسلامشهر"),"658"==t&&(cityN="استان تهران - شهر پاکدشت"),("001"==t||"002"==t||"003"==t||"004"==t||"005"==t||"006"==t||"007"==t||"008"==t)&&(cityN="استان تهران - شهر تهران مرکزی"),"011"==t&&(cityN="استان تهران - شهر تهران جنوب"),"020"==t&&(cityN="استان تهران - شهر تهران شرق"),"025"==t&&(cityN="استان تهران - شهر تهرانشمال"),"015"==t&&(cityN="استان تهران - شهر تهران غرب"),"043"==t&&(cityN="استان تهران - شهر دماوند"),"666"==t&&(cityN="استان تهران - شهر رباط کریم"),"489"==t&&(cityN="استان تهران - شهر ساوجبلاغ"),("044"==t||"045"==t)&&(cityN="استان تهران - شهر شمیران"),("048"==t||"049"==t)&&(cityN="استان تهران - شهر شهرری"),("490"==t||"491"==t)&&(cityN="استان تهران - شهر شهریار"),"695"==t&&(cityN="استان تهران - شهر طالقان"),"659"==t&&(cityN="استان تهران - شهر فیروزکوه"),("031"==t||"032"==t)&&(cityN="استان تهران - شهر کرج"),"664"==t&&(cityN="استان تهران - شهر کهریزک"),"717"==t&&(cityN="استان تهران - شهر نظرآباد"),("041"==t||"042"==t)&&(cityN="استان تهران - شهر ورامین"),("471"==t||"472"==t)&&(cityN=" امور خارجه - امور خارجه"),"454"==t&&(cityN="استان ایلام - شهر آبدانان"),"581"==t&&(cityN="استان ایلام - شهر ارکوازی(ملکشاهی)"),("449"==t||"450"==t)&&(cityN="استان ایلام - شهر ایلام"),"616"==t&&(cityN="استان ایلام - شهر ایوان"),"534"==t&&(cityN="استان ایلام - شهر بدره"),"455"==t&&(cityN="استان ایلام - شهر دره شهر"),"451"==t&&(cityN="استان ایلام - شهر دهلران"),"726"==t&&(cityN="استان ایلام - شهر زرین آباد"),"634"==t&&(cityN="استان ایلام - شهر شیروان لومار"),"453"==t&&(cityN="استان ایلام - شهر شیروان و چرداول"),"727"==t&&(cityN="استان ایلام - شهر موسیان"),"452"==t&&(cityN="استان ایلام - شهر مهران"),("145"==t||"146"==t)&&(cityN="استان اردبیل - شهر اردبیل"),"731"==t&&(cityN="استان اردبیل - شهر ارشق"),"690"==t&&(cityN="استان اردبیل - شهر انگوت"),"601"==t&&(cityN="استان اردبیل - شهر بیله سوار"),"504"==t&&(cityN="استان اردبیل - شهر پارس آباد"),"163"==t&&(cityN="استان اردبیل - شهر خلخال"),"714"==t&&(cityN="استان اردبیل - شهر خورش رستم"),"715"==t&&(cityN="استان اردبیل - شهر سرعین"),"566"==t&&(cityN="استان اردبیل - شهر سنجبد(کوثر)"),("166"==t||"167"==t)&&(cityN="استان اردبیل - شهر مشکین شهر"),("161"==t||"162"==t)&&(cityN="استان اردبیل - شهر مغان"),"686"==t&&(cityN="استان اردبیل - شهر نمین"),"603"==t&&(cityN="استان اردبیل - شهر نیر"),"619"==t&&(cityN="استان اصفهان - شهر آران و بیدگل"),"118"==t&&(cityN="استان اصفهان - شهر اردستان"),("127"==t||"128"==t||"129"==t)&&(cityN="استان اصفهان - شهر اصفهان"),"620"==t&&(cityN="استان اصفهان - شهر باغ بهادران"),"621"==t&&(cityN="استان اصفهان - شهر بوئین و میاندشت"),"549"==t&&(cityN="استان اصفهان - شهر تیران و کرون"),"564"==t&&(cityN="استان اصفهان - شهر جرقویه"),"575"==t&&(cityN="استان اصفهان - شهر چادگان"),("113"==t||"114"==t)&&(cityN="استان اصفهان - شهر خمینی شهر"),"122"==t&&(cityN="استان اصفهان - شهر خوانسار"),"540"==t&&(cityN="استان اصفهان - شهر خور و بیابانک"),"660"==t&&(cityN="استان اصفهان - شهر دولت آباد"),"120"==t&&(cityN="استان اصفهان - شهر سمیرم"),"512"==t&&(cityN="استان اصفهان - شهر سمیرم سفلی (دهاقان)"),("510"==t||"511"==t)&&(cityN="استان اصفهان - شهر شاهین شهر"),"119"==t&&(cityN="استان اصفهان - شهر شهرضا"),"115"==t&&(cityN="استان اصفهان - شهر فریدن"),"112"==t&&(cityN="استان اصفهان - شهر فریدونشهر"),("110"==t||"111"==t)&&(cityN="استان اصفهان - شهر فلاورجان"),("125"==t||"126"==t)&&(cityN="استان اصفهان - شهر کاشان"),"565"==t&&(cityN="استان اصفهان - شهر کوهپایه"),"121"==t&&(cityN="استان اصفهان - شهر گلپایگان"),("116"==t||"117"==t)&&(cityN="استان اصفهان - شهر لنجان(زرینشهر)"),"541"==t&&(cityN="استان اصفهان - شهر مبارکه"),"622"==t&&(cityN="استان اصفهان - شهر میمه"),"124"==t&&(cityN="استان اصفهان - شهر نائین"),("108"==t||"109"==t)&&(cityN="استان اصفهان - شهر نجف آباد"),"123"==t&&(cityN="استان اصفهان - شهر نطنز"),("427"==t||"428"==t)&&(cityN="استان زنجان - شهر زنجان"),"507"==t&&(cityN="استان آذربایجان شرقی - شهر ملکان"),"158"==t&&(cityN="استان آذربایجان شرقی - شهر مرند"),("152"==t||"153"==t)&&(cityN="استان آذربایجان شرقی - شهر میانه"),"615"==t&&(cityN="استان قزوین - شهر ابهر و خرمدره"),cityN}function melli_code_function(t,i,y,N,e,a,l){if(document.getElementById("city_"+i).innerHTML="",""==t.value)return!1;if(t.value=t.value.replace("-","").replace("-",""),8==t.value.length&&(t.value="00"+t.value),9==t.value.length&&(t.value="0"+t.value),isNaN(t.value))return document.getElementById("city_"+i).innerHTML=y,!1;if(t.value.length>10||t.value.length<8)return document.getElementById("city_"+i).innerHTML=N,!1;var u=["0000000000","1111111111","2222222222","3333333333","4444444444","5555555555","6666666666","7777777777","8888888888","9999999999"],v=u.indexOf(t.value);return"-1"!=v?(document.getElementById("city_"+i).innerHTML=e,!1):(city=t.value.substring(0,3),c=parseInt(t.value.charAt(9)),n=10*parseInt(t.value.charAt(0))+9*parseInt(t.value.charAt(1))+8*parseInt(t.value.charAt(2))+7*parseInt(t.value.charAt(3))+6*parseInt(t.value.charAt(4))+5*parseInt(t.value.charAt(5))+4*parseInt(t.value.charAt(6))+3*parseInt(t.value.charAt(7))+2*parseInt(t.value.charAt(8)),r=n-11*parseInt(n/11),0==r&&r==c||1==r&&1==c||r>1&&c==11-r?(a&&10==t.value.length&&(t.value=t.value.substring(0,3)+"-"+t.value.substring(3,9)+"-"+t.value.substring(9,10)),l?(document.getElementById("city_"+i).innerHTML=cityName_by_melliCode_hannanstd(city),!0):void 0):(document.getElementById("city_"+i).innerHTML=e,!1))}
|
|
assets/js/national_id.js
ADDED
@@ -0,0 +1,546 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* @return {string}
|
3 |
+
*/
|
4 |
+
function GFPersian_National_ID_Location(code) {
|
5 |
+
var location = '';
|
6 |
+
if (code == "169") location = "استان آذربایجان شرقی - شهر آذر شهر";
|
7 |
+
if (code == "170") location = "استان آذربایجان شرقی - شهر اسکو";
|
8 |
+
if (code == "149" || code == "150") location = "استان آذربایجان شرقی - شهر اهر";
|
9 |
+
if (code == "171") location = "استان آذربایجان شرقی - شهر بستان آباد";
|
10 |
+
if (code == "168") location = "استان آذربایجان شرقی - شهر بناب";
|
11 |
+
if (code == "136" || code == "137" || code == "138") location = "استان آذربایجان شرقی - شهر تبریز";
|
12 |
+
if (code == "545") location = "استان آذربایجان شرقی - شهر ترکمانچای";
|
13 |
+
if (code == "505") location = "استان آذربایجان شرقی - شهر جلفا";
|
14 |
+
if (code == "636") location = "استان آذربایجان شرقی - شهر چاروایماق";
|
15 |
+
if (code == "164" || code == "165") location = "استان آذربایجان شرقی - شهر سراب";
|
16 |
+
if (code == "172") location = "استان آذربایجان شرقی - شهر شبستر";
|
17 |
+
if (code == "623") location = "استان آذربایجان شرقی - شهر صوفیان";
|
18 |
+
if (code == "506") location = "استان آذربایجان شرقی - شهر عجب شیر";
|
19 |
+
if (code == "519") location = "استان آذربایجان شرقی - شهر کلیبر";
|
20 |
+
if (code == "154" || code == "155") location = "استان آذربایجان شرقی - شهر مراغه";
|
21 |
+
if (code == "567") location = "استان آذربایجان شرقی - شهر ورزقان";
|
22 |
+
if (code == "173") location = "استان آذربایجان شرقی - شهر هریس";
|
23 |
+
if (code == "159" || code == "160") location = "استان آذربایجان شرقی - شهر هشترود";
|
24 |
+
if (code == "604") location = "استان آذربایجان شرقی - شهر هوراند";
|
25 |
+
if (code == "274" || code == "275") location = "استان آذربایجان غربی - شهر ارومیه";
|
26 |
+
if (code == "295") location = "استان آذربایجان غربی - شهر اشنویه";
|
27 |
+
if (code == "637") location = "استان آذربایجان غربی - شهر انزل";
|
28 |
+
if (code == "292") location = "استان آذربایجان غربی - شهر بوکان";
|
29 |
+
if (code == "492") location = "استان آذربایجان غربی - شهر پلدشت";
|
30 |
+
if (code == "289") location = "استان آذربایجان غربی - شهر پیرانشهر";
|
31 |
+
if (code == "677") location = "استان آذربایجان غربی - شهر تخت سلیمان";
|
32 |
+
if (code == "294") location = "استان آذربایجان غربی - شهر تکاب";
|
33 |
+
if (code == "493") location = "استان آذربایجان غربی - شهر چایپاره";
|
34 |
+
if (code == "279" || code == "280") location = "استان آذربایجان غربی - شهر خوی";
|
35 |
+
if (code == "288") location = "استان آذربایجان غربی - شهر سردشت";
|
36 |
+
if (code == "284" || code == "285") location = "استان آذربایجان غربی - شهر سلماس";
|
37 |
+
if (code == "638") location = "استان آذربایجان غربی - شهر سیلوانه";
|
38 |
+
if (code == "291") location = "استان آذربایجان غربی - شهر سیه چشمه(چالدران)";
|
39 |
+
if (code == "640") location = "استان آذربایجان غربی - شهر شوط";
|
40 |
+
if (code == "293") location = "استان آذربایجان غربی - شهر شاهین دژ";
|
41 |
+
if (code == "675") location = "استان آذربایجان غربی - شهر کشاورز";
|
42 |
+
if (code == "282" || code == "283") location = "استان آذربایجان غربی - شهر ماکو";
|
43 |
+
if (code == "286" || code == "287") location = "استان آذربایجان غربی - شهر مهاباد";
|
44 |
+
if (code == "296" || code == "297") location = "استان آذربایجان غربی - شهر میاندوآب";
|
45 |
+
if (code == "290") location = "استان آذربایجان غربی - شهر نقده";
|
46 |
+
if (code == "400" || code == "401") location = "استان همدان - شهر اسدآباد";
|
47 |
+
if (code == "404" || code == "405") location = "استان همدان - شهر بهار";
|
48 |
+
if (code == "397") location = "استان همدان - شهر تویسرکان";
|
49 |
+
if (code == "398" || code == "399") location = "استان همدان - شهر رزن";
|
50 |
+
if (code == "647") location = "استان همدان - شهر شراء و پیشخوار";
|
51 |
+
if (code == "502") location = "استان همدان - شهر فامنین";
|
52 |
+
if (code == "584") location = "استان همدان - شهر قلقل رود";
|
53 |
+
if (code == "402" || code == "403") location = "استان همدان - شهر کبودرآهنگ";
|
54 |
+
if (code == "392" || code == "393") location = "استان همدان - شهر ملایر";
|
55 |
+
if (code == "395" || code == "396") location = "استان همدان - شهر نهاوند";
|
56 |
+
if (code == "386" || code == "387") location = "استان همدان - شهر همدان";
|
57 |
+
if (code == "503") location = "استان یزد - شهر ابرکوه";
|
58 |
+
if (code == "444") location = "استان یزد - شهر اردکان";
|
59 |
+
if (code == "551") location = "استان یزد - شهر اشکذر";
|
60 |
+
if (code == "447") location = "استان یزد - شهر بافق";
|
61 |
+
if (code == "561") location = "استان یزد - شهر بهاباد";
|
62 |
+
if (code == "445") location = "استان یزد - شهر تفت";
|
63 |
+
if (code == "718") location = "استان یزد - شهر دستگردان";
|
64 |
+
if (code == "083") location = "استان یزد - شهر طبس";
|
65 |
+
if (code == "446") location = "استان یزد - شهر مهریز";
|
66 |
+
if (code == "448") location = "استان یزد - شهر میبد";
|
67 |
+
if (code == "552") location = "استان یزد - شهر نیر";
|
68 |
+
if (code == "543") location = "استان یزد - شهر هرات و مروست";
|
69 |
+
if (code == "442" || code == "443") location = "استان یزد - شهر یزد";
|
70 |
+
if (code == "051") location = "استان مرکزی - شهر آشتیان";
|
71 |
+
if (code == "052" || code == "053") location = "استان مرکزی - شهر اراک";
|
72 |
+
if (code == "058") location = "استان مرکزی - شهر تفرش";
|
73 |
+
if (code == "055") location = "استان مرکزی - شهر خمین";
|
74 |
+
if (code == "617") location = "استان مرکزی - شهر خنداب";
|
75 |
+
if (code == "057") location = "استان مرکزی - شهر دلیجان";
|
76 |
+
if (code == "618") location = "استان مرکزی - شهر زرند مرکزی";
|
77 |
+
if (code == "059" || code == "060") location = "استان مرکزی - شهر ساوه";
|
78 |
+
if (code == "061" || code == "062") location = "استان مرکزی - شهر سربند";
|
79 |
+
if (code == "544") location = "استان مرکزی - شهر فراهان";
|
80 |
+
if (code == "056") location = "استان مرکزی - شهر محلات";
|
81 |
+
if (code == "571") location = "استان مرکزی - شهر وفس";
|
82 |
+
if (code == "593") location = "استان مرکزی - شهر هندودر";
|
83 |
+
if (code == "667") location = "استان هرمزگان - شهر ابوموسی";
|
84 |
+
if (code == "348") location = "استان هرمزگان - شهر بستک";
|
85 |
+
if (code == "586") location = "استان هرمزگان - شهر بشاگرد";
|
86 |
+
if (code == "338" || code == "339") location = "استان هرمزگان - شهر بندرعباس";
|
87 |
+
if (code == "343" || code == "344") location = "استان هرمزگان - شهر بندرلنگه";
|
88 |
+
if (code == "346") location = "استان هرمزگان - شهر جاسک";
|
89 |
+
if (code == "337") location = "استان هرمزگان - شهر حاجی آباد";
|
90 |
+
if (code == "554") location = "استان هرمزگان - شهر خمیر";
|
91 |
+
if (code == "469") location = "استان هرمزگان - شهر رودان";
|
92 |
+
if (code == "537") location = "استان هرمزگان - شهر فین";
|
93 |
+
if (code == "345") location = "استان هرمزگان - شهر قشم";
|
94 |
+
if (code == "470") location = "استان هرمزگان - شهر گاوبندی";
|
95 |
+
if (code == "341" || code == "342") location = "استان هرمزگان - شهر میناب";
|
96 |
+
if (code == "483" || code == "484") location = "استان لرستان - شهر ازنا";
|
97 |
+
if (code == "557") location = "استان لرستان - شهر اشترینان";
|
98 |
+
if (code == "418") location = "استان لرستان - شهر الشتر";
|
99 |
+
if (code == "416" || code == "417") location = "استان لرستان - شهر الیگودرز";
|
100 |
+
if (code == "412" || code == "413") location = "استان لرستان - شهر بروجرد";
|
101 |
+
if (code == "592") location = "استان لرستان - شهر پاپی";
|
102 |
+
if (code == "612") location = "استان لرستان - شهر چغلوندی";
|
103 |
+
if (code == "613") location = "استان لرستان - شهر چگنی";
|
104 |
+
if (code == "406" || code == "407") location = "استان لرستان - شهر خرم آباد";
|
105 |
+
if (code == "421") location = "استان لرستان - شهر دورود";
|
106 |
+
if (code == "598") location = "استان لرستان - شهر رومشکان";
|
107 |
+
if (code == "419") location = "استان لرستان - شهر کوهدشت";
|
108 |
+
if (code == "385") location = "استان لرستان - شهر ملاوی(پلدختر)";
|
109 |
+
if (code == "420") location = "استان لرستان - شهر نورآباد(دلفان)";
|
110 |
+
if (code == "528") location = "استان لرستان - شهر ویسیان";
|
111 |
+
if (code == "213" || code == "214") location = "استان مازندران - شهر آمل";
|
112 |
+
if (code == "205" || code == "206") location = "استان مازندران - شهر بابل";
|
113 |
+
if (code == "498") location = "استان مازندران - شهر بابل";
|
114 |
+
if (code == "568") location = "استان مازندران - شهر بندپی";
|
115 |
+
if (code == "711") location = "استان مازندران - شهر بندپی شرقی";
|
116 |
+
if (code == "217" || code == "218") location = "استان مازندران - شهر بهشهر";
|
117 |
+
if (code == "221") location = "استان مازندران - شهر تنکابن";
|
118 |
+
if (code == "582") location = "استان مازندران - شهر جویبار";
|
119 |
+
if (code == "483") location = "استان مازندران - شهر چالوس";
|
120 |
+
if (code == "625") location = "استان مازندران - شهر چمستان";
|
121 |
+
if (code == "576") location = "استان مازندران - شهر چهاردانگه";
|
122 |
+
if (code == "578") location = "استان مازندران - شهر دودانگه";
|
123 |
+
if (code == "227") location = "استان مازندران - شهر رامسر";
|
124 |
+
if (code == "208" || code == "209") location = "استان مازندران - شهر ساری";
|
125 |
+
if (code == "225") location = "استان مازندران - شهر سوادکوه";
|
126 |
+
if (code == "577") location = "استان مازندران - شهر شیرگاه";
|
127 |
+
if (code == "712") location = "استان مازندران - شهر عباس آباد";
|
128 |
+
if (code == "215" || code == "216") location = "استان مازندران - شهر قائمشهر";
|
129 |
+
if (code == "626") location = "استان مازندران - شهر کجور";
|
130 |
+
if (code == "627") location = "استان مازندران - شهر کلاردشت";
|
131 |
+
if (code == "579") location = "استان مازندران - شهر گلوگاه";
|
132 |
+
if (code == "713") location = "استان مازندران - شهر میاندورود";
|
133 |
+
if (code == "499") location = "استان مازندران - شهر نکاء";
|
134 |
+
if (code == "222") location = "استان مازندران - شهر نور";
|
135 |
+
if (code == "219" || code == "220") location = "استان مازندران - شهر نوشهر";
|
136 |
+
if (code == "500" || code == "501") location = "استان مازندران - شهر هراز و محمودآباد";
|
137 |
+
if (code == "623") location = "استان گلستان - شهر آزادشهر";
|
138 |
+
if (code == "497") location = "استان گلستان - شهر آق قلا";
|
139 |
+
if (code == "223") location = "استان گلستان - شهر بندرترکمن";
|
140 |
+
if (code == "689") location = "استان گلستان - شهر بندرگز";
|
141 |
+
if (code == "487") location = "استان گلستان - شهر رامیان";
|
142 |
+
if (code == "226") location = "استان گلستان - شهر علی آباد";
|
143 |
+
if (code == "224") location = "استان گلستان - شهر کردکوی";
|
144 |
+
if (code == "386") location = "استان گلستان - شهر کلاله";
|
145 |
+
if (code == "211" || code == "212") location = "استان گلستان - شهر گرگان";
|
146 |
+
if (code == "628") location = "استان گلستان - شهر گمیشان";
|
147 |
+
if (code == "202" || code == "203") location = "استان گلستان - شهر گنبد کاووس";
|
148 |
+
if (code == "531") location = "استان گلستان - شهر مراوه تپه";
|
149 |
+
if (code == "288") location = "استان گلستان - شهر مینودشت";
|
150 |
+
if (code == "261") location = "استان گیلان - شهر آستارا";
|
151 |
+
if (code == "273") location = "استان گیلان - شهر آستانه";
|
152 |
+
if (code == "630") location = "استان گیلان - شهر املش";
|
153 |
+
if (code == "264") location = "استان گیلان - شهر بندرانزلی";
|
154 |
+
if (code == "518") location = "استان گیلان - شهر خمام";
|
155 |
+
if (code == "631") location = "استان گیلان - شهر رحیم آباد";
|
156 |
+
if (code == "258" || code == "259") location = "استان گیلان - شهر رشت";
|
157 |
+
if (code == "570") location = "استان گیلان - شهر رضوانشهر";
|
158 |
+
if (code == "265") location = "استان گیلان - شهر رودبار";
|
159 |
+
if (code == "268" || code == "269") location = "استان گیلان - شهر رودسر";
|
160 |
+
if (code == "653") location = "استان گیلان - شهر سنگر";
|
161 |
+
if (code == "517") location = "استان گیلان - شهر سیاهکل";
|
162 |
+
if (code == "569") location = "استان گیلان - شهر شفت";
|
163 |
+
if (code == "267") location = "استان گیلان - شهر صومعه سرا";
|
164 |
+
if (code == "262" || code == "263") location = "استان گیلان - شهر طالش";
|
165 |
+
if (code == "593") location = "استان گیلان - شهر عمارلو";
|
166 |
+
if (code == "266") location = "استان گیلان - شهر فومن";
|
167 |
+
if (code == "693") location = "استان گیلان - شهر کوچصفهان";
|
168 |
+
if (code == "271" || code == "272") location = "استان گیلان - شهر لاهیجان";
|
169 |
+
if (code == "694") location = "استان گیلان - شهر لشت نشاء";
|
170 |
+
if (code == "270") location = "استان گیلان - شهر لنگرود";
|
171 |
+
if (code == "516") location = "استان گیلان - شهر ماسال و شاندرمن";
|
172 |
+
if (code == "333" || code == "334") location = "استان کرمانشاه - شهر اسلام آباد";
|
173 |
+
if (code == "691") location = "استان کرمانشاه - شهر باینگان";
|
174 |
+
if (code == "322" || code == "323") location = "استان کرمانشاه - شهر پاوه";
|
175 |
+
if (code == "595") location = "استان کرمانشاه - شهر ثلاث باباجانی";
|
176 |
+
if (code == "395") location = "استان کرمانشاه - شهر جوانرود";
|
177 |
+
if (code == "641") location = "استان کرمانشاه - شهر حمیل";
|
178 |
+
if (code == "596") location = "استان کرمانشاه - شهر روانسر";
|
179 |
+
if (code == "336") location = "استان کرمانشاه - شهر سرپل ذهاب";
|
180 |
+
if (code == "335") location = "استان کرمانشاه - شهر سنقر";
|
181 |
+
if (code == "496") location = "استان کرمانشاه - شهر صحنه";
|
182 |
+
if (code == "337") location = "استان کرمانشاه - شهر قصرشیرین";
|
183 |
+
if (code == "324" || code == "325") location = "استان کرمانشاه - شهر کرمانشاه";
|
184 |
+
if (code == "394") location = "استان کرمانشاه - شهر کرند";
|
185 |
+
if (code == "330") location = "استان کرمانشاه - شهر کنگاور";
|
186 |
+
if (code == "332") location = "استان کرمانشاه - شهر گیلانغرب";
|
187 |
+
if (code == "331") location = "استان کرمانشاه - شهر هرسین";
|
188 |
+
if (code == "687") location = "استان کهکیلویه و بویراحمد - شهر باشت";
|
189 |
+
if (code == "422" || code == "423") location = "استان کهکیلویه و بویراحمد - شهر بویراحمد(یاسوج)";
|
190 |
+
if (code == "599") location = "استان کهکیلویه و بویراحمد - شهر بهمنی";
|
191 |
+
if (code == "600") location = "استان کهکیلویه و بویراحمد - شهر چاروسا";
|
192 |
+
if (code == "688") location = "استان کهکیلویه و بویراحمد - شهر دروهان";
|
193 |
+
if (code == "424" || code == "425") location = "استان کهکیلویه و بویراحمد - شهر کهکیلویه(دهدشت)";
|
194 |
+
if (code == "426") location = "استان کهکیلویه و بویراحمد - شهر گچساران(دوگنبدان)";
|
195 |
+
if (code == "550") location = "استان کهکیلویه و بویراحمد - شهر لنده";
|
196 |
+
if (code == "697") location = "استان کهکیلویه و بویراحمد - شهر مارگون";
|
197 |
+
if (code == "384") location = "استان کردستان - شهر بانه";
|
198 |
+
if (code == "377" || code == "378") location = "استان کردستان - شهر بیجار";
|
199 |
+
if (code == "558") location = "استان کردستان - شهر دهگلان";
|
200 |
+
if (code == "385") location = "استان کردستان - شهر دیواندره";
|
201 |
+
if (code == "646") location = "استان کردستان - شهر سروآباد";
|
202 |
+
if (code == "375" || code == "376") location = "استان کردستان - شهر سقز";
|
203 |
+
if (code == "372" || code == "373") location = "استان کردستان - شهر سنندج";
|
204 |
+
if (code == "379" || code == "380") location = "استان کردستان - شهر قروه";
|
205 |
+
if (code == "383") location = "استان کردستان - شهر کامیاران";
|
206 |
+
if (code == "674") location = "استان کردستان - شهر کرانی";
|
207 |
+
if (code == "381" || code == "382") location = "استان کردستان - شهر مریوان";
|
208 |
+
if (code == "676") location = "استان کردستان - شهر نمشیر";
|
209 |
+
if (code == "722") location = "استان کرمان - شهر ارزونیه";
|
210 |
+
if (code == "542") location = "استان کرمان - شهر انار";
|
211 |
+
if (code == "312" || code == "313") location = "استان کرمان - شهر بافت";
|
212 |
+
if (code == "317") location = "استان کرمان - شهر بردسیر";
|
213 |
+
if (code == "310" || code == "311") location = "استان کرمان - شهر بم";
|
214 |
+
if (code == "302" || code == "303") location = "استان کرمان - شهر جیرفت";
|
215 |
+
if (code == "583") location = "استان کرمان - شهر رابر";
|
216 |
+
if (code == "321") location = "استان کرمان - شهر راور";
|
217 |
+
if (code == "382") location = "استان کرمان - شهر راین";
|
218 |
+
if (code == "304" || code == "305") location = "استان کرمان - شهر رفسنجان";
|
219 |
+
if (code == "536") location = "استان کرمان - شهر رودبار کهنوج";
|
220 |
+
if (code == "605") location = "استان کرمان - شهر ریگان";
|
221 |
+
if (code == "308" || code == "309") location = "استان کرمان - شهر زرند";
|
222 |
+
if (code == "306" || code == "307") location = "استان کرمان - شهر سیرجان";
|
223 |
+
if (code == "319") location = "استان کرمان - شهر شهداد";
|
224 |
+
if (code == "313" || code == "314") location = "استان کرمان - شهر شهربابک";
|
225 |
+
if (code == "606") location = "استان کرمان - شهر عنبرآباد";
|
226 |
+
if (code == "320") location = "استان کرمان - شهر فهرج";
|
227 |
+
if (code == "698") location = "استان کرمان - شهر قلعه گنج";
|
228 |
+
if (code == "298" || code == "299") location = "استان کرمان - شهر کرمان";
|
229 |
+
if (code == "535") location = "استان کرمان - شهر کوهبنان";
|
230 |
+
if (code == "315" || code == "316") location = "استان کرمان - شهر کهنوج";
|
231 |
+
if (code == "318") location = "استان کرمان - شهر گلباف";
|
232 |
+
if (code == "607") location = "استان کرمان - شهر ماهان";
|
233 |
+
if (code == "608") location = "استان کرمان - شهر منوجان";
|
234 |
+
if (code == "508") location = "استان قزوین - شهر آبیک";
|
235 |
+
if (code == "538") location = "استان قزوین - شهر آوج";
|
236 |
+
if (code == "728") location = "استان قزوین - شهر البرز";
|
237 |
+
if (code == "509") location = "استان قزوین - شهر بوئین زهرا";
|
238 |
+
if (code == "438" || code == "439") location = "استان قزوین - شهر تاکستان";
|
239 |
+
if (code == "580") location = "استان قزوین - شهر رودبار الموت";
|
240 |
+
if (code == "590") location = "استان قزوین - شهر رودبار شهرستان";
|
241 |
+
if (code == "559") location = "استان قزوین - شهر ضیاءآباد";
|
242 |
+
if (code == "588") location = "استان قزوین - شهر طارم سفلی";
|
243 |
+
if (code == "431" || code == "432") location = "استان قزوین - شهر قزوین";
|
244 |
+
if (code == "037" || code == "038") location = "استان قم - شهر قم";
|
245 |
+
if (code == "702") location = "استان قم - شهر کهک";
|
246 |
+
if (code == "240" || code == "241") location = "استان فارس - شهر آباده";
|
247 |
+
if (code == "670") location = "استان فارس - شهر آباده طشک";
|
248 |
+
if (code == "648") location = "استان فارس - شهر ارسنجان";
|
249 |
+
if (code == "252") location = "استان فارس - شهر استهبان";
|
250 |
+
if (code == "678") location = "استان فارس - شهر اشکنان";
|
251 |
+
if (code == "253") location = "استان فارس - شهر اقلید";
|
252 |
+
if (code == "649") location = "استان فارس - شهر اوز";
|
253 |
+
if (code == "513") location = "استان فارس - شهر بوانات";
|
254 |
+
if (code == "546") location = "استان فارس - شهر بیضا";
|
255 |
+
if (code == "671") location = "استان فارس - شهر جویم";
|
256 |
+
if (code == "246" || code == "247") location = "استان فارس - شهر جهرم";
|
257 |
+
if (code == "654") location = "استان فارس - شهر حاجی آباد(زرین دشت)";
|
258 |
+
if (code == "548") location = "استان فارس - شهر خرامه";
|
259 |
+
if (code == "547") location = "استان فارس - شهر خشت و کمارج";
|
260 |
+
if (code == "655") location = "استان فارس - شهر خفر";
|
261 |
+
if (code == "248" || code == "249") location = "استان فارس - شهر داراب";
|
262 |
+
if (code == "253") location = "استان فارس - شهر سپیدان";
|
263 |
+
if (code == "514") location = "استان فارس - شهر سروستان";
|
264 |
+
if (code == "665") location = "استان فارس - شهر سعادت آباد";
|
265 |
+
if (code == "673") location = "استان فارس - شهر شیبکوه";
|
266 |
+
if (code == "228" || code == "229" || code == "230") location = "استان فارس - شهر شیراز";
|
267 |
+
if (code == "679") location = "استان فارس - شهر فراشبند";
|
268 |
+
if (code == "256" || code == "257") location = "استان فارس - شهر فسا";
|
269 |
+
if (code == "244" || code == "245") location = "استان فارس - شهر فیروزآباد";
|
270 |
+
if (code == "681") location = "استان فارس - شهر قنقری(خرم بید)";
|
271 |
+
if (code == "723") location = "استان فارس - شهر قیروکارزین";
|
272 |
+
if (code == "236" || code == "237") location = "استان فارس - شهر کازرون";
|
273 |
+
if (code == "683") location = "استان فارس - شهر کوار";
|
274 |
+
if (code == "656") location = "استان فارس - شهر کراش";
|
275 |
+
if (code == "250" || code == "251") location = "استان فارس - شهر لارستان";
|
276 |
+
if (code == "515") location = "استان فارس - شهر لامرد";
|
277 |
+
if (code == "242" || code == "243") location = "استان فارس - شهر مرودشت";
|
278 |
+
if (code == "238" || code == "239") location = "استان فارس - شهر ممسنی";
|
279 |
+
if (code == "657") location = "استان فارس - شهر مهر";
|
280 |
+
if (code == "255") location = "استان فارس - شهر نی ریز";
|
281 |
+
if (code == "684") location = "استان سمنان - شهر ایوانکی";
|
282 |
+
if (code == "700") location = "استان سمنان - شهر بسطام";
|
283 |
+
if (code == "642") location = "استان سمنان - شهر بیارجمند";
|
284 |
+
if (code == "457") location = "استان سمنان - شهر دامغان";
|
285 |
+
if (code == "456") location = "استان سمنان - شهر سمنان";
|
286 |
+
if (code == "458" || code == "459") location = "استان سمنان - شهر شاهرود";
|
287 |
+
if (code == "460") location = "استان سمنان - شهر گرمسار";
|
288 |
+
if (code == "530") location = "استان سمنان - شهر مهدیشهر";
|
289 |
+
if (code == "520") location = "استان سمنان - شهر میامی";
|
290 |
+
if (code == "358" || code == "359") location = "استان سیستان و بلوچستان - شهر ایرانشهر";
|
291 |
+
if (code == "682") location = "استان سیستان و بلوچستان - شهر بزمان";
|
292 |
+
if (code == "703") location = "استان سیستان و بلوچستان - شهر بمپور";
|
293 |
+
if (code == "364" || code == "365") location = "استان سیستان و بلوچستان - شهر چابهار";
|
294 |
+
if (code == "371") location = "استان سیستان و بلوچستان - شهر خاش";
|
295 |
+
if (code == "701") location = "استان سیستان و بلوچستان - شهر دشتیاری";
|
296 |
+
if (code == "720") location = "استان سیستان و بلوچستان - شهر راسک";
|
297 |
+
if (code == "366" || code == "367") location = "استان سیستان و بلوچستان - شهر زابل";
|
298 |
+
if (code == "704") location = "استان سیستان و بلوچستان - شهر زابلی";
|
299 |
+
if (code == "361" || code == "362") location = "استان سیستان و بلوچستان - شهر زاهدان";
|
300 |
+
if (code == "369" || code == "370") location = "استان سیستان و بلوچستان - شهر سراوان";
|
301 |
+
if (code == "635") location = "استان سیستان و بلوچستان - شهر سرباز";
|
302 |
+
if (code == "668") location = "استان سیستان و بلوچستان - شهر سیب و سوران";
|
303 |
+
if (code == "533") location = "استان سیستان و بلوچستان - شهر شهرکی و ناروئی(زهک)";
|
304 |
+
if (code == "705") location = "استان سیستان و بلوچستان - شهر شیب آب";
|
305 |
+
if (code == "699") location = "استان سیستان و بلوچستان - شهر فنوج";
|
306 |
+
if (code == "669") location = "استان سیستان و بلوچستان - شهر قصرقند";
|
307 |
+
if (code == "725") location = "استان سیستان و بلوچستان - شهر کنارک";
|
308 |
+
if (code == "597") location = "استان سیستان و بلوچستان - شهر لاشار(اسپکه)";
|
309 |
+
if (code == "611") location = "استان سیستان و بلوچستان - شهر میرجاوه";
|
310 |
+
if (code == "525") location = "استان سیستان و بلوچستان - شهر نیک شهر";
|
311 |
+
if (code == "181") location = "استان خوزستان - شهر آبادان";
|
312 |
+
if (code == "527") location = "استان خوزستان - شهر آغاجاری";
|
313 |
+
if (code == "585") location = "استان خوزستان - شهر اروندکنار";
|
314 |
+
if (code == "685") location = "استان خوزستان - شهر امیدیه";
|
315 |
+
if (code == "663") location = "استان خوزستان - شهر اندیکا";
|
316 |
+
if (code == "192" || code == "193") location = "استان خوزستان - شهر اندیمشک";
|
317 |
+
if (code == "174" || code == "175") location = "استان خوزستان - شهر اهواز";
|
318 |
+
if (code == "183" || code == "184") location = "استان خوزستان - شهر ایذه";
|
319 |
+
if (code == "481") location = "استان خوزستان - شهر باغ ملک";
|
320 |
+
if (code == "706") location = "استان خوزستان - شهر بندر امام خمینی";
|
321 |
+
if (code == "194" || code == "195") location = "استان خوزستان - شهر بندرماهشهر";
|
322 |
+
if (code == "185" || code == "186") location = "استان خوزستان - شهر بهبهان";
|
323 |
+
if (code == "182") location = "استان خوزستان - شهر خرمشهر";
|
324 |
+
if (code == "199" || code == "200") location = "استان خوزستان - شهر دزفول";
|
325 |
+
if (code == "198") location = "استان خوزستان - شهر دشت آزادگان";
|
326 |
+
if (code == "662") location = "استان خوزستان - شهر رامشیر";
|
327 |
+
if (code == "190" || code == "191") location = "استان خوزستان - شهر رامهرمز";
|
328 |
+
if (code == "692") location = "استان خوزستان - شهر سردشت";
|
329 |
+
if (code == "189") location = "استان خوزستان - شهر شادگان";
|
330 |
+
if (code == "707") location = "استان خوزستان - شهر شاوور";
|
331 |
+
if (code == "526") location = "استان خوزستان - شهر شوش";
|
332 |
+
if (code == "187" || code == "188") location = "استان خوزستان - شهر شوشتر";
|
333 |
+
if (code == "729") location = "استان خوزستان - شهر گتوند";
|
334 |
+
if (code == "730") location = "استان خوزستان - شهر لالی";
|
335 |
+
if (code == "196" || code == "197") location = "استان خوزستان - شهر مسجدسلیمان";
|
336 |
+
if (code == "661") location = "استان خوزستان - شهر هندیجان";
|
337 |
+
if (code == "680") location = "استان خوزستان - شهر هویزه";
|
338 |
+
if (code == "643") location = "استان خراسان رضوی - شهر احمدآباد";
|
339 |
+
if (code == "562") location = "استان خراسان رضوی - شهر بجستان";
|
340 |
+
if (code == "572") location = "استان خراسان رضوی - شهر بردسکن";
|
341 |
+
if (code == "074") location = "استان خراسان رضوی - شهر تایباد";
|
342 |
+
if (code == "644") location = "استان خراسان رضوی - شهر تخت جلگه";
|
343 |
+
if (code == "072" || code == "073") location = "استان خراسان رضوی - شهر تربت جام";
|
344 |
+
if (code == "069" || code == "070") location = "استان خراسان رضوی - شهر تربت حیدریه";
|
345 |
+
if (code == "521") location = "استان خراسان رضوی - شهر جغتای";
|
346 |
+
if (code == "573") location = "استان خراسان رضوی - شهر جوین";
|
347 |
+
if (code == "522") location = "استان خراسان رضوی - شهر چناران";
|
348 |
+
if (code == "724") location = "استان خراسان رضوی - شهر خلیل آباد";
|
349 |
+
if (code == "076") location = "استان خراسان رضوی - شهر خواف";
|
350 |
+
if (code == "077") location = "استان خراسان رضوی - شهر درگز";
|
351 |
+
if (code == "650") location = "استان خراسان رضوی - شهر رشتخوار";
|
352 |
+
if (code == "574") location = "استان خراسان رضوی - شهر زبرخان";
|
353 |
+
if (code == "078" || code == "079") location = "استان خراسان رضوی - شهر سبزوار";
|
354 |
+
if (code == "081") location = "استان خراسان رضوی - شهر سرخس";
|
355 |
+
if (code == "084") location = "استان خراسان رضوی - شهر فریمان";
|
356 |
+
if (code == "651") location = "استان خراسان رضوی - شهر فیض آباد";
|
357 |
+
if (code == "086" || code == "087") location = "استان خراسان رضوی - شهر قوچان";
|
358 |
+
if (code == "089" || code == "090") location = "استان خراسان رضوی - شهر کاشمر";
|
359 |
+
if (code == "553") location = "استان خراسان رضوی - شهر کلات";
|
360 |
+
if (code == "091") location = "استان خراسان رضوی - شهر گناباد";
|
361 |
+
if (code == "092" || code == "093" || code == "094") location = "استان خراسان رضوی - شهر مشهد";
|
362 |
+
if (code == "097") location = "استان خراسان رضوی - شهر مشهد منطقه2";
|
363 |
+
if (code == "098") location = "استان خراسان رضوی - شهر مشهد منطقه3";
|
364 |
+
if (code == "096") location = "استان خراسان رضوی - شهر مشهد منطقه1";
|
365 |
+
if (code == "105" || code == "106") location = "استان خراسان رضوی - شهر نیشابور";
|
366 |
+
if (code == "063") location = "استان خراسان شمالی - شهر اسفراین";
|
367 |
+
if (code == "067" || code == "068") location = "استان خراسان شمالی - شهر بجنورد";
|
368 |
+
if (code == "075") location = "استان خراسان شمالی - شهر جاجرم";
|
369 |
+
if (code == "591") location = "استان خراسان شمالی - شهر رازوجرکلان";
|
370 |
+
if (code == "082") location = "استان خراسان شمالی - شهر شیروان";
|
371 |
+
if (code == "635") location = "استان خراسان شمالی - شهر فاروج";
|
372 |
+
if (code == "524") location = "استان خراسان شمالی - شهر مانه و سملقان";
|
373 |
+
if (code == "468") location = "استان چهارمحال و بختیاری - شهر اردل";
|
374 |
+
if (code == "465") location = "استان چهارمحال و بختیاری - شهر بروجن";
|
375 |
+
if (code == "461" || code == "462") location = "استان چهارمحال و بختیاری - شهر شهرکرد";
|
376 |
+
if (code == "467") location = "استان چهارمحال و بختیاری - شهر فارسان";
|
377 |
+
if (code == "555") location = "استان چهارمحال و بختیاری - شهر کوهرنگ";
|
378 |
+
if (code == "633") location = "استان چهارمحال و بختیاری - شهر کیار";
|
379 |
+
if (code == "629") location = "استان چهارمحال و بختیاری - شهر گندمان";
|
380 |
+
if (code == "466") location = "استان چهارمحال و بختیاری - شهر لردگان";
|
381 |
+
if (code == "696") location = "استان چهارمحال و بختیاری - شهر میانکوه";
|
382 |
+
if (code == "721") location = "استان خراسان جنوبی - شهر بشرویه";
|
383 |
+
if (code == "064" || code == "065") location = "استان خراسان جنوبی - شهر بیرجند";
|
384 |
+
if (code == "523") location = "استان خراسان جنوبی - شهر درمیان";
|
385 |
+
if (code == "652") location = "استان خراسان جنوبی - شهر زیرکوه";
|
386 |
+
if (code == "719") location = "استان خراسان جنوبی - شهر سرایان";
|
387 |
+
if (code == "716") location = "استان خراسان جنوبی - شهر سربیشه";
|
388 |
+
if (code == "085") location = "استان خراسان جنوبی - شهر فردوس";
|
389 |
+
if (code == "088") location = "استان خراسان جنوبی - شهر قائنات";
|
390 |
+
if (code == "563") location = "استان خراسان جنوبی - شهر نهبندان";
|
391 |
+
if (code == "529") location = "استان بوشهر - شهر بندر دیلم";
|
392 |
+
if (code == "353") location = "استان بوشهر - شهر بندر گناوه";
|
393 |
+
if (code == "349" || code == "350") location = "استان بوشهر - شهر بوشهر";
|
394 |
+
if (code == "355") location = "استان بوشهر - شهر تنگستان";
|
395 |
+
if (code == "609") location = "استان بوشهر - شهر جم";
|
396 |
+
if (code == "351" || code == "352") location = "استان بوشهر - شهر دشتستان";
|
397 |
+
if (code == "354") location = "استان بوشهر - شهر دشتی";
|
398 |
+
if (code == "732") location = "استان بوشهر - شهر دلوار";
|
399 |
+
if (code == "357") location = "استان بوشهر - شهر دیر";
|
400 |
+
if (code == "532") location = "استان بوشهر - شهر سعد آباد";
|
401 |
+
if (code == "610") location = "استان بوشهر - شهر شبانکاره";
|
402 |
+
if (code == "356") location = "استان بوشهر - شهر کنگان";
|
403 |
+
if (code == "556") location = "استان تهران - شهر اسلامشهر";
|
404 |
+
if (code == "658") location = "استان تهران - شهر پاکدشت";
|
405 |
+
if (code == "001" || code == "002" || code == "003" || code == "004" || code == "005" || code == "006" || code == "007" || code == "008") location = "استان تهران - شهر تهران مرکزی";
|
406 |
+
if (code == "011") location = "استان تهران - شهر تهران جنوب";
|
407 |
+
if (code == "020") location = "استان تهران - شهر تهران شرق";
|
408 |
+
if (code == "025") location = "استان تهران - شهر تهرانشمال";
|
409 |
+
if (code == "015") location = "استان تهران - شهر تهران غرب";
|
410 |
+
if (code == "043") location = "استان تهران - شهر دماوند";
|
411 |
+
if (code == "666") location = "استان تهران - شهر رباط کریم";
|
412 |
+
if (code == "489") location = "استان تهران - شهر ساوجبلاغ";
|
413 |
+
if (code == "044" || code == "045") location = "استان تهران - شهر شمیران";
|
414 |
+
if (code == "048" || code == "049") location = "استان تهران - شهر شهرری";
|
415 |
+
if (code == "490" || code == "491") location = "استان تهران - شهر شهریار";
|
416 |
+
if (code == "695") location = "استان تهران - شهر طالقان";
|
417 |
+
if (code == "659") location = "استان تهران - شهر فیروزکوه";
|
418 |
+
if (code == "031" || code == "032") location = "استان تهران - شهر کرج";
|
419 |
+
if (code == "664") location = "استان تهران - شهر کهریزک";
|
420 |
+
if (code == "717") location = "استان تهران - شهر نظرآباد";
|
421 |
+
if (code == "041" || code == "042") location = "استان تهران - شهر ورامین";
|
422 |
+
if (code == "471" || code == "472") location = " امور خارجه - امور خارجه";
|
423 |
+
if (code == "454") location = "استان ایلام - شهر آبدانان";
|
424 |
+
if (code == "581") location = "استان ایلام - شهر ارکوازی(ملکشاهی)";
|
425 |
+
if (code == "449" || code == "450") location = "استان ایلام - شهر ایلام";
|
426 |
+
if (code == "616") location = "استان ایلام - شهر ایوان";
|
427 |
+
if (code == "534") location = "استان ایلام - شهر بدره";
|
428 |
+
if (code == "455") location = "استان ایلام - شهر دره شهر";
|
429 |
+
if (code == "451") location = "استان ایلام - شهر دهلران";
|
430 |
+
if (code == "726") location = "استان ایلام - شهر زرین آباد";
|
431 |
+
if (code == "634") location = "استان ایلام - شهر شیروان لومار";
|
432 |
+
if (code == "453") location = "استان ایلام - شهر شیروان و چرداول";
|
433 |
+
if (code == "727") location = "استان ایلام - شهر موسیان";
|
434 |
+
if (code == "452") location = "استان ایلام - شهر مهران";
|
435 |
+
if (code == "145" || code == "146") location = "استان اردبیل - شهر اردبیل";
|
436 |
+
if (code == "731") location = "استان اردبیل - شهر ارشق";
|
437 |
+
if (code == "690") location = "استان اردبیل - شهر انگوت";
|
438 |
+
if (code == "601") location = "استان اردبیل - شهر بیله سوار";
|
439 |
+
if (code == "504") location = "استان اردبیل - شهر پارس آباد";
|
440 |
+
if (code == "163") location = "استان اردبیل - شهر خلخال";
|
441 |
+
if (code == "714") location = "استان اردبیل - شهر خورش رستم";
|
442 |
+
if (code == "715") location = "استان اردبیل - شهر سرعین";
|
443 |
+
if (code == "566") location = "استان اردبیل - شهر سنجبد(کوثر)";
|
444 |
+
if (code == "166" || code == "167") location = "استان اردبیل - شهر مشکین شهر";
|
445 |
+
if (code == "161" || code == "162") location = "استان اردبیل - شهر مغان";
|
446 |
+
if (code == "686") location = "استان اردبیل - شهر نمین";
|
447 |
+
if (code == "603") location = "استان اردبیل - شهر نیر";
|
448 |
+
if (code == "619") location = "استان اصفهان - شهر آران و بیدگل";
|
449 |
+
if (code == "118") location = "استان اصفهان - شهر اردستان";
|
450 |
+
if (code == "127" || code == "128" || code == "129") location = "استان اصفهان - شهر اصفهان";
|
451 |
+
if (code == "620") location = "استان اصفهان - شهر باغ بهادران";
|
452 |
+
if (code == "621") location = "استان اصفهان - شهر بوئین و میاندشت";
|
453 |
+
if (code == "549") location = "استان اصفهان - شهر تیران و کرون";
|
454 |
+
if (code == "564") location = "استان اصفهان - شهر جرقویه";
|
455 |
+
if (code == "575") location = "استان اصفهان - شهر چادگان";
|
456 |
+
if (code == "113" || code == "114") location = "استان اصفهان - شهر خمینی شهر";
|
457 |
+
if (code == "122") location = "استان اصفهان - شهر خوانسار";
|
458 |
+
if (code == "540") location = "استان اصفهان - شهر خور و بیابانک";
|
459 |
+
if (code == "660") location = "استان اصفهان - شهر دولت آباد";
|
460 |
+
if (code == "120") location = "استان اصفهان - شهر سمیرم";
|
461 |
+
if (code == "512") location = "استان اصفهان - شهر سمیرم سفلی (دهاقان)";
|
462 |
+
if (code == "510" || code == "511") location = "استان اصفهان - شهر شاهین شهر";
|
463 |
+
if (code == "119") location = "استان اصفهان - شهر شهرضا";
|
464 |
+
if (code == "115") location = "استان اصفهان - شهر فریدن";
|
465 |
+
if (code == "112") location = "استان اصفهان - شهر فریدونشهر";
|
466 |
+
if (code == "110" || code == "111") location = "استان اصفهان - شهر فلاورجان";
|
467 |
+
if (code == "125" || code == "126") location = "استان اصفهان - شهر کاشان";
|
468 |
+
if (code == "565") location = "استان اصفهان - شهر کوهپایه";
|
469 |
+
if (code == "121") location = "استان اصفهان - شهر گلپایگان";
|
470 |
+
if (code == "116" || code == "117") location = "استان اصفهان - شهر لنجان(زرینشهر)";
|
471 |
+
if (code == "541") location = "استان اصفهان - شهر مبارکه";
|
472 |
+
if (code == "622") location = "استان اصفهان - شهر میمه";
|
473 |
+
if (code == "124") location = "استان اصفهان - شهر نائین";
|
474 |
+
if (code == "108" || code == "109") location = "استان اصفهان - شهر نجف آباد";
|
475 |
+
if (code == "123") location = "استان اصفهان - شهر نطنز";
|
476 |
+
if (code == "427" || code == "428") location = "استان زنجان - شهر زنجان";
|
477 |
+
if (code == "507") location = "استان آذربایجان شرقی - شهر ملکان";
|
478 |
+
if (code == "158") location = "استان آذربایجان شرقی - شهر مرند";
|
479 |
+
if (code == "152" || code == "153") location = "استان آذربایجان شرقی - شهر میانه";
|
480 |
+
if (code == "615") location = "استان قزوین - شهر ابهر و خرمدره";
|
481 |
+
return location;
|
482 |
+
}
|
483 |
+
|
484 |
+
/**
|
485 |
+
* @return {boolean}
|
486 |
+
*/
|
487 |
+
function GFPersian_National_ID_Handler(national_id, field_id, message1, message2, message3, is_seperate, show_location) {
|
488 |
+
|
489 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = '';
|
490 |
+
|
491 |
+
if (national_id.value == '')
|
492 |
+
return false;
|
493 |
+
|
494 |
+
national_id.value = national_id.value.replace("-", "").replace("-", "");
|
495 |
+
|
496 |
+
if (isNaN(national_id.value)) {
|
497 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = message1;
|
498 |
+
return false;
|
499 |
+
}
|
500 |
+
|
501 |
+
if (national_id.value.length == 8)
|
502 |
+
national_id.value = '00' + national_id.value;
|
503 |
+
|
504 |
+
if (national_id.value.length == 9)
|
505 |
+
national_id.value = '0' + national_id.value;
|
506 |
+
|
507 |
+
if (national_id.value.length > 10 || national_id.value.length < 8) {
|
508 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = message2;
|
509 |
+
return false;
|
510 |
+
}
|
511 |
+
|
512 |
+
var pre_check = ["0000000000", "1111111111", "2222222222", "3333333333", "4444444444", "5555555555", "6666666666", "7777777777", "8888888888", "9999999999", "0123456789"];
|
513 |
+
var indexOf = pre_check.indexOf(national_id.value);
|
514 |
+
if (indexOf != '-1') {
|
515 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = message3;
|
516 |
+
return false;
|
517 |
+
}
|
518 |
+
|
519 |
+
var location = national_id.value.substring(0, 3);
|
520 |
+
var c = parseInt(national_id.value.charAt(9));
|
521 |
+
var n = parseInt(national_id.value.charAt(0)) * 10 +
|
522 |
+
parseInt(national_id.value.charAt(1)) * 9 +
|
523 |
+
parseInt(national_id.value.charAt(2)) * 8 +
|
524 |
+
parseInt(national_id.value.charAt(3)) * 7 +
|
525 |
+
parseInt(national_id.value.charAt(4)) * 6 +
|
526 |
+
parseInt(national_id.value.charAt(5)) * 5 +
|
527 |
+
parseInt(national_id.value.charAt(6)) * 4 +
|
528 |
+
parseInt(national_id.value.charAt(7)) * 3 +
|
529 |
+
parseInt(national_id.value.charAt(8)) * 2;
|
530 |
+
var r = n - parseInt(n / 11) * 11;
|
531 |
+
|
532 |
+
if ((r == 0 && r == c) || (r == 1 && c == 1) || (r > 1 && c == 11 - r)) {
|
533 |
+
if (is_seperate) {
|
534 |
+
if (national_id.value.length == 10)
|
535 |
+
national_id.value = national_id.value.substring(0, 3) + "-" + national_id.value.substring(3, 9) + "-" + national_id.value.substring(9, 10);
|
536 |
+
}
|
537 |
+
if (show_location) {
|
538 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = GFPersian_National_ID_Location(location);
|
539 |
+
return true;
|
540 |
+
}
|
541 |
+
}
|
542 |
+
else {
|
543 |
+
document.getElementById("ir_national_id_location_" + field_id).innerHTML = message3;
|
544 |
+
return false;
|
545 |
+
}
|
546 |
+
}
|
assets/js/national_id.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function GFPersian_National_ID_Location(e){var a="";return"169"==e&&(a="استان آذربایجان شرقی - شهر آذر شهر"),"170"==e&&(a="استان آذربایجان شرقی - شهر اسکو"),"149"!=e&&"150"!=e||(a="استان آذربایجان شرقی - شهر اهر"),"171"==e&&(a="استان آذربایجان شرقی - شهر بستان آباد"),"168"==e&&(a="استان آذربایجان شرقی - شهر بناب"),"136"!=e&&"137"!=e&&"138"!=e||(a="استان آذربایجان شرقی - شهر تبریز"),"545"==e&&(a="استان آذربایجان شرقی - شهر ترکمانچای"),"505"==e&&(a="استان آذربایجان شرقی - شهر جلفا"),"636"==e&&(a="استان آذربایجان شرقی - شهر چاروایماق"),"164"!=e&&"165"!=e||(a="استان آذربایجان شرقی - شهر سراب"),"172"==e&&(a="استان آذربایجان شرقی - شهر شبستر"),"623"==e&&(a="استان آذربایجان شرقی - شهر صوفیان"),"506"==e&&(a="استان آذربایجان شرقی - شهر عجب شیر"),"519"==e&&(a="استان آذربایجان شرقی - شهر کلیبر"),"154"!=e&&"155"!=e||(a="استان آذربایجان شرقی - شهر مراغه"),"567"==e&&(a="استان آذربایجان شرقی - شهر ورزقان"),"173"==e&&(a="استان آذربایجان شرقی - شهر هریس"),"159"!=e&&"160"!=e||(a="استان آذربایجان شرقی - شهر هشترود"),"604"==e&&(a="استان آذربایجان شرقی - شهر هوراند"),"274"!=e&&"275"!=e||(a="استان آذربایجان غربی - شهر ارومیه"),"295"==e&&(a="استان آذربایجان غربی - شهر اشنویه"),"637"==e&&(a="استان آذربایجان غربی - شهر انزل"),"292"==e&&(a="استان آذربایجان غربی - شهر بوکان"),"492"==e&&(a="استان آذربایجان غربی - شهر پلدشت"),"289"==e&&(a="استان آذربایجان غربی - شهر پیرانشهر"),"677"==e&&(a="استان آذربایجان غربی - شهر تخت سلیمان"),"294"==e&&(a="استان آذربایجان غربی - شهر تکاب"),"493"==e&&(a="استان آذربایجان غربی - شهر چایپاره"),"279"!=e&&"280"!=e||(a="استان آذربایجان غربی - شهر خوی"),"288"==e&&(a="استان آذربایجان غربی - شهر سردشت"),"284"!=e&&"285"!=e||(a="استان آذربایجان غربی - شهر سلماس"),"638"==e&&(a="استان آذربایجان غربی - شهر سیلوانه"),"291"==e&&(a="استان آذربایجان غربی - شهر سیه چشمه(چالدران)"),"640"==e&&(a="استان آذربایجان غربی - شهر شوط"),"293"==e&&(a="استان آذربایجان غربی - شهر شاهین دژ"),"675"==e&&(a="استان آذربایجان غربی - شهر کشاورز"),"282"!=e&&"283"!=e||(a="استان آذربایجان غربی - شهر ماکو"),"286"!=e&&"287"!=e||(a="استان آذربایجان غربی - شهر مهاباد"),"296"!=e&&"297"!=e||(a="استان آذربایجان غربی - شهر میاندوآب"),"290"==e&&(a="استان آذربایجان غربی - شهر نقده"),"400"!=e&&"401"!=e||(a="استان همدان - شهر اسدآباد"),"404"!=e&&"405"!=e||(a="استان همدان - شهر بهار"),"397"==e&&(a="استان همدان - شهر تویسرکان"),"398"!=e&&"399"!=e||(a="استان همدان - شهر رزن"),"647"==e&&(a="استان همدان - شهر شراء و پیشخوار"),"502"==e&&(a="استان همدان - شهر فامنین"),"584"==e&&(a="استان همدان - شهر قلقل رود"),"402"!=e&&"403"!=e||(a="استان همدان - شهر کبودرآهنگ"),"392"!=e&&"393"!=e||(a="استان همدان - شهر ملایر"),"395"!=e&&"396"!=e||(a="استان همدان - شهر نهاوند"),"386"!=e&&"387"!=e||(a="استان همدان - شهر همدان"),"503"==e&&(a="استان یزد - شهر ابرکوه"),"444"==e&&(a="استان یزد - شهر اردکان"),"551"==e&&(a="استان یزد - شهر اشکذر"),"447"==e&&(a="استان یزد - شهر بافق"),"561"==e&&(a="استان یزد - شهر بهاباد"),"445"==e&&(a="استان یزد - شهر تفت"),"718"==e&&(a="استان یزد - شهر دستگردان"),"083"==e&&(a="استان یزد - شهر طبس"),"446"==e&&(a="استان یزد - شهر مهریز"),"448"==e&&(a="استان یزد - شهر میبد"),"552"==e&&(a="استان یزد - شهر نیر"),"543"==e&&(a="استان یزد - شهر هرات و مروست"),"442"!=e&&"443"!=e||(a="استان یزد - شهر یزد"),"051"==e&&(a="استان مرکزی - شهر آشتیان"),"052"!=e&&"053"!=e||(a="استان مرکزی - شهر اراک"),"058"==e&&(a="استان مرکزی - شهر تفرش"),"055"==e&&(a="استان مرکزی - شهر خمین"),"617"==e&&(a="استان مرکزی - شهر خنداب"),"057"==e&&(a="استان مرکزی - شهر دلیجان"),"618"==e&&(a="استان مرکزی - شهر زرند مرکزی"),"059"!=e&&"060"!=e||(a="استان مرکزی - شهر ساوه"),"061"!=e&&"062"!=e||(a="استان مرکزی - شهر سربند"),"544"==e&&(a="استان مرکزی - شهر فراهان"),"056"==e&&(a="استان مرکزی - شهر محلات"),"571"==e&&(a="استان مرکزی - شهر وفس"),"593"==e&&(a="استان مرکزی - شهر هندودر"),"667"==e&&(a="استان هرمزگان - شهر ابوموسی"),"348"==e&&(a="استان هرمزگان - شهر بستک"),"586"==e&&(a="استان هرمزگان - شهر بشاگرد"),"338"!=e&&"339"!=e||(a="استان هرمزگان - شهر بندرعباس"),"343"!=e&&"344"!=e||(a="استان هرمزگان - شهر بندرلنگه"),"346"==e&&(a="استان هرمزگان - شهر جاسک"),"337"==e&&(a="استان هرمزگان - شهر حاجی آباد"),"554"==e&&(a="استان هرمزگان - شهر خمیر"),"469"==e&&(a="استان هرمزگان - شهر رودان"),"537"==e&&(a="استان هرمزگان - شهر فین"),"345"==e&&(a="استان هرمزگان - شهر قشم"),"470"==e&&(a="استان هرمزگان - شهر گاوبندی"),"341"!=e&&"342"!=e||(a="استان هرمزگان - شهر میناب"),"483"!=e&&"484"!=e||(a="استان لرستان - شهر ازنا"),"557"==e&&(a="استان لرستان - شهر اشترینان"),"418"==e&&(a="استان لرستان - شهر الشتر"),"416"!=e&&"417"!=e||(a="استان لرستان - شهر الیگودرز"),"412"!=e&&"413"!=e||(a="استان لرستان - شهر بروجرد"),"592"==e&&(a="استان لرستان - شهر پاپی"),"612"==e&&(a="استان لرستان - شهر چغلوندی"),"613"==e&&(a="استان لرستان - شهر چگنی"),"406"!=e&&"407"!=e||(a="استان لرستان - شهر خرم آباد"),"421"==e&&(a="استان لرستان - شهر دورود"),"598"==e&&(a="استان لرستان - شهر رومشکان"),"419"==e&&(a="استان لرستان - شهر کوهدشت"),"385"==e&&(a="استان لرستان - شهر ملاوی(پلدختر)"),"420"==e&&(a="استان لرستان - شهر نورآباد(دلفان)"),"528"==e&&(a="استان لرستان - شهر ویسیان"),"213"!=e&&"214"!=e||(a="استان مازندران - شهر آمل"),"205"!=e&&"206"!=e||(a="استان مازندران - شهر بابل"),"498"==e&&(a="استان مازندران - شهر بابل"),"568"==e&&(a="استان مازندران - شهر بندپی"),"711"==e&&(a="استان مازندران - شهر بندپی شرقی"),"217"!=e&&"218"!=e||(a="استان مازندران - شهر بهشهر"),"221"==e&&(a="استان مازندران - شهر تنکابن"),"582"==e&&(a="استان مازندران - شهر جویبار"),"483"==e&&(a="استان مازندران - شهر چالوس"),"625"==e&&(a="استان مازندران - شهر چمستان"),"576"==e&&(a="استان مازندران - شهر چهاردانگه"),"578"==e&&(a="استان مازندران - شهر دودانگه"),"227"==e&&(a="استان مازندران - شهر رامسر"),"208"!=e&&"209"!=e||(a="استان مازندران - شهر ساری"),"225"==e&&(a="استان مازندران - شهر سوادکوه"),"577"==e&&(a="استان مازندران - شهر شیرگاه"),"712"==e&&(a="استان مازندران - شهر عباس آباد"),"215"!=e&&"216"!=e||(a="استان مازندران - شهر قائمشهر"),"626"==e&&(a="استان مازندران - شهر کجور"),"627"==e&&(a="استان مازندران - شهر کلاردشت"),"579"==e&&(a="استان مازندران - شهر گلوگاه"),"713"==e&&(a="استان مازندران - شهر میاندورود"),"499"==e&&(a="استان مازندران - شهر نکاء"),"222"==e&&(a="استان مازندران - شهر نور"),"219"!=e&&"220"!=e||(a="استان مازندران - شهر نوشهر"),"500"!=e&&"501"!=e||(a="استان مازندران - شهر هراز و محمودآباد"),"623"==e&&(a="استان گلستان - شهر آزادشهر"),"497"==e&&(a="استان گلستان - شهر آق قلا"),"223"==e&&(a="استان گلستان - شهر بندرترکمن"),"689"==e&&(a="استان گلستان - شهر بندرگز"),"487"==e&&(a="استان گلستان - شهر رامیان"),"226"==e&&(a="استان گلستان - شهر علی آباد"),"224"==e&&(a="استان گلستان - شهر کردکوی"),"386"==e&&(a="استان گلستان - شهر کلاله"),"211"!=e&&"212"!=e||(a="استان گلستان - شهر گرگان"),"628"==e&&(a="استان گلستان - شهر گمیشان"),"202"!=e&&"203"!=e||(a="استان گلستان - شهر گنبد کاووس"),"531"==e&&(a="استان گلستان - شهر مراوه تپه"),"288"==e&&(a="استان گلستان - شهر مینودشت"),"261"==e&&(a="استان گیلان - شهر آستارا"),"273"==e&&(a="استان گیلان - شهر آستانه"),"630"==e&&(a="استان گیلان - شهر املش"),"264"==e&&(a="استان گیلان - شهر بندرانزلی"),"518"==e&&(a="استان گیلان - شهر خمام"),"631"==e&&(a="استان گیلان - شهر رحیم آباد"),"258"!=e&&"259"!=e||(a="استان گیلان - شهر رشت"),"570"==e&&(a="استان گیلان - شهر رضوانشهر"),"265"==e&&(a="استان گیلان - شهر رودبار"),"268"!=e&&"269"!=e||(a="استان گیلان - شهر رودسر"),"653"==e&&(a="استان گیلان - شهر سنگر"),"517"==e&&(a="استان گیلان - شهر سیاهکل"),"569"==e&&(a="استان گیلان - شهر شفت"),"267"==e&&(a="استان گیلان - شهر صومعه سرا"),"262"!=e&&"263"!=e||(a="استان گیلان - شهر طالش"),"593"==e&&(a="استان گیلان - شهر عمارلو"),"266"==e&&(a="استان گیلان - شهر فومن"),"693"==e&&(a="استان گیلان - شهر کوچصفهان"),"271"!=e&&"272"!=e||(a="استان گیلان - شهر لاهیجان"),"694"==e&&(a="استان گیلان - شهر لشت نشاء"),"270"==e&&(a="استان گیلان - شهر لنگرود"),"516"==e&&(a="استان گیلان - شهر ماسال و شاندرمن"),"333"!=e&&"334"!=e||(a="استان کرمانشاه - شهر اسلام آباد"),"691"==e&&(a="استان کرمانشاه - شهر باینگان"),"322"!=e&&"323"!=e||(a="استان کرمانشاه - شهر پاوه"),"595"==e&&(a="استان کرمانشاه - شهر ثلاث باباجانی"),"395"==e&&(a="استان کرمانشاه - شهر جوانرود"),"641"==e&&(a="استان کرمانشاه - شهر حمیل"),"596"==e&&(a="استان کرمانشاه - شهر روانسر"),"336"==e&&(a="استان کرمانشاه - شهر سرپل ذهاب"),"335"==e&&(a="استان کرمانشاه - شهر سنقر"),"496"==e&&(a="استان کرمانشاه - شهر صحنه"),"337"==e&&(a="استان کرمانشاه - شهر قصرشیرین"),"324"!=e&&"325"!=e||(a="استان کرمانشاه - شهر کرمانشاه"),"394"==e&&(a="استان کرمانشاه - شهر کرند"),"330"==e&&(a="استان کرمانشاه - شهر کنگاور"),"332"==e&&(a="استان کرمانشاه - شهر گیلانغرب"),"331"==e&&(a="استان کرمانشاه - شهر هرسین"),"687"==e&&(a="استان کهکیلویه و بویراحمد - شهر باشت"),"422"!=e&&"423"!=e||(a="استان کهکیلویه و بویراحمد - شهر بویراحمد(یاسوج)"),"599"==e&&(a="استان کهکیلویه و بویراحمد - شهر بهمنی"),"600"==e&&(a="استان کهکیلویه و بویراحمد - شهر چاروسا"),"688"==e&&(a="استان کهکیلویه و بویراحمد - شهر دروهان"),"424"!=e&&"425"!=e||(a="استان کهکیلویه و بویراحمد - شهر کهکیلویه(دهدشت)"),"426"==e&&(a="استان کهکیلویه و بویراحمد - شهر گچساران(دوگنبدان)"),"550"==e&&(a="استان کهکیلویه و بویراحمد - شهر لنده"),"697"==e&&(a="استان کهکیلویه و بویراحمد - شهر مارگون"),"384"==e&&(a="استان کردستان - شهر بانه"),"377"!=e&&"378"!=e||(a="استان کردستان - شهر بیجار"),"558"==e&&(a="استان کردستان - شهر دهگلان"),"385"==e&&(a="استان کردستان - شهر دیواندره"),"646"==e&&(a="استان کردستان - شهر سروآباد"),"375"!=e&&"376"!=e||(a="استان کردستان - شهر سقز"),"372"!=e&&"373"!=e||(a="استان کردستان - شهر سنندج"),"379"!=e&&"380"!=e||(a="استان کردستان - شهر قروه"),"383"==e&&(a="استان کردستان - شهر کامیاران"),"674"==e&&(a="استان کردستان - شهر کرانی"),"381"!=e&&"382"!=e||(a="استان کردستان - شهر مریوان"),"676"==e&&(a="استان کردستان - شهر نمشیر"),"722"==e&&(a="استان کرمان - شهر ارزونیه"),"542"==e&&(a="استان کرمان - شهر انار"),"312"!=e&&"313"!=e||(a="استان کرمان - شهر بافت"),"317"==e&&(a="استان کرمان - شهر بردسیر"),"310"!=e&&"311"!=e||(a="استان کرمان - شهر بم"),"302"!=e&&"303"!=e||(a="استان کرمان - شهر جیرفت"),"583"==e&&(a="استان کرمان - شهر رابر"),"321"==e&&(a="استان کرمان - شهر راور"),"382"==e&&(a="استان کرمان - شهر راین"),"304"!=e&&"305"!=e||(a="استان کرمان - شهر رفسنجان"),"536"==e&&(a="استان کرمان - شهر رودبار کهنوج"),"605"==e&&(a="استان کرمان - شهر ریگان"),"308"!=e&&"309"!=e||(a="استان کرمان - شهر زرند"),"306"!=e&&"307"!=e||(a="استان کرمان - شهر سیرجان"),"319"==e&&(a="استان کرمان - شهر شهداد"),"313"!=e&&"314"!=e||(a="استان کرمان - شهر شهربابک"),"606"==e&&(a="استان کرمان - شهر عنبرآباد"),"320"==e&&(a="استان کرمان - شهر فهرج"),"698"==e&&(a="استان کرمان - شهر قلعه گنج"),"298"!=e&&"299"!=e||(a="استان کرمان - شهر کرمان"),"535"==e&&(a="استان کرمان - شهر کوهبنان"),"315"!=e&&"316"!=e||(a="استان کرمان - شهر کهنوج"),"318"==e&&(a="استان کرمان - شهر گلباف"),"607"==e&&(a="استان کرمان - شهر ماهان"),"608"==e&&(a="استان کرمان - شهر منوجان"),"508"==e&&(a="استان قزوین - شهر آبیک"),"538"==e&&(a="استان قزوین - شهر آوج"),"728"==e&&(a="استان قزوین - شهر البرز"),"509"==e&&(a="استان قزوین - شهر بوئین زهرا"),"438"!=e&&"439"!=e||(a="استان قزوین - شهر تاکستان"),"580"==e&&(a="استان قزوین - شهر رودبار الموت"),"590"==e&&(a="استان قزوین - شهر رودبار شهرستان"),"559"==e&&(a="استان قزوین - شهر ضیاءآباد"),"588"==e&&(a="استان قزوین - شهر طارم سفلی"),"431"!=e&&"432"!=e||(a="استان قزوین - شهر قزوین"),"037"!=e&&"038"!=e||(a="استان قم - شهر قم"),"702"==e&&(a="استان قم - شهر کهک"),"240"!=e&&"241"!=e||(a="استان فارس - شهر آباده"),"670"==e&&(a="استان فارس - شهر آباده طشک"),"648"==e&&(a="استان فارس - شهر ارسنجان"),"252"==e&&(a="استان فارس - شهر استهبان"),"678"==e&&(a="استان فارس - شهر اشکنان"),"253"==e&&(a="استان فارس - شهر اقلید"),"649"==e&&(a="استان فارس - شهر اوز"),"513"==e&&(a="استان فارس - شهر بوانات"),"546"==e&&(a="استان فارس - شهر بیضا"),"671"==e&&(a="استان فارس - شهر جویم"),"246"!=e&&"247"!=e||(a="استان فارس - شهر جهرم"),"654"==e&&(a="استان فارس - شهر حاجی آباد(زرین دشت)"),"548"==e&&(a="استان فارس - شهر خرامه"),"547"==e&&(a="استان فارس - شهر خشت و کمارج"),"655"==e&&(a="استان فارس - شهر خفر"),"248"!=e&&"249"!=e||(a="استان فارس - شهر داراب"),"253"==e&&(a="استان فارس - شهر سپیدان"),"514"==e&&(a="استان فارس - شهر سروستان"),"665"==e&&(a="استان فارس - شهر سعادت آباد"),"673"==e&&(a="استان فارس - شهر شیبکوه"),"228"!=e&&"229"!=e&&"230"!=e||(a="استان فارس - شهر شیراز"),"679"==e&&(a="استان فارس - شهر فراشبند"),"256"!=e&&"257"!=e||(a="استان فارس - شهر فسا"),"244"!=e&&"245"!=e||(a="استان فارس - شهر فیروزآباد"),"681"==e&&(a="استان فارس - شهر قنقری(خرم بید)"),"723"==e&&(a="استان فارس - شهر قیروکارزین"),"236"!=e&&"237"!=e||(a="استان فارس - شهر کازرون"),"683"==e&&(a="استان فارس - شهر کوار"),"656"==e&&(a="استان فارس - شهر کراش"),"250"!=e&&"251"!=e||(a="استان فارس - شهر لارستان"),"515"==e&&(a="استان فارس - شهر لامرد"),"242"!=e&&"243"!=e||(a="استان فارس - شهر مرودشت"),"238"!=e&&"239"!=e||(a="استان فارس - شهر ممسنی"),"657"==e&&(a="استان فارس - شهر مهر"),"255"==e&&(a="استان فارس - شهر نی ریز"),"684"==e&&(a="استان سمنان - شهر ایوانکی"),"700"==e&&(a="استان سمنان - شهر بسطام"),"642"==e&&(a="استان سمنان - شهر بیارجمند"),"457"==e&&(a="استان سمنان - شهر دامغان"),"456"==e&&(a="استان سمنان - شهر سمنان"),"458"!=e&&"459"!=e||(a="استان سمنان - شهر شاهرود"),"460"==e&&(a="استان سمنان - شهر گرمسار"),"530"==e&&(a="استان سمنان - شهر مهدیشهر"),"520"==e&&(a="استان سمنان - شهر میامی"),"358"!=e&&"359"!=e||(a="استان سیستان و بلوچستان - شهر ایرانشهر"),"682"==e&&(a="استان سیستان و بلوچستان - شهر بزمان"),"703"==e&&(a="استان سیستان و بلوچستان - شهر بمپور"),"364"!=e&&"365"!=e||(a="استان سیستان و بلوچستان - شهر چابهار"),"371"==e&&(a="استان سیستان و بلوچستان - شهر خاش"),"701"==e&&(a="استان سیستان و بلوچستان - شهر دشتیاری"),"720"==e&&(a="استان سیستان و بلوچستان - شهر راسک"),"366"!=e&&"367"!=e||(a="استان سیستان و بلوچستان - شهر زابل"),"704"==e&&(a="استان سیستان و بلوچستان - شهر زابلی"),"361"!=e&&"362"!=e||(a="استان سیستان و بلوچستان - شهر زاهدان"),"369"!=e&&"370"!=e||(a="استان سیستان و بلوچستان - شهر سراوان"),"635"==e&&(a="استان سیستان و بلوچستان - شهر سرباز"),"668"==e&&(a="استان سیستان و بلوچستان - شهر سیب و سوران"),"533"==e&&(a="استان سیستان و بلوچستان - شهر شهرکی و ناروئی(زهک)"),"705"==e&&(a="استان سیستان و بلوچستان - شهر شیب آب"),"699"==e&&(a="استان سیستان و بلوچستان - شهر فنوج"),"669"==e&&(a="استان سیستان و بلوچستان - شهر قصرقند"),"725"==e&&(a="استان سیستان و بلوچستان - شهر کنارک"),"597"==e&&(a="استان سیستان و بلوچستان - شهر لاشار(اسپکه)"),"611"==e&&(a="استان سیستان و بلوچستان - شهر میرجاوه"),"525"==e&&(a="استان سیستان و بلوچستان - شهر نیک شهر"),"181"==e&&(a="استان خوزستان - شهر آبادان"),"527"==e&&(a="استان خوزستان - شهر آغاجاری"),"585"==e&&(a="استان خوزستان - شهر اروندکنار"),"685"==e&&(a="استان خوزستان - شهر امیدیه"),"663"==e&&(a="استان خوزستان - شهر اندیکا"),"192"!=e&&"193"!=e||(a="استان خوزستان - شهر اندیمشک"),"174"!=e&&"175"!=e||(a="استان خوزستان - شهر اهواز"),"183"!=e&&"184"!=e||(a="استان خوزستان - شهر ایذه"),"481"==e&&(a="استان خوزستان - شهر باغ ملک"),"706"==e&&(a="استان خوزستان - شهر بندر امام خمینی"),"194"!=e&&"195"!=e||(a="استان خوزستان - شهر بندرماهشهر"),"185"!=e&&"186"!=e||(a="استان خوزستان - شهر بهبهان"),"182"==e&&(a="استان خوزستان - شهر خرمشهر"),"199"!=e&&"200"!=e||(a="استان خوزستان - شهر دزفول"),"198"==e&&(a="استان خوزستان - شهر دشت آزادگان"),"662"==e&&(a="استان خوزستان - شهر رامشیر"),"190"!=e&&"191"!=e||(a="استان خوزستان - شهر رامهرمز"),"692"==e&&(a="استان خوزستان - شهر سردشت"),"189"==e&&(a="استان خوزستان - شهر شادگان"),"707"==e&&(a="استان خوزستان - شهر شاوور"),"526"==e&&(a="استان خوزستان - شهر شوش"),"187"!=e&&"188"!=e||(a="استان خوزستان - شهر شوشتر"),"729"==e&&(a="استان خوزستان - شهر گتوند"),"730"==e&&(a="استان خوزستان - شهر لالی"),"196"!=e&&"197"!=e||(a="استان خوزستان - شهر مسجدسلیمان"),"661"==e&&(a="استان خوزستان - شهر هندیجان"),"680"==e&&(a="استان خوزستان - شهر هویزه"),"643"==e&&(a="استان خراسان رضوی - شهر احمدآباد"),"562"==e&&(a="استان خراسان رضوی - شهر بجستان"),"572"==e&&(a="استان خراسان رضوی - شهر بردسکن"),"074"==e&&(a="استان خراسان رضوی - شهر تایباد"),"644"==e&&(a="استان خراسان رضوی - شهر تخت جلگه"),"072"!=e&&"073"!=e||(a="استان خراسان رضوی - شهر تربت جام"),"069"!=e&&"070"!=e||(a="استان خراسان رضوی - شهر تربت حیدریه"),"521"==e&&(a="استان خراسان رضوی - شهر جغتای"),"573"==e&&(a="استان خراسان رضوی - شهر جوین"),"522"==e&&(a="استان خراسان رضوی - شهر چناران"),"724"==e&&(a="استان خراسان رضوی - شهر خلیل آباد"),"076"==e&&(a="استان خراسان رضوی - شهر خواف"),"077"==e&&(a="استان خراسان رضوی - شهر درگز"),"650"==e&&(a="استان خراسان رضوی - شهر رشتخوار"),"574"==e&&(a="استان خراسان رضوی - شهر زبرخان"),"078"!=e&&"079"!=e||(a="استان خراسان رضوی - شهر سبزوار"),"081"==e&&(a="استان خراسان رضوی - شهر سرخس"),"084"==e&&(a="استان خراسان رضوی - شهر فریمان"),"651"==e&&(a="استان خراسان رضوی - شهر فیض آباد"),"086"!=e&&"087"!=e||(a="استان خراسان رضوی - شهر قوچان"),"089"!=e&&"090"!=e||(a="استان خراسان رضوی - شهر کاشمر"),"553"==e&&(a="استان خراسان رضوی - شهر کلات"),"091"==e&&(a="استان خراسان رضوی - شهر گناباد"),"092"!=e&&"093"!=e&&"094"!=e||(a="استان خراسان رضوی - شهر مشهد"),"097"==e&&(a="استان خراسان رضوی - شهر مشهد منطقه2"),"098"==e&&(a="استان خراسان رضوی - شهر مشهد منطقه3"),"096"==e&&(a="استان خراسان رضوی - شهر مشهد منطقه1"),"105"!=e&&"106"!=e||(a="استان خراسان رضوی - شهر نیشابور"),"063"==e&&(a="استان خراسان شمالی - شهر اسفراین"),"067"!=e&&"068"!=e||(a="استان خراسان شمالی - شهر بجنورد"),"075"==e&&(a="استان خراسان شمالی - شهر جاجرم"),"591"==e&&(a="استان خراسان شمالی - شهر رازوجرکلان"),"082"==e&&(a="استان خراسان شمالی - شهر شیروان"),"635"==e&&(a="استان خراسان شمالی - شهر فاروج"),"524"==e&&(a="استان خراسان شمالی - شهر مانه و سملقان"),"468"==e&&(a="استان چهارمحال و بختیاری - شهر اردل"),"465"==e&&(a="استان چهارمحال و بختیاری - شهر بروجن"),"461"!=e&&"462"!=e||(a="استان چهارمحال و بختیاری - شهر شهرکرد"),"467"==e&&(a="استان چهارمحال و بختیاری - شهر فارسان"),"555"==e&&(a="استان چهارمحال و بختیاری - شهر کوهرنگ"),"633"==e&&(a="استان چهارمحال و بختیاری - شهر کیار"),"629"==e&&(a="استان چهارمحال و بختیاری - شهر گندمان"),"466"==e&&(a="استان چهارمحال و بختیاری - شهر لردگان"),"696"==e&&(a="استان چهارمحال و بختیاری - شهر میانکوه"),"721"==e&&(a="استان خراسان جنوبی - شهر بشرویه"),"064"!=e&&"065"!=e||(a="استان خراسان جنوبی - شهر بیرجند"),"523"==e&&(a="استان خراسان جنوبی - شهر درمیان"),"652"==e&&(a="استان خراسان جنوبی - شهر زیرکوه"),"719"==e&&(a="استان خراسان جنوبی - شهر سرایان"),"716"==e&&(a="استان خراسان جنوبی - شهر سربیشه"),"085"==e&&(a="استان خراسان جنوبی - شهر فردوس"),"088"==e&&(a="استان خراسان جنوبی - شهر قائنات"),"563"==e&&(a="استان خراسان جنوبی - شهر نهبندان"),"529"==e&&(a="استان بوشهر - شهر بندر دیلم"),"353"==e&&(a="استان بوشهر - شهر بندر گناوه"),"349"!=e&&"350"!=e||(a="استان بوشهر - شهر بوشهر"),"355"==e&&(a="استان بوشهر - شهر تنگستان"),"609"==e&&(a="استان بوشهر - شهر جم"),"351"!=e&&"352"!=e||(a="استان بوشهر - شهر دشتستان"),"354"==e&&(a="استان بوشهر - شهر دشتی"),"732"==e&&(a="استان بوشهر - شهر دلوار"),"357"==e&&(a="استان بوشهر - شهر دیر"),"532"==e&&(a="استان بوشهر - شهر سعد آباد"),"610"==e&&(a="استان بوشهر - شهر شبانکاره"),"356"==e&&(a="استان بوشهر - شهر کنگان"),"556"==e&&(a="استان تهران - شهر اسلامشهر"),"658"==e&&(a="استان تهران - شهر پاکدشت"),"001"!=e&&"002"!=e&&"003"!=e&&"004"!=e&&"005"!=e&&"006"!=e&&"007"!=e&&"008"!=e||(a="استان تهران - شهر تهران مرکزی"),"011"==e&&(a="استان تهران - شهر تهران جنوب"),"020"==e&&(a="استان تهران - شهر تهران شرق"),"025"==e&&(a="استان تهران - شهر تهرانشمال"),"015"==e&&(a="استان تهران - شهر تهران غرب"),"043"==e&&(a="استان تهران - شهر دماوند"),"666"==e&&(a="استان تهران - شهر رباط کریم"),"489"==e&&(a="استان تهران - شهر ساوجبلاغ"),"044"!=e&&"045"!=e||(a="استان تهران - شهر شمیران"),"048"!=e&&"049"!=e||(a="استان تهران - شهر شهرری"),"490"!=e&&"491"!=e||(a="استان تهران - شهر شهریار"),"695"==e&&(a="استان تهران - شهر طالقان"),"659"==e&&(a="استان تهران - شهر فیروزکوه"),"031"!=e&&"032"!=e||(a="استان تهران - شهر کرج"),"664"==e&&(a="استان تهران - شهر کهریزک"),"717"==e&&(a="استان تهران - شهر نظرآباد"),"041"!=e&&"042"!=e||(a="استان تهران - شهر ورامین"),"471"!=e&&"472"!=e||(a=" امور خارجه - امور خارجه"),"454"==e&&(a="استان ایلام - شهر آبدانان"),"581"==e&&(a="استان ایلام - شهر ارکوازی(ملکشاهی)"),"449"!=e&&"450"!=e||(a="استان ایلام - شهر ایلام"),"616"==e&&(a="استان ایلام - شهر ایوان"),"534"==e&&(a="استان ایلام - شهر بدره"),"455"==e&&(a="استان ایلام - شهر دره شهر"),"451"==e&&(a="استان ایلام - شهر دهلران"),"726"==e&&(a="استان ایلام - شهر زرین آباد"),"634"==e&&(a="استان ایلام - شهر شیروان لومار"),"453"==e&&(a="استان ایلام - شهر شیروان و چرداول"),"727"==e&&(a="استان ایلام - شهر موسیان"),"452"==e&&(a="استان ایلام - شهر مهران"),"145"!=e&&"146"!=e||(a="استان اردبیل - شهر اردبیل"),"731"==e&&(a="استان اردبیل - شهر ارشق"),"690"==e&&(a="استان اردبیل - شهر انگوت"),"601"==e&&(a="استان اردبیل - شهر بیله سوار"),"504"==e&&(a="استان اردبیل - شهر پارس آباد"),"163"==e&&(a="استان اردبیل - شهر خلخال"),"714"==e&&(a="استان اردبیل - شهر خورش رستم"),"715"==e&&(a="استان اردبیل - شهر سرعین"),"566"==e&&(a="استان اردبیل - شهر سنجبد(کوثر)"),"166"!=e&&"167"!=e||(a="استان اردبیل - شهر مشکین شهر"),"161"!=e&&"162"!=e||(a="استان اردبیل - شهر مغان"),"686"==e&&(a="استان اردبیل - شهر نمین"),"603"==e&&(a="استان اردبیل - شهر نیر"),"619"==e&&(a="استان اصفهان - شهر آران و بیدگل"),"118"==e&&(a="استان اصفهان - شهر اردستان"),"127"!=e&&"128"!=e&&"129"!=e||(a="استان اصفهان - شهر اصفهان"),"620"==e&&(a="استان اصفهان - شهر باغ بهادران"),"621"==e&&(a="استان اصفهان - شهر بوئین و میاندشت"),"549"==e&&(a="استان اصفهان - شهر تیران و کرون"),"564"==e&&(a="استان اصفهان - شهر جرقویه"),"575"==e&&(a="استان اصفهان - شهر چادگان"),"113"!=e&&"114"!=e||(a="استان اصفهان - شهر خمینی شهر"),"122"==e&&(a="استان اصفهان - شهر خوانسار"),"540"==e&&(a="استان اصفهان - شهر خور و بیابانک"),"660"==e&&(a="استان اصفهان - شهر دولت آباد"),"120"==e&&(a="استان اصفهان - شهر سمیرم"),"512"==e&&(a="استان اصفهان - شهر سمیرم سفلی (دهاقان)"),"510"!=e&&"511"!=e||(a="استان اصفهان - شهر شاهین شهر"),"119"==e&&(a="استان اصفهان - شهر شهرضا"),"115"==e&&(a="استان اصفهان - شهر فریدن"),"112"==e&&(a="استان اصفهان - شهر فریدونشهر"),"110"!=e&&"111"!=e||(a="استان اصفهان - شهر فلاورجان"),"125"!=e&&"126"!=e||(a="استان اصفهان - شهر کاشان"),"565"==e&&(a="استان اصفهان - شهر کوهپایه"),"121"==e&&(a="استان اصفهان - شهر گلپایگان"),"116"!=e&&"117"!=e||(a="استان اصفهان - شهر لنجان(زرینشهر)"),"541"==e&&(a="استان اصفهان - شهر مبارکه"),"622"==e&&(a="استان اصفهان - شهر میمه"),"124"==e&&(a="استان اصفهان - شهر نائین"),"108"!=e&&"109"!=e||(a="استان اصفهان - شهر نجف آباد"),"123"==e&&(a="استان اصفهان - شهر نطنز"),"427"!=e&&"428"!=e||(a="استان زنجان - شهر زنجان"),"507"==e&&(a="استان آذربایجان شرقی - شهر ملکان"),"158"==e&&(a="استان آذربایجان شرقی - شهر مرند"),"152"!=e&&"153"!=e||(a="استان آذربایجان شرقی - شهر میانه"),"615"==e&&(a="استان قزوین - شهر ابهر و خرمدره"),a}function GFPersian_National_ID_Handler(e,a,n,t,l,r,i){if(document.getElementById("ir_national_id_location_"+a).innerHTML="",""==e.value)return!1;if(e.value=e.value.replace("-","").replace("-",""),isNaN(e.value))return document.getElementById("ir_national_id_location_"+a).innerHTML=n,!1;if(8==e.value.length&&(e.value="00"+e.value),9==e.value.length&&(e.value="0"+e.value),e.value.length>10||e.value.length<8)return document.getElementById("ir_national_id_location_"+a).innerHTML=t,!1;if("-1"!=["0000000000","1111111111","2222222222","3333333333","4444444444","5555555555","6666666666","7777777777","8888888888","9999999999","0123456789"].indexOf(e.value))return document.getElementById("ir_national_id_location_"+a).innerHTML=l,!1;var u=e.value.substring(0,3),o=parseInt(e.value.charAt(9)),_=10*parseInt(e.value.charAt(0))+9*parseInt(e.value.charAt(1))+8*parseInt(e.value.charAt(2))+7*parseInt(e.value.charAt(3))+6*parseInt(e.value.charAt(4))+5*parseInt(e.value.charAt(5))+4*parseInt(e.value.charAt(6))+3*parseInt(e.value.charAt(7))+2*parseInt(e.value.charAt(8)),v=_-11*parseInt(_/11);return 0==v&&v==o||1==v&&1==o||v>1&&o==11-v?(r&&10==e.value.length&&(e.value=e.value.substring(0,3)+"-"+e.value.substring(3,9)+"-"+e.value.substring(9,10)),i?(document.getElementById("ir_national_id_location_"+a).innerHTML=GFPersian_National_ID_Location(u),!0):void 0):(document.getElementById("ir_national_id_location_"+a).innerHTML=l,!1)}
|
assets/js/shamsi_chart.js
CHANGED
File without changes
|
includes/{class-iran-cities.php → class-address.php}
RENAMED
@@ -2,80 +2,91 @@
|
|
2 |
exit;
|
3 |
}
|
4 |
|
5 |
-
class
|
6 |
-
|
7 |
-
public $province = array();
|
8 |
|
9 |
public function __construct() {
|
10 |
-
add_action( 'gform_editor_js', array( $this, 'iran_cities' ) );
|
11 |
-
add_action( 'gform_field_standard_settings', array( $this, 'iran_cities_option' ), 10, 2 );
|
12 |
-
add_filter( 'gform_address_types', array( $this, 'iran_address' ) );
|
13 |
-
add_filter( 'gform_predefined_choices', array( $this, 'predefined_choices' ), 1 );
|
14 |
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
add_action( 'gform_register_init_scripts', array( $this, 'init_script' ), 10, 1 );
|
17 |
add_action( 'gform_enqueue_scripts', array( $this, 'external_js' ), 10, 2 );
|
18 |
}
|
19 |
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
__( 'Hamadan', 'GF_FA' ),
|
54 |
-
__( 'Yazd', 'GF_FA' )
|
55 |
);
|
56 |
}
|
57 |
|
58 |
-
public function
|
59 |
-
|
60 |
$address_types['iran'] = array(
|
61 |
-
'label' =>
|
62 |
-
'country' =>
|
63 |
-
'zip_label' =>
|
64 |
-
'state_label' =>
|
65 |
-
'states' => array_merge( array( '' ), $this->
|
66 |
);
|
67 |
|
68 |
return $address_types;
|
69 |
}
|
70 |
|
71 |
-
public function
|
72 |
-
|
73 |
-
$states[
|
74 |
|
75 |
return $choices = array_merge( $states, $choices );
|
76 |
}
|
77 |
|
78 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
<script type='text/javascript'>
|
81 |
jQuery(document).ready(function ($) {
|
@@ -89,10 +100,10 @@ class GFParsi_IranCities {
|
|
89 |
$iran_cities.remove();
|
90 |
$address_type.after('<div id="iran_cities_div"><br>' + $iran_cities_input + '</div>');
|
91 |
}
|
92 |
-
var $iran_cities_div = $('#iran_cities_div');
|
93 |
-
$iran_cities_div.hide();
|
94 |
if ($address_type.val() === 'iran')
|
95 |
-
$iran_cities_div.show();
|
|
|
|
|
96 |
$address_type.change(function () {
|
97 |
if ($(this).val() === 'iran')
|
98 |
$("#iran_cities_div").slideDown();
|
@@ -106,26 +117,13 @@ class GFParsi_IranCities {
|
|
106 |
<?php
|
107 |
}
|
108 |
|
109 |
-
public function
|
110 |
-
if ( $position == 25 ) { ?>
|
111 |
-
<li class="iran_cities field_setting">
|
112 |
-
<input type="checkbox" id="iran_cities"
|
113 |
-
onclick="SetFieldProperty('iran_cities', jQuery(this).is(':checked') ? 1 : 0);"/>
|
114 |
-
<label class="inline gfield_value_label" for="iran_cities" class="inline">
|
115 |
-
<?php _e( 'Activate Iran Cities', 'GF_FA' ); ?>
|
116 |
-
</label>
|
117 |
-
</li>
|
118 |
-
<?php
|
119 |
-
}
|
120 |
-
}
|
121 |
-
|
122 |
-
public function city_select( $content, $field, $value, $lead_id, $form_id ) {
|
123 |
|
124 |
if ( $this->is_iran_cities( $field ) ) {
|
125 |
|
126 |
$id = absint( $field['id'] );
|
127 |
|
128 |
-
preg_match( '/<input(
|
129 |
|
130 |
if ( ! empty( $match[0] ) && ! empty( $match[1] ) ) {
|
131 |
$city_input = trim( $match[1] );
|
@@ -148,41 +146,41 @@ class GFParsi_IranCities {
|
|
148 |
wp_dequeue_script( 'gform_iran_citeis' );
|
149 |
wp_deregister_script( 'gform_iran_citeis' );
|
150 |
|
151 |
-
wp_register_script( 'gform_iran_citeis',
|
152 |
wp_enqueue_script( 'gform_iran_citeis' );
|
153 |
|
154 |
-
add_action( '
|
155 |
|
156 |
break;
|
157 |
}
|
158 |
}
|
159 |
}
|
160 |
|
|
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
$frontend_rtl = apply_filters( 'gf_persian_frontend_rtl', is_rtl() && ! is_admin() );
|
165 |
-
if ( ! $frontend_rtl ) {
|
166 |
return;
|
167 |
}
|
168 |
?>
|
169 |
<style type="text/css">
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
|
|
|
|
186 |
</style>
|
187 |
<?php
|
188 |
}
|
@@ -193,15 +191,13 @@ class GFParsi_IranCities {
|
|
193 |
|
194 |
if ( $this->is_iran_cities( $field ) ) {
|
195 |
|
196 |
-
$
|
197 |
-
$form_id = $form['id'];
|
198 |
-
$id = $form_id . '_' . $field_id;
|
199 |
|
200 |
$script = 'jQuery().ready(function($){' .
|
201 |
'$(".has_city #input_' . $id . '_3").html(gform_iranCities(""+$(".has_city #input_' . $id . '_4").val()));' .
|
202 |
'if ($(".has_city #input_' . $id . '_3").attr("data-selected")) {' .
|
203 |
-
|
204 |
-
|
205 |
'$(document.body).on("change", ".has_city #input_' . $id . '_4" ,function(){' .
|
206 |
'$(".has_city #input_' . $id . '_3").html(gform_iranCities(""+$(".has_city #input_' . $id . '_4").val()));' .
|
207 |
'}).on("change", ".has_city #input_' . $id . '_3" ,function(){' .
|
@@ -214,9 +210,9 @@ class GFParsi_IranCities {
|
|
214 |
}
|
215 |
|
216 |
private function is_iran_cities( $field ) {
|
217 |
-
return $field['type'] == 'address' && $field['addressType'] == 'iran' &&
|
218 |
}
|
219 |
|
220 |
}
|
221 |
|
222 |
-
new
|
2 |
exit;
|
3 |
}
|
4 |
|
5 |
+
class GFPersian_Adress extends GFPersian_Core {
|
|
|
|
|
6 |
|
7 |
public function __construct() {
|
|
|
|
|
|
|
|
|
8 |
|
9 |
+
if ( $this->option( 'address', '1' ) != '1' ) {
|
10 |
+
return;
|
11 |
+
}
|
12 |
+
|
13 |
+
add_action( 'gform_editor_js', array( $this, 'iran_cities_editor_js' ) );
|
14 |
+
add_action( 'gform_field_standard_settings', array( $this, 'iran_cities_option' ), 10, 2 );
|
15 |
+
add_filter( 'gform_address_types', array( $this, 'iran_address_type' ) );
|
16 |
+
add_filter( 'gform_predefined_choices', array( $this, 'iran_provinces_choices' ), 1 );
|
17 |
+
add_filter( 'gform_field_content', array( $this, 'iran_cities_field_type' ), 10, 5 );
|
18 |
add_action( 'gform_register_init_scripts', array( $this, 'init_script' ), 10, 1 );
|
19 |
add_action( 'gform_enqueue_scripts', array( $this, 'external_js' ), 10, 2 );
|
20 |
}
|
21 |
|
22 |
+
public function iran_provinces() {
|
23 |
+
return array(
|
24 |
+
'آذربایجان شرقی',
|
25 |
+
'آذربایجان غربی',
|
26 |
+
'اردبیل',
|
27 |
+
'اصفهان',
|
28 |
+
'البرز',
|
29 |
+
'ایلام',
|
30 |
+
'بوشهر',
|
31 |
+
'تهران',
|
32 |
+
'چهارمحال و بختیاری',
|
33 |
+
'خراسان جنوبی',
|
34 |
+
'خراسان رضوی',
|
35 |
+
'خراسان شمالی',
|
36 |
+
'خوزستان',
|
37 |
+
'زنجان',
|
38 |
+
'سمنان',
|
39 |
+
'سیستان و بلوچستان',
|
40 |
+
'فارس',
|
41 |
+
'قزوین',
|
42 |
+
'قم',
|
43 |
+
'کردستان',
|
44 |
+
'کرمان',
|
45 |
+
'کرمانشاه',
|
46 |
+
'کهگیلویه و بویراحمد',
|
47 |
+
'گلستان',
|
48 |
+
'گیلان',
|
49 |
+
'لرستان',
|
50 |
+
'مازندران',
|
51 |
+
'مرکزی',
|
52 |
+
'هرمزگان',
|
53 |
+
'همدان',
|
54 |
+
'یزد'
|
|
|
|
|
55 |
);
|
56 |
}
|
57 |
|
58 |
+
public function iran_address_type( $address_types ) {
|
59 |
+
|
60 |
$address_types['iran'] = array(
|
61 |
+
'label' => 'ایران',
|
62 |
+
'country' => 'ایران',
|
63 |
+
'zip_label' => 'کدپستی',
|
64 |
+
'state_label' => 'استان',
|
65 |
+
'states' => array_merge( array( '' ), $this->iran_provinces() )
|
66 |
);
|
67 |
|
68 |
return $address_types;
|
69 |
}
|
70 |
|
71 |
+
public function iran_provinces_choices( $choices ) {
|
72 |
+
|
73 |
+
$states['استان های ایران'] = $this->iran_provinces();
|
74 |
|
75 |
return $choices = array_merge( $states, $choices );
|
76 |
}
|
77 |
|
78 |
+
public function iran_cities_option( $position, $form_id ) {
|
79 |
+
if ( $position == 25 ) { ?>
|
80 |
+
<li class="iran_cities field_setting">
|
81 |
+
<input type="checkbox" id="iran_cities"
|
82 |
+
onclick="SetFieldProperty('iran_cities', jQuery(this).is(':checked') ? 1 : 0);"/>
|
83 |
+
<label class="inline gfield_value_label" for="iran_cities">فعالسازی شهرهای ایران</label>
|
84 |
+
</li>
|
85 |
+
<?php
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
public function iran_cities_editor_js() { ?>
|
90 |
|
91 |
<script type='text/javascript'>
|
92 |
jQuery(document).ready(function ($) {
|
100 |
$iran_cities.remove();
|
101 |
$address_type.after('<div id="iran_cities_div"><br>' + $iran_cities_input + '</div>');
|
102 |
}
|
|
|
|
|
103 |
if ($address_type.val() === 'iran')
|
104 |
+
$('#iran_cities_div').show();
|
105 |
+
else
|
106 |
+
$('#iran_cities_div').hide();
|
107 |
$address_type.change(function () {
|
108 |
if ($(this).val() === 'iran')
|
109 |
$("#iran_cities_div").slideDown();
|
117 |
<?php
|
118 |
}
|
119 |
|
120 |
+
public function iran_cities_field_type( $content, $field, $value, $entry_id, $form_id ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
if ( $this->is_iran_cities( $field ) ) {
|
123 |
|
124 |
$id = absint( $field['id'] );
|
125 |
|
126 |
+
preg_match( '/<input.*?(name=["\']input_' . $id . '.3["\'].*?)\/??>/i', $content, $match );
|
127 |
|
128 |
if ( ! empty( $match[0] ) && ! empty( $match[1] ) ) {
|
129 |
$city_input = trim( $match[1] );
|
146 |
wp_dequeue_script( 'gform_iran_citeis' );
|
147 |
wp_deregister_script( 'gform_iran_citeis' );
|
148 |
|
149 |
+
wp_register_script( 'gform_iran_citeis', GF_PERSIAN_URL . 'assets/js/iran-cities-full.min.js', array(), GF_PERSIAN_VERSION, false );
|
150 |
wp_enqueue_script( 'gform_iran_citeis' );
|
151 |
|
152 |
+
add_action( 'gform_enqueue_scripts', array( $this, 'frontend_rtl' ), 999, 1 );
|
153 |
|
154 |
break;
|
155 |
}
|
156 |
}
|
157 |
}
|
158 |
|
159 |
+
public function frontend_rtl( $form ) {
|
160 |
|
161 |
+
if ( ! apply_filters( 'gform_iran_cities_fronend_rtl', is_rtl() && ! is_admin() ) ) {
|
|
|
|
|
|
|
162 |
return;
|
163 |
}
|
164 |
?>
|
165 |
<style type="text/css">
|
166 |
+
<?php
|
167 |
+
foreach ( $form['fields'] as &$field ) {
|
168 |
+
if ( $this->is_iran_cities( $field ) ) {
|
169 |
+
$id = $form['id'] . '_' . $field['id'];
|
170 |
+
echo '
|
171 |
+
html[dir="rtl"] #input_' . $id . '_4_container{
|
172 |
+
float: right !important;
|
173 |
+
padding-right: 0 !important;
|
174 |
+
padding-left: 16px !important;
|
175 |
+
}
|
176 |
+
html[dir="rtl"] #input_' . $id . '_3_container{
|
177 |
+
float: left !important;
|
178 |
+
padding-right: 0 !important;
|
179 |
+
padding-left: 0 !important;
|
180 |
+
}';
|
181 |
+
}
|
182 |
+
}
|
183 |
+
?>
|
184 |
</style>
|
185 |
<?php
|
186 |
}
|
191 |
|
192 |
if ( $this->is_iran_cities( $field ) ) {
|
193 |
|
194 |
+
$id = $form['id'] . '_' . $field['id'];
|
|
|
|
|
195 |
|
196 |
$script = 'jQuery().ready(function($){' .
|
197 |
'$(".has_city #input_' . $id . '_3").html(gform_iranCities(""+$(".has_city #input_' . $id . '_4").val()));' .
|
198 |
'if ($(".has_city #input_' . $id . '_3").attr("data-selected")) {' .
|
199 |
+
'$(".has_city #input_' . $id . '_3").val($(".has_city #input_' . $id . '_3").attr("data-selected"));' .
|
200 |
+
'}' .
|
201 |
'$(document.body).on("change", ".has_city #input_' . $id . '_4" ,function(){' .
|
202 |
'$(".has_city #input_' . $id . '_3").html(gform_iranCities(""+$(".has_city #input_' . $id . '_4").val()));' .
|
203 |
'}).on("change", ".has_city #input_' . $id . '_3" ,function(){' .
|
210 |
}
|
211 |
|
212 |
private function is_iran_cities( $field ) {
|
213 |
+
return $field['type'] == 'address' && $field['addressType'] == 'iran' && rgar( $field, 'iran_cities' ) && ! is_admin();
|
214 |
}
|
215 |
|
216 |
}
|
217 |
|
218 |
+
new GFPersian_Adress();
|
includes/class-admin.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Admin extends GFPersian_Core {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
add_filter( 'gform_print_styles', array( $this, 'print_styles' ), 10, 1 );
|
9 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ), 999 );
|
10 |
+
add_filter( 'gform_noconflict_styles', array( $this, 'noconflict_styles' ) );
|
11 |
+
add_filter( 'gform_noconflict_scripts', array( $this, 'noconflict_scripts' ) );
|
12 |
+
add_action( 'wp_dashboard_setup', array( $this, 'dashboard_rss_widget' ) );
|
13 |
+
add_action( 'admin_footer', array( $this, 'hide_license' ), 9999 );
|
14 |
+
}
|
15 |
+
|
16 |
+
public function admin_styles() {
|
17 |
+
|
18 |
+
if ( $this->is_gravity_page() ) {
|
19 |
+
|
20 |
+
if ( is_rtl() && $this->option( 'rtl_admin', '1' ) == '1' ) {
|
21 |
+
wp_register_style( 'gform_admin_rtl_style', GF_PERSIAN_URL . 'assets/css/rtl-admin.css' );
|
22 |
+
wp_enqueue_style( 'gform_admin_rtl_style' );
|
23 |
+
}
|
24 |
+
|
25 |
+
$this->font_styles();
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
public function print_styles( $styles ) {
|
30 |
+
|
31 |
+
$styles = (array) $styles;
|
32 |
+
|
33 |
+
if ( is_rtl() && $this->option( 'rtl_admin', '1' ) == '1' ) {
|
34 |
+
$styles[] = $style = 'gform_print_rtl_style';
|
35 |
+
wp_register_style( $style, GF_PERSIAN_URL . 'assets/css/rtl-print.css' );
|
36 |
+
}
|
37 |
+
|
38 |
+
return array_merge( $styles, $this->font_styles() );
|
39 |
+
}
|
40 |
+
|
41 |
+
private function font_styles( $only_face = false ) {
|
42 |
+
|
43 |
+
$styles = array();
|
44 |
+
|
45 |
+
if ( ( $font = $this->option( 'font_admin', 'vazir' ) ) != '0' ) {
|
46 |
+
|
47 |
+
$styles[] = $style = 'gform_admin_font_face';
|
48 |
+
wp_register_style( $style, GF_PERSIAN_URL . "assets/css/font-face-{$font}.css" );
|
49 |
+
wp_enqueue_style( $style );
|
50 |
+
|
51 |
+
if ( ! $only_face ) {
|
52 |
+
$styles[] = $style = 'gform_print_font_style';
|
53 |
+
wp_register_style( $style, GF_PERSIAN_URL . "assets/css/font-admin.css" );
|
54 |
+
wp_enqueue_style( $style );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
return $styles;
|
59 |
+
}
|
60 |
+
|
61 |
+
|
62 |
+
public function noconflict_scripts( $scripts ) {
|
63 |
+
//$scripts[] = '';//ممکنه احتیاج بشه
|
64 |
+
return $scripts;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function noconflict_styles( $styles ) {
|
68 |
+
$styles[] = 'gform_print_rtl_style';
|
69 |
+
$styles[] = 'gform_admin_rtl_style';
|
70 |
+
$styles[] = 'gform_admin_font_face';
|
71 |
+
$styles[] = 'gform_print_font_style';
|
72 |
+
|
73 |
+
return $styles;
|
74 |
+
}
|
75 |
+
|
76 |
+
public function dashboard_rss_widget() {
|
77 |
+
|
78 |
+
if ( current_user_can( 'manage_options' ) && $this->option( 'rss_widget', '1' ) == '1' ) {
|
79 |
+
|
80 |
+
/*wp_add_dashboard_widget( 'GFPersian_RSS', 'آخرین مطالب گرویتی فرم پارسی',
|
81 |
+
array( $this, 'callback_rss_widget' ) );*/
|
82 |
+
|
83 |
+
add_meta_box( 'GFPersian_RSS', 'آخرین مطالب گرویتی فرم پارسی', array( $this, 'callback_rss_widget' ),
|
84 |
+
'dashboard', 'side', 'low' );
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
public function callback_rss_widget() {
|
89 |
+
|
90 |
+
$font = $this->font_styles( true );
|
91 |
+
$style = ! empty( $font ) ? 'style="font-family: GFPersian;"' : ''; ?>
|
92 |
+
|
93 |
+
<div class="rss-widget" <?php echo $style; ?>>
|
94 |
+
<?php wp_widget_rss_output( array(
|
95 |
+
'url' => 'http://gravityforms.ir/feed/',
|
96 |
+
'items' => 2,
|
97 |
+
'show_summary' => 1,
|
98 |
+
'show_author' => 1,
|
99 |
+
'show_date' => 1
|
100 |
+
) ); ?>
|
101 |
+
<div style="border-top: 1px solid #e7e7e7; padding-top: 12px !important; font-size: 13px; height: 20px;">
|
102 |
+
|
103 |
+
<img src="<?php echo GF_PERSIAN_URL ?>assets/images/logo.png" width="30" height="auto"
|
104 |
+
style="float: right; margin: -10px 1px 0 10px"/>
|
105 |
+
|
106 |
+
<a href="http://gravityforms.ir" target="_blank" title="گرویتی فرم پارسی">
|
107 |
+
مشاهده وب سایت گرویتی فرم پارسی
|
108 |
+
</a>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
<?php
|
112 |
+
}
|
113 |
+
|
114 |
+
|
115 |
+
public function hide_license() {
|
116 |
+
if ( $this->is_gravity_page() && $this->option( 'hide_lic', '0' ) == '1' ) { ?>
|
117 |
+
<script type="text/javascript">
|
118 |
+
jQuery(document).ready(function ($) {
|
119 |
+
$('img').each(function () {
|
120 |
+
if (this.title.indexOf("licensed") !== -1 || this.alt.indexOf("licensed") !== -1)
|
121 |
+
$(this).hide().parent("a").hide().parent("div").hide();
|
122 |
+
});
|
123 |
+
});
|
124 |
+
</script>
|
125 |
+
<?php
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
new GFPersian_Admin;
|
includes/class-core.php
ADDED
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Core {
|
6 |
+
|
7 |
+
private static $settings;
|
8 |
+
|
9 |
+
public function __construct() {
|
10 |
+
|
11 |
+
if ( ! class_exists( 'GFCommon' ) ) {
|
12 |
+
add_action( 'admin_notices', array( $this, 'gform_notice' ) );
|
13 |
+
|
14 |
+
return;
|
15 |
+
}
|
16 |
+
|
17 |
+
add_action( 'admin_notices', array( $this, 'plugin_update' ), 9999 );
|
18 |
+
add_filter( 'load_textdomain_mofile', array( $this, 'load_translate' ), 10, 2 );
|
19 |
+
add_action( 'gform_loaded', array( $this, 'load_settings' ), 5 );
|
20 |
+
add_filter( 'gform_tooltips', array( $this, 'tooltips' ) );
|
21 |
+
add_filter( 'gform_add_field_buttons', array( $this, 'fields_group' ) );
|
22 |
+
|
23 |
+
$this->include_files();
|
24 |
+
}
|
25 |
+
|
26 |
+
public function gform_notice() {
|
27 |
+
$message = sprintf( 'شما فقط بسته گرویتی فرم پارسی را نصب کرده اید. در حالیکه نصب هسته اصلی گرویتی فرم هم نیاز است. %sسوالات متداول%s', '<a href="http://gravityforms.ir/faq/" target="_blank">', '</a>' );
|
28 |
+
printf( '<div class="notice notice-error"><p>%s</p></div>', $message );
|
29 |
+
}
|
30 |
+
|
31 |
+
public function plugin_update() {
|
32 |
+
|
33 |
+
if ( get_option( 'gform_pending_installation' ) ) {
|
34 |
+
update_option( 'gform_pending_installation', false );
|
35 |
+
$current_version = get_option( 'rg_form_version' );
|
36 |
+
if ( $current_version === false ) {
|
37 |
+
if ( class_exists( 'GFCommon' ) ) {
|
38 |
+
update_option( 'rg_form_version', GFCommon::$version );
|
39 |
+
} else {
|
40 |
+
update_option( 'rg_form_version', '2.0.0' );
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
if ( ! get_option( 'gf_persian_updated' ) ) {
|
46 |
+
|
47 |
+
for ( $i = 1; $i <= 5; $i ++ ) {
|
48 |
+
delete_option( 'persian_gf_notice_v' . $i );
|
49 |
+
}
|
50 |
+
|
51 |
+
//update national id
|
52 |
+
global $wpdb;
|
53 |
+
$table = RGFormsModel::get_meta_table_name();
|
54 |
+
$update = $wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, 'mellicart', 'ir_national_id')" );
|
55 |
+
if ( $update !== false ) {
|
56 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id\"', '\"showLocation\"')" );
|
57 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id_sp\"', '\"showSeperator\"')" );
|
58 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id_sp1\"', '\"notDigitError\"')" );
|
59 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id_sp2\"', '\"qtyDigitError\"')" );
|
60 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id_sp3\"', '\"duplicateError\"')" );
|
61 |
+
$wpdb->query( "UPDATE $table SET display_meta = REPLACE(display_meta, '\"field_ir_national_id_sp4\"', '\"isInvalidError\"')" );
|
62 |
+
update_option( 'gf_persian_updated', GF_PERSIAN_VERSION );
|
63 |
+
}
|
64 |
+
|
65 |
+
echo '<div class="notice notice-success is-dismissible"><p>' . sprintf( 'گرویتی فرم پارسی با موفقیت بروز شد. %sرفتن به صفحه تنظیمات%s', '<a href="' . admin_url( 'admin.php?page=gf_settings&subview=persian' ) . '">', '</a>' ) . '</p></div>';
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
public function tooltips( $tooltips ) {
|
70 |
+
|
71 |
+
$tooltips['form_gf_persian_fields'] = '<h6>گرویتی فرم پارسی</h6>فیلدهای برنامه نویسی شده توسط گرویتی فرم پارسی به مرور اینجا اضافه خواهند شد.';
|
72 |
+
|
73 |
+
return $tooltips;
|
74 |
+
}
|
75 |
+
|
76 |
+
|
77 |
+
public function fields_group( $field_groups ) {
|
78 |
+
|
79 |
+
$group = 'gf_persian_fields';
|
80 |
+
|
81 |
+
if ( ! function_exists( 'wp_list_pluck' ) || ! in_array( $group, wp_list_pluck( $field_groups, 'name' ) ) ) {
|
82 |
+
array_push( $field_groups, array(
|
83 |
+
'name' => $group,
|
84 |
+
'label' => 'فیلدهای گرویتی فرم پارسی',
|
85 |
+
'fields' => array()
|
86 |
+
) );
|
87 |
+
}
|
88 |
+
|
89 |
+
return $field_groups;
|
90 |
+
}
|
91 |
+
|
92 |
+
public function load_settings() {
|
93 |
+
|
94 |
+
if ( method_exists( 'GFForms', 'include_addon_framework' ) ) {
|
95 |
+
|
96 |
+
GFForms::include_addon_framework();
|
97 |
+
GFAddOn::register( 'GFPersian_Settings' );
|
98 |
+
|
99 |
+
require_once( 'class-settings.php' );
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
public function load_translate( $mo_file, $domain ) {
|
104 |
+
|
105 |
+
if ( $this->option( 'translate', '1' ) == '1' && get_locale() == 'fa_IR' ) {
|
106 |
+
|
107 |
+
$translates = array(
|
108 |
+
'gravityforms',
|
109 |
+
'gravityformscoupons',
|
110 |
+
'gravityformsmailchimp',
|
111 |
+
'gravityformspolls',
|
112 |
+
'gravityformsquiz',
|
113 |
+
'gravityformssignature',
|
114 |
+
'gravityformssurvey',
|
115 |
+
'gravityformsuserregistration',
|
116 |
+
'gravityformsauthorizenet',
|
117 |
+
'gravityformsaweber',
|
118 |
+
'gravityformscampaignmonitor',
|
119 |
+
'gravityformspaypalpaymentspro',
|
120 |
+
'gravityformsfreshbooks',
|
121 |
+
'gravityformspaypal',
|
122 |
+
'gravityformspaypalpro',
|
123 |
+
'gravityformstwilio',
|
124 |
+
'gravityformsstripe',
|
125 |
+
'gravityformszapier',
|
126 |
+
'sticky-list',
|
127 |
+
'gf-limit'
|
128 |
+
);
|
129 |
+
|
130 |
+
if ( in_array( $domain, $translates ) ) {
|
131 |
+
$mo_file = dirname( plugin_dir_path( __FILE__ ) ) . "/languages/$domain/$domain-fa_IR.mo";
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
return $mo_file;
|
136 |
+
}
|
137 |
+
|
138 |
+
private function include_files() {
|
139 |
+
include 'class-admin.php';
|
140 |
+
include 'class-address.php';
|
141 |
+
include 'class-payments.php';
|
142 |
+
include 'class-snippets.php';
|
143 |
+
include 'class-merge-tag.php';
|
144 |
+
include 'class-currencies.php';
|
145 |
+
include 'class-jalali-date.php';
|
146 |
+
include 'class-live-preview.php';
|
147 |
+
include 'class-transaction-id.php';
|
148 |
+
include 'class-multi-page-navi.php';
|
149 |
+
|
150 |
+
include 'class-deprecated.php';
|
151 |
+
if ( get_option( 'gf_persian_updated' ) ) {
|
152 |
+
include 'class-national-id.php';
|
153 |
+
} else {
|
154 |
+
//the class is existed in class-deprecated.php
|
155 |
+
new GFParsi_MelliCode();
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
public static function _option( $setting_name = '', $default = null ) {
|
160 |
+
|
161 |
+
if ( empty( self::$settings ) ) {
|
162 |
+
if ( class_exists( 'GFPersian_Settings' ) ) {
|
163 |
+
if ( method_exists( 'GFPersian_Settings', 'get_plugin_settings' ) ) {
|
164 |
+
self::$settings = GFPersian_Settings::get_instance()->get_plugin_settings();
|
165 |
+
}
|
166 |
+
}
|
167 |
+
if ( empty( self::$settings ) && defined( 'GF_PERSIAN_SLUG' ) ) {
|
168 |
+
self::$settings = get_option( 'gravityformsaddon_' . GF_PERSIAN_SLUG . '_settings' );
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
$settings = self::$settings;
|
173 |
+
|
174 |
+
if ( ! empty( $setting_name ) ) {
|
175 |
+
$settings = isset( $settings[ $setting_name ] ) ? $settings[ $setting_name ] : '';
|
176 |
+
}
|
177 |
+
|
178 |
+
return ! empty( $settings ) || strval( $settings ) == '0' ? $settings : $default;
|
179 |
+
}
|
180 |
+
|
181 |
+
public function option( $setting_name = '', $default = null ) {
|
182 |
+
return self::_option( $setting_name, $default );
|
183 |
+
}
|
184 |
+
|
185 |
+
public function is_gravity_page() {
|
186 |
+
|
187 |
+
$is_gform = class_exists( 'RGForms' ) ? RGForms::is_gravity_page() : false;
|
188 |
+
$current_page = trim( strtolower( rgget( 'page' ) ) );
|
189 |
+
|
190 |
+
return $is_gform || substr( $current_page, 0, 2 ) == 'gf' || stripos( $current_page, 'gravity' ) !== false;
|
191 |
+
}
|
192 |
+
|
193 |
+
public static function get_base_url() {
|
194 |
+
return plugins_url( '', dirname(__FILE__) );
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
new GFPersian_Core;
|
includes/class-currencies.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Currencies extends GFPersian_Core {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
|
9 |
+
if ( $this->option( 'currencies', '1' ) != '1' ) {
|
10 |
+
return;
|
11 |
+
}
|
12 |
+
|
13 |
+
add_filter( 'gform_currencies', array( $this, 'iran_currencies' ) );
|
14 |
+
}
|
15 |
+
|
16 |
+
public function iran_currencies( $currencies ) {
|
17 |
+
|
18 |
+
unset( $currencies['IRR'], $currencies['irr'], $currencies['IRT'], $currencies['irt'] );
|
19 |
+
|
20 |
+
$is_rtl = true; /*may be need use is_rtl() later but not now*/
|
21 |
+
$is_fa = apply_filters( 'gform_iran_currencies_is_fa', get_locale() == 'fa_IR', $currencies );
|
22 |
+
|
23 |
+
$ir_currencies = array(
|
24 |
+
|
25 |
+
'IRR' => array(
|
26 |
+
'name' => 'ریال ایران',
|
27 |
+
'symbol_left' => ( ! $is_rtl ? ( $is_fa ? 'ریال' : 'Rial' ) : '' ),
|
28 |
+
'symbol_right' => ( $is_rtl ? ( $is_fa ? 'ریال' : 'Rial' ) : '' ),
|
29 |
+
'symbol_padding' => ' ',
|
30 |
+
'thousand_separator' => ',',
|
31 |
+
'decimal_separator' => '.',
|
32 |
+
'decimals' => 0
|
33 |
+
),
|
34 |
+
|
35 |
+
'IRHR' => array(
|
36 |
+
'name' => 'هزار ریال ایران',
|
37 |
+
'symbol_left' => ( ! $is_rtl ? ( $is_fa ? 'هزار ریال' : 'Thousand Rial' ) : '' ),
|
38 |
+
'symbol_right' => ( $is_rtl ? ( $is_fa ? 'هزار ریال' : 'Thousand Rial' ) : '' ),
|
39 |
+
'symbol_padding' => ' ',
|
40 |
+
'thousand_separator' => ',',
|
41 |
+
'decimal_separator' => '.',
|
42 |
+
'decimals' => 0
|
43 |
+
),
|
44 |
+
|
45 |
+
'IRT' => array(
|
46 |
+
'name' => 'تومان ایران',
|
47 |
+
'symbol_left' => ( ! $is_rtl ? ( $is_fa ? 'تومان' : 'Toman' ) : '' ),
|
48 |
+
'symbol_right' => ( $is_rtl ? ( $is_fa ? 'تومان' : 'Toman' ) : '' ),
|
49 |
+
'symbol_padding' => ' ',
|
50 |
+
'thousand_separator' => ',',
|
51 |
+
'decimal_separator' => '.',
|
52 |
+
'decimals' => 0
|
53 |
+
),
|
54 |
+
|
55 |
+
'IRHT' => array(
|
56 |
+
'name' => 'هزار تومان ایران',
|
57 |
+
'symbol_left' => ( ! $is_rtl ? ( $is_fa ? 'هزار تومان' : 'Thousand Toman' ) : '' ),
|
58 |
+
'symbol_right' => ( $is_rtl ? ( $is_fa ? 'هزار تومان' : 'Thousand Toman' ) : '' ),
|
59 |
+
'symbol_padding' => ' ',
|
60 |
+
'thousand_separator' => ',',
|
61 |
+
'decimal_separator' => '.',
|
62 |
+
'decimals' => 0
|
63 |
+
),
|
64 |
+
|
65 |
+
);
|
66 |
+
|
67 |
+
return array_merge( $ir_currencies, $currencies );
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
new GFPersian_Currencies();
|
includes/class-deprecated.php
ADDED
@@ -0,0 +1,657 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
/*
|
5 |
+
* @deprecated
|
6 |
+
* this methods are used in Gateway->charts
|
7 |
+
* will be deleted completely in some next updates
|
8 |
+
* */
|
9 |
+
if ( ! class_exists( 'GFParsi' ) ) :
|
10 |
+
|
11 |
+
class GFParsi {
|
12 |
+
|
13 |
+
public static function better_noDuplicate_hook( $version ) {
|
14 |
+
if ( version_compare( $version, '1.9.19', '>' ) ) {
|
15 |
+
add_filter( 'gform_is_duplicate', array( __CLASS__, 'better_noDuplicate_1_9_19' ), 10, 4 );
|
16 |
+
} else {
|
17 |
+
add_filter( 'gform_is_duplicate', array( __CLASS__, 'better_noDuplicate_old' ), 10, 4 );
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
public static function better_noDuplicate_1_9_19( $count, $form_id, $field, $value ) {
|
22 |
+
global $wpdb;
|
23 |
+
|
24 |
+
$lead_detail_table_name = GFFormsModel::get_lead_details_table_name();
|
25 |
+
$lead_table_name = GFFormsModel::get_lead_table_name();
|
26 |
+
$sql_comparison = 'ld.value = %s';
|
27 |
+
|
28 |
+
switch ( GFFormsModel::get_input_type( $field ) ) {
|
29 |
+
case 'time':
|
30 |
+
$value = sprintf( "%02d:%02d %s", $value[0], $value[1], $value[2] );
|
31 |
+
break;
|
32 |
+
case 'date':
|
33 |
+
$value = GFFormsModel::prepare_date( $field->dateFormat, $value );
|
34 |
+
break;
|
35 |
+
case 'number':
|
36 |
+
$value = GFCommon::clean_number( $value, $field->numberFormat );
|
37 |
+
break;
|
38 |
+
case 'phone':
|
39 |
+
$value = str_replace( array( ')', '(', '-', ' ' ), '', $value );
|
40 |
+
$sql_comparison = 'replace( replace( replace( replace( ld.value, ")", "" ), "(", "" ), "-", "" ), " ", "" ) = %s';
|
41 |
+
break;
|
42 |
+
case 'email':
|
43 |
+
$value = is_array( $value ) ? rgar( $value, 0 ) : $value;
|
44 |
+
break;
|
45 |
+
}
|
46 |
+
|
47 |
+
$inner_sql_template = "SELECT %s as input, ld.lead_id
|
48 |
+
FROM {$lead_detail_table_name} ld
|
49 |
+
INNER JOIN {$lead_table_name} l ON l.id = ld.lead_id\n";
|
50 |
+
|
51 |
+
|
52 |
+
$inner_sql_template .= "WHERE l.form_id=%d AND ld.form_id=%d
|
53 |
+
AND ld.field_number between %s AND %s
|
54 |
+
AND status='active'
|
55 |
+
AND (payment_status IS NULL OR LOWER(payment_status) IN ('', 'approved', 'approve', 'completed', 'complete', 'actived', 'active', 'paid'))
|
56 |
+
AND {$sql_comparison}";
|
57 |
+
|
58 |
+
$sql = "SELECT count(DISTINCT input) AS match_count FROM ( ";
|
59 |
+
|
60 |
+
$inner_sql = '';
|
61 |
+
$input_count = 1;
|
62 |
+
if ( is_array( $field->get_entry_inputs() ) ) {
|
63 |
+
$input_count = sizeof( $field->inputs );
|
64 |
+
foreach ( $field->inputs as $input ) {
|
65 |
+
$union = empty( $inner_sql ) ? '' : ' UNION ALL ';
|
66 |
+
$inner_sql .= $union . $wpdb->prepare( $inner_sql_template, $input['id'], $form_id, $form_id, $input['id'] - 0.0001, $input['id'] + 0.0001, $value[ $input['id'] ], $value[ $input['id'] ] );
|
67 |
+
}
|
68 |
+
} else {
|
69 |
+
$inner_sql = $wpdb->prepare( $inner_sql_template, $field->id, $form_id, $form_id, doubleval( $field->id ) - 0.0001, doubleval( $field->id ) + 0.0001, $value, $value );
|
70 |
+
}
|
71 |
+
|
72 |
+
$sql .= $inner_sql . "
|
73 |
+
) as count
|
74 |
+
GROUP BY lead_id
|
75 |
+
ORDER BY match_count DESC";
|
76 |
+
|
77 |
+
$count = gf_apply_filters( array(
|
78 |
+
'gform_is_duplicate_better',
|
79 |
+
$form_id
|
80 |
+
), $wpdb->get_var( $sql ), $form_id, $field, $value );
|
81 |
+
|
82 |
+
return $count != null && $count >= $input_count;
|
83 |
+
}
|
84 |
+
|
85 |
+
public static function better_noDuplicate_old( $count, $form_id, $field, $value ) {
|
86 |
+
|
87 |
+
global $wpdb;
|
88 |
+
|
89 |
+
$lead_detail_table_name = GFFormsModel::get_lead_details_table_name();
|
90 |
+
$lead_table_name = GFFormsModel::get_lead_table_name();
|
91 |
+
$lead_detail_long = GFFormsModel::get_lead_details_long_table_name();
|
92 |
+
$is_long = ! is_array( $value ) && strlen( $value ) > GFORMS_MAX_FIELD_LENGTH - 10;
|
93 |
+
|
94 |
+
$sql_comparison = $is_long ? '( ld.value = %s OR ldl.value = %s )' : 'ld.value = %s';
|
95 |
+
|
96 |
+
switch ( GFFormsModel::get_input_type( $field ) ) {
|
97 |
+
case 'time':
|
98 |
+
$value = sprintf( "%02d:%02d %s", $value[0], $value[1], $value[2] );
|
99 |
+
break;
|
100 |
+
case 'date':
|
101 |
+
$value = GFFormsModel::prepare_date( $field->dateFormat, $value );
|
102 |
+
break;
|
103 |
+
case 'number':
|
104 |
+
$value = GFCommon::clean_number( $value, $field->numberFormat );
|
105 |
+
break;
|
106 |
+
case 'phone':
|
107 |
+
$value = str_replace( array( ')', '(', '-', ' ' ), '', $value );
|
108 |
+
$sql_comparison = 'replace( replace( replace( replace( ld.value, ")", "" ), "(", "" ), "-", "" ), " ", "" ) = %s';
|
109 |
+
break;
|
110 |
+
case 'email':
|
111 |
+
$value = is_array( $value ) ? rgar( $value, 0 ) : $value;
|
112 |
+
break;
|
113 |
+
}
|
114 |
+
|
115 |
+
$inner_sql_template = "SELECT %s as input, ld.lead_id
|
116 |
+
FROM {$lead_detail_table_name} ld
|
117 |
+
INNER JOIN {$lead_table_name} l ON l.id = ld.lead_id\n";
|
118 |
+
|
119 |
+
if ( $is_long ) {
|
120 |
+
$inner_sql_template .= "INNER JOIN {$lead_detail_long} ldl ON ldl.lead_detail_id = ld.id\n";
|
121 |
+
}
|
122 |
+
|
123 |
+
$inner_sql_template .= "WHERE l.form_id=%d AND ld.form_id=%d
|
124 |
+
AND ld.field_number between %s AND %s
|
125 |
+
AND status='active'
|
126 |
+
AND (payment_status IS NULL OR LOWER(payment_status) IN ('', 'approved', 'approve', 'completed', 'complete', 'actived', 'active', 'paid'))
|
127 |
+
AND {$sql_comparison}";
|
128 |
+
|
129 |
+
$sql = "SELECT count(DISTINCT input) AS match_count FROM ( ";
|
130 |
+
|
131 |
+
$inner_sql = '';
|
132 |
+
$input_count = 1;
|
133 |
+
if ( is_object( $field ) && is_array( $field->get_entry_inputs() ) ) {
|
134 |
+
$input_count = sizeof( $field->inputs );
|
135 |
+
foreach ( $field->inputs as $input ) {
|
136 |
+
$union = empty( $inner_sql ) ? '' : ' UNION ALL ';
|
137 |
+
$inner_sql .= $union . $wpdb->prepare( $inner_sql_template, $input['id'], $form_id, $form_id, $input['id'] - 0.0001, $input['id'] + 0.0001, $value[ $input['id'] ], $value[ $input['id'] ] );
|
138 |
+
}
|
139 |
+
} else {
|
140 |
+
$inner_sql = $wpdb->prepare( $inner_sql_template, $field->id, $form_id, $form_id, doubleval( $field->id ) - 0.0001, doubleval( $field->id ) + 0.0001, $value, $value );
|
141 |
+
}
|
142 |
+
|
143 |
+
$sql .= $inner_sql . "
|
144 |
+
) as count
|
145 |
+
GROUP BY lead_id
|
146 |
+
ORDER BY match_count DESC";
|
147 |
+
|
148 |
+
$count = gf_apply_filters( 'gform_is_duplicate_better', $form_id, $wpdb->get_var( $sql ), $form_id, $field, $value );
|
149 |
+
|
150 |
+
return $count != null && $count >= $input_count;
|
151 |
+
}
|
152 |
+
|
153 |
+
public static function get_base_url() {
|
154 |
+
return plugins_url( '', dirname( __FILE__ ) );
|
155 |
+
}
|
156 |
+
|
157 |
+
public static function get_mysql_tz_offset() {
|
158 |
+
|
159 |
+
$time_zone_orig = $time_zone = get_option( 'gmt_offset' );
|
160 |
+
|
161 |
+
$prefix = intval( $time_zone ) > 0 ? '+' : '-';
|
162 |
+
$time_zone = abs( $time_zone ) * 3600;
|
163 |
+
$time_zone = gmdate( 'H:i', $time_zone );
|
164 |
+
$time_zone = $prefix . $time_zone;
|
165 |
+
|
166 |
+
$today = date( 'Y-m-d H:i:s' );
|
167 |
+
$date = new DateTime( $today );
|
168 |
+
|
169 |
+
$tzn = abs( $time_zone_orig ) * 3600;
|
170 |
+
$tzh = intval( gmdate( 'H', $tzn ) );
|
171 |
+
$tzm = intval( gmdate( 'i', $tzn ) );
|
172 |
+
try {
|
173 |
+
if ( intval( $time_zone_orig ) < 0 ) {
|
174 |
+
$date->sub( new DateInterval( 'P0DT' . $tzh . 'H' . $tzm . 'M' ) );
|
175 |
+
} else {
|
176 |
+
$date->add( new DateInterval( 'P0DT' . $tzh . 'H' . $tzm . 'M' ) );
|
177 |
+
}
|
178 |
+
} catch ( Exception $e ) {
|
179 |
+
return array( 'tz' => $time_zone, 'today' => time() );
|
180 |
+
}
|
181 |
+
$today = $date->format( 'Y-m-d H:i:s' );
|
182 |
+
$today = strtotime( $today );
|
183 |
+
|
184 |
+
return array( 'tz' => $time_zone, 'today' => $today );
|
185 |
+
}
|
186 |
+
}
|
187 |
+
endif;
|
188 |
+
|
189 |
+
|
190 |
+
if ( ! class_exists( 'GFParsi_MelliCode' ) ) :
|
191 |
+
|
192 |
+
class GFParsi_MelliCode {
|
193 |
+
|
194 |
+
private $field = array();
|
195 |
+
|
196 |
+
public function __construct() {
|
197 |
+
|
198 |
+
if ( GFPersian_Core::_option( 'national_id', '1' ) != '1' ) {
|
199 |
+
return;
|
200 |
+
}
|
201 |
+
|
202 |
+
if ( is_admin() ) {
|
203 |
+
add_filter( 'gform_add_field_buttons', array( $this, 'button' ) );
|
204 |
+
add_filter( 'gform_field_type_title', array( $this, 'title' ) );
|
205 |
+
add_filter( 'gform_editor_js_set_default_values', array( $this, 'label' ) );
|
206 |
+
add_action( 'gform_editor_js', array( $this, 'settings' ) );
|
207 |
+
add_action( 'gform_field_standard_settings', array( $this, 'standard_settings' ), 10, 2 );
|
208 |
+
add_filter( 'gform_tooltips', array( $this, 'tooltips' ) );
|
209 |
+
add_filter( 'gform_admin_pre_render', array( $this, 'admin_conditional_logic' ) );
|
210 |
+
}
|
211 |
+
|
212 |
+
add_action( 'gform_field_input', array( $this, 'input' ), 10, 5 );
|
213 |
+
add_action( 'gform_field_css_class', array( $this, 'classes' ), 10, 3 );
|
214 |
+
add_action( 'gform_pre_submission', array( $this, 'pre_submission' ) );
|
215 |
+
add_filter( 'gform_field_content', array( $this, 'city' ), 10, 5 );
|
216 |
+
add_filter( 'gform_field_validation', array( $this, 'validator' ), 10, 4 );
|
217 |
+
add_action( 'wp_footer', array( $this, 'js' ) );
|
218 |
+
add_action( 'gform_enqueue_scripts', array( $this, 'external_js' ), 10, 2 );
|
219 |
+
}
|
220 |
+
|
221 |
+
public function button( $field_groups ) {
|
222 |
+
foreach ( $field_groups as &$group ) {
|
223 |
+
if ( $group["name"] == "gf_persian_fields" ) {
|
224 |
+
$group["fields"][] = array(
|
225 |
+
"class" => "button",
|
226 |
+
"value" => 'کد ملی',
|
227 |
+
"onclick" => "StartAddField('mellicart');"
|
228 |
+
);
|
229 |
+
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
return $field_groups;
|
234 |
+
}
|
235 |
+
|
236 |
+
public function title( $type ) {
|
237 |
+
if ( $type == 'mellicart' ) {
|
238 |
+
return 'کد ملی';
|
239 |
+
}
|
240 |
+
|
241 |
+
return $type;
|
242 |
+
}
|
243 |
+
|
244 |
+
public function label() {
|
245 |
+
?>
|
246 |
+
case "mellicart" :
|
247 |
+
field.label = 'کد ملی';
|
248 |
+
break;
|
249 |
+
<?php
|
250 |
+
}
|
251 |
+
|
252 |
+
public function classes( $classes, $field, $form ) {
|
253 |
+
if ( $field["type"] == "mellicart" ) {
|
254 |
+
$classes .= " gform_melli_code";
|
255 |
+
}
|
256 |
+
|
257 |
+
return $classes;
|
258 |
+
}
|
259 |
+
|
260 |
+
public function tooltips( $tooltips ) {
|
261 |
+
$tooltips['gform_melli_code_city'] = '<h6>نمایش لحظه ای شهر از روی کد ملی </h6>نمایش شهر و پیغام زیر فیلد کد ملی بعد از پر شدن فیلد . تذکر : در صورتی که این گزینه را فعال نمایید ،ممکن است فراخوانی شهر های ایران با توجه به زیاد بودن آنها سبب سنگین شدن صفحه گردد.';
|
262 |
+
$tooltips['gform_melli_code_seperate'] = '<h6>جدا سازی ارقام</h6>در صورتی که این گزینه را فعال نمایید ، پس از پر شدن فیلد کد ملی ، <strong>در صورتی که کد ملی وارد شده صحیح تشخصی داده شود</strong> ؛ کد ملی به صورت زیر در خواهد آمد و در غیر این صورت علی صحیح نبودن کد ملی زیر فیلد نمایش داده خواهد شد :<br>xxx-xxxxxx-x';
|
263 |
+
$tooltips['gform_melli_code_abnormal'] = 'با توجه به اینکه کد ملی فقط باید به صورت عدد باشد ، در صورتی که کاراکتری غیر از عدد وارد شده باشد پیغام خطا نمایش داده خواهد شد .<br/>پیغام پیشفرض : کد ملی فقط باید به صورت عدد وارد شود .';
|
264 |
+
$tooltips['gform_melli_code_len'] = 'با توجه به اینکه کد ملی می بایست 10 رقمی باشد اگر تعداد رقم وارد شده ، اشتباه باشد پیغام خطا نمایش داده خواهد شد .<br>پیغام پیشفرض : کد ملی می بایست 10 رقمی باشد . تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند .';
|
265 |
+
$tooltips['gform_melli_code_dup'] = 'در صورتی که از تب وِیژگی تیک گزینه بدون تکرار را زده باشید ؛ بعد از پر شدن فرم و زدن دکمه ارسال پیغامی مبتنی بر تکراری بودن کد ملی نمایش داده خواهد شد . <br/>پیغام پیشفرض : این کد ملی توسط فرد دیگری ثبت شده است .';
|
266 |
+
$tooltips['gform_melli_code_noStandard'] = 'در صورتی که کد ملی وارد شده مطابق با الگوریتم کشور نباشد پیغام خطا نمایش داده خواهد شد .<br/>پیغام پیشفرض : کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .';
|
267 |
+
|
268 |
+
return $tooltips;
|
269 |
+
}
|
270 |
+
|
271 |
+
public function input( $input, $field, $value, $lead_id, $form_id ) {
|
272 |
+
|
273 |
+
if ( $field["type"] == "mellicart" ) {
|
274 |
+
|
275 |
+
$is_admin = is_admin();
|
276 |
+
$is_frontend = ! $is_admin;
|
277 |
+
$is_form_editor = ( $is_admin && GFForms::get( 'view' ) != 'entry' );
|
278 |
+
$is_entry_page = ( $is_admin && GFForms::get( 'view' ) == 'entry' );
|
279 |
+
|
280 |
+
if ( ! $is_admin && ( RGFormsModel::get_input_type( $field ) == 'adminonly_hidden' ) ) {
|
281 |
+
return '';
|
282 |
+
}
|
283 |
+
|
284 |
+
$field_id = $field["id"];
|
285 |
+
$form_id = $is_admin && empty( $form_id ) ? rgget( "id" ) : $form_id;
|
286 |
+
|
287 |
+
$disabled_text = ( $is_admin && rgget( 'view' ) != 'entry' ) ? "disabled='disabled'" : '';
|
288 |
+
|
289 |
+
$size = rgar( $field, "size" );
|
290 |
+
$class_suffix = GFForms::get( 'view' ) == 'entry' ? '_admin' : '';
|
291 |
+
$class = $size . $class_suffix;
|
292 |
+
|
293 |
+
$html5_attributes = '';
|
294 |
+
|
295 |
+
$tabindex = GFCommon::get_tabindex();
|
296 |
+
|
297 |
+
|
298 |
+
//$this->get_conditional_logic_event( 'keyup' ) //text or radio
|
299 |
+
//$this->get_conditional_logic_event( 'change' ) //select
|
300 |
+
//$this->get_conditional_logic_event( 'click' ) // checkbox or radio
|
301 |
+
//note : radio has keyup and click
|
302 |
+
$logic_event = ! $is_form_editor && ! $is_entry_page ? $field->get_conditional_logic_event( 'keyup' ) : '';
|
303 |
+
|
304 |
+
$input = '<div class="ginput_container ginput_container_text ginput_container_melli_code">';
|
305 |
+
$input .= '<input onblur="melli_code_' . $field_id . '(this);" name="input_' . $field_id . '" id="input_' . $form_id . '_' . $field_id . '" type="text" value="' . esc_attr( $value ) . '" class="melli_code ' . esc_attr( $size ) . '" ' . $tabindex . ' ' . $logic_event . ' ' . $html5_attributes . ' ' . $disabled_text . '/>';
|
306 |
+
$input .= '</div>';
|
307 |
+
|
308 |
+
if ( $is_frontend ) {
|
309 |
+
$input .= '<span class="city melli_code" id="ir_national_id_location_' . $field_id . '"></span>';
|
310 |
+
}
|
311 |
+
|
312 |
+
}
|
313 |
+
|
314 |
+
return $input;
|
315 |
+
}
|
316 |
+
|
317 |
+
public function settings() { ?>
|
318 |
+
<script type='text/javascript'>
|
319 |
+
fieldSettings["mellicart"] = ".placeholder_setting, .input_mask_setting, .label_placement_setting, .prepopulate_field_setting, .conditional_logic_field_setting, .label_setting, .admin_label_setting, .size_setting, .rules_setting, .visibility_setting, .duplicate_setting, .default_value_setting, .description_setting, .css_class_setting, .mellicart_setting";
|
320 |
+
jQuery(document).bind("gform_load_field_settings", function (event, field, form) {
|
321 |
+
jQuery("#field_mellicart").attr("checked", field["field_mellicart"] == true);
|
322 |
+
jQuery("#field_mellicart_sp").attr("checked", field["field_mellicart_sp"] == true);
|
323 |
+
jQuery("#field_mellicart_sp1").val(field["field_mellicart_sp1"]);
|
324 |
+
jQuery("#field_mellicart_sp2").val(field["field_mellicart_sp2"]);
|
325 |
+
jQuery("#field_mellicart_sp3").val(field["field_mellicart_sp3"]);
|
326 |
+
jQuery("#field_mellicart_sp4").val(field["field_mellicart_sp4"]);
|
327 |
+
});
|
328 |
+
</script>
|
329 |
+
<?php
|
330 |
+
}
|
331 |
+
|
332 |
+
|
333 |
+
public function admin_conditional_logic( $form ) {
|
334 |
+
|
335 |
+
if ( GFCommon::is_entry_detail() ) {
|
336 |
+
return $form;
|
337 |
+
}
|
338 |
+
|
339 |
+
echo "<script type='text/javascript'>" .
|
340 |
+
" gform.addFilter('gform_is_conditional_logic_field', function (isConditionalLogicField, field) {" .
|
341 |
+
" return field.type == 'mellicart' ? true : isConditionalLogicField;" .
|
342 |
+
' });' .
|
343 |
+
" gform.addFilter('gform_conditional_logic_operators', function (operators, objectType, fieldId) {" .
|
344 |
+
' var targetField = GetFieldById(fieldId);' .
|
345 |
+
" if (targetField && targetField['type'] == 'mellicart') {" .
|
346 |
+
" operators = {'is':'is','isnot':'isNot', '>':'greaterThan', '<':'lessThan', 'contains':'contains', 'starts_with':'startsWith', 'ends_with':'endsWith'};" .
|
347 |
+
' }' .
|
348 |
+
' return operators;' .
|
349 |
+
' });' .
|
350 |
+
'</script>';
|
351 |
+
|
352 |
+
return $form;
|
353 |
+
}
|
354 |
+
|
355 |
+
public function standard_settings( $position, $form_id ) {
|
356 |
+
|
357 |
+
if ( $position == 50 ) { ?>
|
358 |
+
|
359 |
+
<li class="mellicart_setting field_setting">
|
360 |
+
|
361 |
+
<input type="checkbox" id="field_mellicart"
|
362 |
+
onclick="SetFieldProperty('field_mellicart', this.checked);"/>
|
363 |
+
<label for="field_mellicart" class="inline">
|
364 |
+
نمایش شهر بر اساس کد ملی
|
365 |
+
<?php gform_tooltip( "gform_melli_code_city" ); ?>
|
366 |
+
</label>
|
367 |
+
|
368 |
+
|
369 |
+
<br/>
|
370 |
+
<input type="checkbox" id="field_mellicart_sp"
|
371 |
+
onclick="SetFieldProperty('field_mellicart_sp', this.checked);"/>
|
372 |
+
<label for="field_mellicart_sp" class="inline">
|
373 |
+
جداسازی خودکار ارقام توسط خط فاصله
|
374 |
+
<?php gform_tooltip( "gform_melli_code_seperate" ); ?>
|
375 |
+
</label>
|
376 |
+
<br/>
|
377 |
+
|
378 |
+
|
379 |
+
<br/>
|
380 |
+
<label for="field_mellicart_sp1">
|
381 |
+
پیغام زمانی که مقدار وارد شده شامل کاراکتر غیر عددی باشد
|
382 |
+
<?php gform_tooltip( "gform_melli_code_abnormal" ); ?>
|
383 |
+
</label>
|
384 |
+
<input type="text" class="fieldwidth-3" id="field_mellicart_sp1" size="35"
|
385 |
+
onkeyup="SetFieldProperty('field_mellicart_sp1', this.value);"/>
|
386 |
+
<br/>
|
387 |
+
|
388 |
+
|
389 |
+
<br/>
|
390 |
+
<label for="field_mellicart_sp2">
|
391 |
+
پیغام زمانیکه تعداد ارقام وارد شده استاندارد نباشد
|
392 |
+
<?php gform_tooltip( "gform_melli_code_len" ); ?>
|
393 |
+
</label>
|
394 |
+
<input type="text" class="fieldwidth-3" id="field_mellicart_sp2" size="35"
|
395 |
+
onkeyup="SetFieldProperty('field_mellicart_sp2', this.value);"/>
|
396 |
+
<br/>
|
397 |
+
|
398 |
+
|
399 |
+
<br/>
|
400 |
+
<label for="field_mellicart_sp3">
|
401 |
+
پیغام زمانیکه کد ملی وارد شده قبلا ثبت شده باشد
|
402 |
+
<?php gform_tooltip( "gform_melli_code_dup" ); ?>
|
403 |
+
</label>
|
404 |
+
<input type="text" class="fieldwidth-3" id="field_mellicart_sp3" size="35"
|
405 |
+
onkeyup="SetFieldProperty('field_mellicart_sp3', this.value);"/>
|
406 |
+
<br/>
|
407 |
+
|
408 |
+
|
409 |
+
<br/>
|
410 |
+
<label for="field_mellicart_sp4">
|
411 |
+
پیغام زمانیکه کد ملی وارد شده مطابق با الگوی ملی نباشد
|
412 |
+
<?php gform_tooltip( "gform_melli_code_noStandard" ); ?>
|
413 |
+
</label>
|
414 |
+
<input type="text" class="fieldwidth-3" id="field_mellicart_sp4" size="35"
|
415 |
+
onkeyup="SetFieldProperty('field_mellicart_sp4', this.value);"/>
|
416 |
+
<br/>
|
417 |
+
|
418 |
+
|
419 |
+
</li>
|
420 |
+
<?php
|
421 |
+
}
|
422 |
+
}
|
423 |
+
|
424 |
+
|
425 |
+
public function pre_submission( $form ) {
|
426 |
+
|
427 |
+
$mellicart_fields = GFCommon::get_fields_by_type( $form, array( 'mellicart' ) );
|
428 |
+
|
429 |
+
foreach ( (array) $mellicart_fields as $field ) {
|
430 |
+
|
431 |
+
$input_name = "input_{$field['id']}";
|
432 |
+
$input_value = ! rgempty( $input_name ) ? rgpost( $input_name ) : '';
|
433 |
+
|
434 |
+
if ( ! empty( $input_value ) ) {
|
435 |
+
|
436 |
+
if ( strlen( $input_value ) == 8 ) {
|
437 |
+
$_POST["input_{$field['id']}"] = '00' . $input_value;
|
438 |
+
} elseif ( strlen( $input_value ) == 9 ) {
|
439 |
+
$_POST["input_{$field['id']}"] = '0' . $input_value;
|
440 |
+
} else {
|
441 |
+
$_POST["input_{$field['id']}"] = $input_value;
|
442 |
+
}
|
443 |
+
}
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
public function city( $content, $field, $value, $lead_id, $form_id ) {
|
448 |
+
|
449 |
+
if ( $field['type'] == 'mellicart' ) {
|
450 |
+
if ( ! is_admin() ) {
|
451 |
+
$this->field[] = $field;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
return $content;
|
456 |
+
}
|
457 |
+
|
458 |
+
public function external_js( $form, $ajax ) {
|
459 |
+
|
460 |
+
$melli_code = GFCommon::get_fields_by_type( $form, array( 'mellicart' ) );
|
461 |
+
|
462 |
+
foreach ( (array) $melli_code as $field ) {
|
463 |
+
|
464 |
+
$is_seperate = rgar( $field, 'field_mellicart_sp' );
|
465 |
+
$is_seperate = ! empty( $is_seperate ) ? $is_seperate : false;
|
466 |
+
|
467 |
+
$show_city = rgar( $field, 'field_mellicart' );
|
468 |
+
$show_city = ! empty( $show_city ) ? $show_city : false;
|
469 |
+
|
470 |
+
if ( $show_city || $is_seperate ) {
|
471 |
+
wp_register_script( 'gform_mellicode', GF_PERSIAN_URL . 'assets/js/national_id.min.js', array(), GF_PERSIAN_VERSION, false );
|
472 |
+
wp_enqueue_script( 'gform_mellicode' );
|
473 |
+
break;
|
474 |
+
}
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
public function js() {
|
479 |
+
|
480 |
+
$fields = $this->field;
|
481 |
+
|
482 |
+
if ( empty( $fields ) ) {
|
483 |
+
return;
|
484 |
+
}
|
485 |
+
|
486 |
+
foreach ( (array) $fields as $field ) {
|
487 |
+
|
488 |
+
$is_seperate = rgar( $field, 'field_mellicart_sp' );
|
489 |
+
$is_seperate = ! empty( $is_seperate ) && $is_seperate ? 1 : 0;
|
490 |
+
|
491 |
+
$show_city = rgar( $field, 'field_mellicart' );
|
492 |
+
$show_city = ! empty( $show_city ) && $show_city ? 1 : 0;
|
493 |
+
|
494 |
+
if ( ! $show_city && ! $is_seperate ) { ?>
|
495 |
+
<script type="text/javascript">
|
496 |
+
function melli_code_<?php echo $field['id']; ?> (melli_code) {
|
497 |
+
}
|
498 |
+
</script>
|
499 |
+
<?php
|
500 |
+
} else {
|
501 |
+
|
502 |
+
$message1 = rgar( $field, 'field_mellicart_sp1' );
|
503 |
+
$message1 = ! empty( $message1 ) ? $message1 : 'کد ملی فقط باید به صورت عدد وارد شود .';
|
504 |
+
|
505 |
+
$message2 = rgar( $field, 'field_mellicart_sp2' );
|
506 |
+
$message2 = ! empty( $message2 ) ? $message2 : 'کد ملی می بایست 10 رقمی باشد .';
|
507 |
+
|
508 |
+
$message3 = rgar( $field, 'field_mellicart_sp4' );
|
509 |
+
$message3 = ! empty( $message3 ) ? $message3 : 'کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .';
|
510 |
+
?>
|
511 |
+
|
512 |
+
<script type="text/javascript">
|
513 |
+
function melli_code_<?php echo $field['id']; ?> (melli_code) {
|
514 |
+
var field_id = "<?php echo $field['id'] ?>";
|
515 |
+
var message1 = "<?php echo $message1 ?>";
|
516 |
+
var message2 = "<?php echo $message2 ?>";
|
517 |
+
var message3 = "<?php echo $message3 ?>";
|
518 |
+
var show_city = <?php echo $show_city ?>;
|
519 |
+
var is_seperate = <?php echo $is_seperate ?>;
|
520 |
+
GFPersian_National_ID_Handler(melli_code, field_id, message1, message2, message3, is_seperate, show_city);
|
521 |
+
jQuery(melli_code).trigger('change');
|
522 |
+
}
|
523 |
+
</script>
|
524 |
+
|
525 |
+
<?php
|
526 |
+
}
|
527 |
+
}
|
528 |
+
}
|
529 |
+
|
530 |
+
public function is_valid( $melli_code = '' ) {
|
531 |
+
|
532 |
+
if ( ! empty( $melli_code ) ) {
|
533 |
+
|
534 |
+
$_melli_code = $melli_code;
|
535 |
+
|
536 |
+
if ( strlen( $melli_code ) == 8 ) {
|
537 |
+
$_melli_code = '00' . $melli_code;
|
538 |
+
}
|
539 |
+
|
540 |
+
if ( strlen( $melli_code ) == 9 ) {
|
541 |
+
$_melli_code = '0' . $melli_code;
|
542 |
+
}
|
543 |
+
|
544 |
+
$pre_check = array(
|
545 |
+
'0000000000',
|
546 |
+
'1111111111',
|
547 |
+
'2222222222',
|
548 |
+
'3333333333',
|
549 |
+
'4444444444',
|
550 |
+
'5555555555',
|
551 |
+
'6666666666',
|
552 |
+
'7777777777',
|
553 |
+
'8888888888',
|
554 |
+
'9999999999',
|
555 |
+
'0123456789',
|
556 |
+
);
|
557 |
+
|
558 |
+
if ( in_array( $_melli_code, $pre_check ) ) {
|
559 |
+
return 2;
|
560 |
+
}
|
561 |
+
|
562 |
+
if ( ! is_numeric( $melli_code ) ) {
|
563 |
+
return 4;
|
564 |
+
}
|
565 |
+
|
566 |
+
$melli_code = (string) preg_replace( '/[^0-9]/', '', $melli_code );
|
567 |
+
|
568 |
+
if ( strlen( $melli_code ) > 10 || strlen( $melli_code ) < 8 ) {
|
569 |
+
return 3;
|
570 |
+
}
|
571 |
+
|
572 |
+
$melli_code = $_melli_code;
|
573 |
+
|
574 |
+
$list_code = str_split( $melli_code );
|
575 |
+
$last = (int) $list_code[9];
|
576 |
+
unset( $list_code[9] );
|
577 |
+
|
578 |
+
$i = 10;
|
579 |
+
$sum = 0;
|
580 |
+
foreach ( $list_code as $key => $val ) {
|
581 |
+
$sum += intval( $val ) * $i;
|
582 |
+
$i --;
|
583 |
+
}
|
584 |
+
|
585 |
+
$mod = (int) $sum % 11;
|
586 |
+
|
587 |
+
if ( $mod >= 2 ) {
|
588 |
+
$mod = 11 - $mod;
|
589 |
+
}
|
590 |
+
if ( $mod != $last ) {
|
591 |
+
return 2;
|
592 |
+
} else {
|
593 |
+
return 1;
|
594 |
+
}
|
595 |
+
}
|
596 |
+
|
597 |
+
return false;
|
598 |
+
}
|
599 |
+
|
600 |
+
|
601 |
+
public function validator( $result, $value, $form, $field ) {
|
602 |
+
|
603 |
+
if ( $field["type"] == 'mellicart' ) {
|
604 |
+
|
605 |
+
$melli_code = ! empty( $value ) ? str_replace( '-', '', $value ) : '';
|
606 |
+
|
607 |
+
$is_valid = $this->is_valid( $melli_code );
|
608 |
+
|
609 |
+
if ( $is_valid == 4 ) {
|
610 |
+
$message = rgar( $field, 'field_mellicart_sp1' );
|
611 |
+
$result['message'] = ! empty( $message ) ? $message : 'کد ملی فقط باید به صورت عدد وارد شود .';
|
612 |
+
$result['is_valid'] = false;
|
613 |
+
|
614 |
+
return $result;
|
615 |
+
}
|
616 |
+
|
617 |
+
if ( $is_valid == 3 ) {
|
618 |
+
$message = rgar( $field, 'field_mellicart_sp2' );
|
619 |
+
$result['message'] = ! empty( $message ) ? $message : 'کد ملی می بایست 10 رقمی باشد . تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند .';
|
620 |
+
$result['is_valid'] = false;
|
621 |
+
|
622 |
+
return $result;
|
623 |
+
}
|
624 |
+
|
625 |
+
if ( $is_valid == 2 ) {
|
626 |
+
$message = rgar( $field, 'field_mellicart_sp4' );
|
627 |
+
$result['message'] = ! empty( $message ) ? $message : 'کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .';
|
628 |
+
$result['is_valid'] = false;
|
629 |
+
|
630 |
+
return $result;
|
631 |
+
}
|
632 |
+
|
633 |
+
if ( $field['noDuplicates'] ) {
|
634 |
+
|
635 |
+
if ( strlen( $melli_code ) == 8 ) {
|
636 |
+
$melli_code = '00' . $melli_code;
|
637 |
+
}
|
638 |
+
|
639 |
+
if ( strlen( $melli_code ) == 9 ) {
|
640 |
+
$melli_code = '0' . $melli_code;
|
641 |
+
}
|
642 |
+
|
643 |
+
if ( RGFormsModel::is_duplicate( $form['id'], $field, $melli_code ) ) {
|
644 |
+
$message = rgar( $field, 'field_mellicart_sp3' );
|
645 |
+
$result['message'] = ! empty( $message ) ? $message : 'این کد ملی توسط فرد دیگری ثبت شده است .';
|
646 |
+
$result['is_valid'] = false;
|
647 |
+
|
648 |
+
return $result;
|
649 |
+
}
|
650 |
+
}
|
651 |
+
}
|
652 |
+
|
653 |
+
return $result;
|
654 |
+
}
|
655 |
+
}
|
656 |
+
|
657 |
+
endif;
|
includes/class-jalali-date.php
CHANGED
@@ -1,281 +1,162 @@
|
|
1 |
-
<?php if ( ! defined('ABSPATH') )
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
add_filter('
|
15 |
-
add_action('
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
19 |
}
|
20 |
-
|
21 |
public function tooltips( $tooltips ) {
|
22 |
-
$tooltips[
|
|
|
23 |
return $tooltips;
|
24 |
}
|
25 |
|
26 |
-
public function jalali_settings(){ ?>
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
<?php
|
34 |
}
|
35 |
-
|
36 |
-
public function jalali_checkbox( $position, $form_id ){
|
37 |
-
if( $position == 25 ) { ?>
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
|
|
46 |
}
|
47 |
}
|
48 |
-
|
49 |
-
public function
|
50 |
-
|
51 |
-
if ( !is_admin() && ( wp_script_is( 'gform_datepicker_init' ) || wp_script_is( 'gform_datepicker_init', 'registered' ) ) ) {
|
52 |
-
|
53 |
-
$is_jalali = false;
|
54 |
-
|
55 |
foreach ( $form['fields'] as $field ) {
|
56 |
-
|
57 |
-
if ( $field['type'] == 'date' &&
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
break;
|
60 |
}
|
61 |
}
|
62 |
-
|
63 |
-
if ( $is_jalali ) {
|
64 |
-
|
65 |
-
wp_dequeue_script('jquery-ui-datepicker');
|
66 |
-
wp_deregister_script('jquery-ui-datepicker');
|
67 |
-
|
68 |
-
wp_register_script('jquery-ui-datepicker', GF_PARSI_URL . 'assets/js/jalali.date.picker.js', array( 'jquery', 'jquery-migrate', 'jquery-ui-core', 'gform_gravityforms' ), GF_PARSI_VERSION, true );
|
69 |
-
wp_enqueue_script( 'jquery-ui-datepicker' );
|
70 |
-
}
|
71 |
-
|
72 |
-
}
|
73 |
}
|
74 |
|
75 |
-
public function
|
76 |
-
?>
|
77 |
-
<script type="text/javascript">
|
78 |
-
jQuery(document).ready(function ($) {
|
79 |
-
|
80 |
-
jQuery('.datepicker').datepicker({
|
81 |
-
showOn: 'both',
|
82 |
-
buttonImage: "<?php echo GFCommon::get_base_url() ?>/images/calendar.png",
|
83 |
-
buttonImageOnly: true,
|
84 |
-
changeMonth: true,
|
85 |
-
changeYear: true,
|
86 |
-
showButtonPanel: true,
|
87 |
-
onSelect: function(dateStr, inst) {
|
88 |
-
var selectedJalaliDate = new JalaliDate(inst.selectedYear, inst.selectedMonth, inst.selectedDay);
|
89 |
-
var date = selectedJalaliDate.getGregorianDate();
|
90 |
-
var month= date.getMonth()+1;
|
91 |
-
var day = date.getDate() < 10 ? '0'+date.getDate() : date.getDate();
|
92 |
-
var months = date.getMonth() < 9 ? '0'+month : month;
|
93 |
-
$(this).val(months + '/' + day + '/' + date.getFullYear());
|
94 |
-
}
|
95 |
-
});
|
96 |
-
|
97 |
-
jQuery('#export_date_start').datepicker({
|
98 |
-
changeMonth: true,
|
99 |
-
changeYear: true,
|
100 |
-
showButtonPanel: true,
|
101 |
-
onSelect: function(dateStr, inst) {
|
102 |
-
var selectedJalaliDate = new JalaliDate(inst.selectedYear, inst.selectedMonth, inst.selectedDay);
|
103 |
-
var date = selectedJalaliDate.getGregorianDate();
|
104 |
-
var month= date.getMonth()+1;
|
105 |
-
var day = date.getDate() < 10 ? '0'+date.getDate() : date.getDate();
|
106 |
-
var months = date.getMonth() < 9 ? '0'+month : month;
|
107 |
-
$(this).val(date.getFullYear() + '-' + months + '-' + day);
|
108 |
-
}
|
109 |
-
});
|
110 |
-
|
111 |
-
jQuery('#export_date_end').datepicker({
|
112 |
-
changeMonth: true,
|
113 |
-
changeYear: true,
|
114 |
-
showButtonPanel: true,
|
115 |
-
onSelect: function(dateStr, inst) {
|
116 |
-
var selectedJalaliDate = new JalaliDate(inst.selectedYear, inst.selectedMonth, inst.selectedDay);
|
117 |
-
var date = selectedJalaliDate.getGregorianDate();
|
118 |
-
var month= date.getMonth()+1;
|
119 |
-
var day = date.getDate() < 10 ? '0'+date.getDate() : date.getDate();
|
120 |
-
var months = date.getMonth() < 9 ? '0'+month : month;
|
121 |
-
$(this).val(date.getFullYear() + '-' + months + '-' + day);
|
122 |
-
}
|
123 |
-
});
|
124 |
-
|
125 |
-
});
|
126 |
-
|
127 |
-
</script>
|
128 |
-
<?php
|
129 |
-
}
|
130 |
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
wp_dequeue_script('jquery-ui-datepicker');
|
136 |
-
wp_deregister_script('jquery-ui-datepicker');
|
137 |
-
|
138 |
-
if ( ! wp_script_is( 'jquery-ui-core' ))
|
139 |
-
wp_enqueue_script('jquery-ui-core');
|
140 |
-
|
141 |
-
wp_register_script('gform_datepicker_jalali_admin', GF_PARSI_URL . 'assets/js/jalali.date.picker.js', array( 'jquery', 'jquery-ui-core' ), GF_PARSI_VERSION, true );
|
142 |
-
wp_enqueue_script( 'gform_datepicker_jalali_admin' );
|
143 |
}
|
|
|
|
|
144 |
}
|
145 |
-
|
146 |
-
public function
|
147 |
-
|
148 |
-
if ( $field
|
149 |
-
$
|
150 |
-
$
|
151 |
-
}
|
152 |
-
|
153 |
-
return apply_filters( 'jalali_date_min', $min_year, $form, $field );
|
154 |
-
}
|
155 |
-
|
156 |
-
public function jalali_date_max($max_year, $form, $field ){
|
157 |
-
|
158 |
-
if ( $field->type == 'date' && !empty($field->check_jalali) ) {
|
159 |
-
$max_year = GF_gregorian_to_jalali($max_year,03,21);
|
160 |
-
$max_year = $max_year[0]+20;
|
161 |
}
|
162 |
-
|
163 |
-
return apply_filters( '
|
164 |
}
|
165 |
-
|
166 |
-
public function jalali_validator($result, $value, $form, $field){
|
167 |
-
|
168 |
-
if ( $field
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
$max = 29;
|
202 |
-
}
|
203 |
-
|
204 |
-
if ( intval($date["day"]) >= $min && intval($date["day"]) <= $max ) {
|
205 |
-
$gregorian = GF_jalali_to_gregorian($date["year"],$date["month"],$date["day"]);
|
206 |
-
$day = $gregorian[2];
|
207 |
-
$month = $gregorian[1];
|
208 |
-
$year = $gregorian[0];
|
209 |
-
$result["is_valid"] = $this->jalali_checkdate($month, $day, $year);
|
210 |
-
}
|
211 |
-
else
|
212 |
-
$result["is_valid"] = false;
|
213 |
-
|
214 |
-
}
|
215 |
-
else
|
216 |
-
$result["is_valid"] = false;
|
217 |
-
}
|
218 |
-
else
|
219 |
-
$result["is_valid"] = false;
|
220 |
-
|
221 |
-
if( empty($date) || !$result["is_valid"] ) {
|
222 |
-
|
223 |
-
$format_name = '';
|
224 |
-
switch($format) {
|
225 |
-
|
226 |
-
case "mdy" :
|
227 |
-
$format_name = "mm/dd/yyyy";
|
228 |
-
break;
|
229 |
-
|
230 |
-
case "dmy" :
|
231 |
-
$format_name = "dd/mm/yyyy";
|
232 |
-
break;
|
233 |
-
case "dmy_dash" :
|
234 |
-
$format_name = "dd-mm-yyyy";
|
235 |
-
break;
|
236 |
-
case "dmy_dot" :
|
237 |
-
$format_name = "dd.mm.yyyy";
|
238 |
-
break;
|
239 |
-
|
240 |
-
case "ymd_slash" :
|
241 |
-
$format_name = "yyyy/mm/dd";
|
242 |
-
break;
|
243 |
-
|
244 |
-
case "ymd_dash" :
|
245 |
-
$format_name = "yyyy-mm-dd";
|
246 |
-
break;
|
247 |
-
case "ymd_dot" :
|
248 |
-
$format_name = "yyyy.mm.dd";
|
249 |
-
break;
|
250 |
-
}
|
251 |
-
|
252 |
-
$result["is_valid"] = false;
|
253 |
-
$message = $field["dateType"] == "datepicker" ? sprintf(__("Please enter a valid date in the format (%s).", "gravityforms"), $format_name) : __("Please enter a valid date.", "gravityforms");
|
254 |
-
$result["message"] = empty($field["errorMessage"]) ? $message : $field["errorMessage"];
|
255 |
-
}
|
256 |
-
else
|
257 |
-
$result["is_valid"] = true;
|
258 |
}
|
259 |
}
|
260 |
}
|
261 |
-
|
262 |
return $result;
|
263 |
}
|
264 |
|
265 |
-
public function
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
|
|
|
|
|
|
|
|
|
|
278 |
}
|
|
|
279 |
}
|
280 |
|
281 |
-
new
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_JalaliDate extends GFPersian_Core {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
|
9 |
+
if ( $this->option( 'jalali', '1' ) != '1' ) {
|
10 |
+
return;
|
11 |
+
}
|
12 |
+
|
13 |
+
require_once( 'lib/jalali.php' );
|
14 |
+
add_filter( 'gform_tooltips', array( $this, 'tooltips' ) );
|
15 |
+
add_action( 'gform_editor_js', array( $this, 'jalali_settings' ) );
|
16 |
+
add_action( 'gform_field_standard_settings', array( $this, 'jalali_checkbox' ), 10, 2 );
|
17 |
+
add_action( 'gform_enqueue_scripts', array( $this, 'jalali_datepicker' ), 11, 1 );
|
18 |
+
add_filter( 'gform_date_min_year', array( $this, 'jalali_date_min' ), 10, 3 );
|
19 |
+
add_filter( 'gform_date_max_year', array( $this, 'jalali_date_max' ), 10, 3 );
|
20 |
+
add_filter( 'gform_field_validation', array( $this, 'jalali_validator' ), 999999, 4 );
|
21 |
+
add_filter( 'gform_predefined_choices', array( $this, 'jalali_predefined_choices' ), 1 );
|
22 |
}
|
23 |
+
|
24 |
public function tooltips( $tooltips ) {
|
25 |
+
$tooltips['gform_activate_jalali'] = '<h6>فعالسازی تاریخ شمسی</h6>در صورتی که از چند فیلد تاریخ استفاده میکنید، فعالسازی تاریخ شمسی یکی از فیلدها کفایت میکند.<br/>تذکر : با توجه به آزمایشی بودن این قسمت ممکن است تداخل توابع سبب ناسازگاری با برخی قالب ها شود.';
|
26 |
+
|
27 |
return $tooltips;
|
28 |
}
|
29 |
|
30 |
+
public function jalali_settings() { ?>
|
31 |
+
<script type='text/javascript'>
|
32 |
+
fieldSettings['date'] += ', .jalali_setting';
|
33 |
+
jQuery(document).bind('gform_load_field_settings', function (event, field, form) {
|
34 |
+
jQuery('#check_jalali').attr('checked', field['check_jalali'] == true);
|
35 |
+
});
|
36 |
+
</script>
|
37 |
<?php
|
38 |
}
|
39 |
+
|
40 |
+
public function jalali_checkbox( $position, $form_id ) {
|
41 |
+
if ( $position == 25 ) { ?>
|
42 |
+
<li class="jalali_setting field_setting">
|
43 |
+
<input type="checkbox" id="check_jalali"
|
44 |
+
onclick="SetFieldProperty('check_jalali', jQuery(this).is(':checked') ? 1 : 0);"/>
|
45 |
+
<label class="inline gfield_value_label" for="check_jalali" class="inline">
|
46 |
+
فعالسازی تاریخ شمسی
|
47 |
+
<?php gform_tooltip( "gform_activate_jalali" ) ?>
|
48 |
+
</label>
|
49 |
+
</li>
|
50 |
+
<?php
|
51 |
}
|
52 |
}
|
53 |
+
|
54 |
+
public function jalali_datepicker( $form ) {
|
55 |
+
|
56 |
+
if ( ! is_admin() && ( wp_script_is( 'gform_datepicker_init' ) || wp_script_is( 'gform_datepicker_init', 'registered' ) ) ) {
|
57 |
+
|
|
|
|
|
58 |
foreach ( $form['fields'] as $field ) {
|
59 |
+
|
60 |
+
if ( $field['type'] == 'date' && rgar( $field, 'check_jalali' ) ) {
|
61 |
+
|
62 |
+
wp_dequeue_script( 'jquery-ui-datepicker' );
|
63 |
+
wp_deregister_script( 'jquery-ui-datepicker' );
|
64 |
+
|
65 |
+
wp_register_script( 'jquery-ui-datepicker', GF_PERSIAN_URL . 'assets/js/jalali-datepicker.js', array(
|
66 |
+
'jquery',
|
67 |
+
'jquery-migrate',
|
68 |
+
'jquery-ui-core',
|
69 |
+
'gform_gravityforms'
|
70 |
+
), GF_PERSIAN_VERSION, true );
|
71 |
+
wp_enqueue_script( 'jquery-ui-datepicker' );
|
72 |
break;
|
73 |
}
|
74 |
}
|
75 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
}
|
77 |
|
78 |
+
public function jalali_date_min( $min_year, $form, $field ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
+
if ( rgar( $field, 'type' ) == 'date' && rgar( $field, 'check_jalali' ) ) {
|
81 |
+
$min_year = GF_gregorian_to_jalali( $min_year, 03, 21 );
|
82 |
+
$min_year = $min_year[0] + 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
+
|
85 |
+
return apply_filters( 'gform_jalali_date_min_year', $min_year, $form, $field );
|
86 |
}
|
87 |
+
|
88 |
+
public function jalali_date_max( $max_year, $form, $field ) {
|
89 |
+
|
90 |
+
if ( rgar( $field, 'type' ) == 'date' && rgar( $field, 'check_jalali' ) ) {
|
91 |
+
$max_year = GF_gregorian_to_jalali( $max_year, 03, 21 );
|
92 |
+
$max_year = $max_year[0] + 20;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
}
|
94 |
+
|
95 |
+
return apply_filters( 'gform_jalali_date_max_year', $max_year, $form, $field );
|
96 |
}
|
97 |
+
|
98 |
+
public function jalali_validator( $result, $value, $form, $field ) {
|
99 |
+
|
100 |
+
if ( rgar( $field, 'type' ) == 'date' && rgar( $field, 'check_jalali' ) ) {
|
101 |
+
|
102 |
+
$format = rgar( $field, 'dateFormat', 'mdy' );
|
103 |
+
$formats = array(
|
104 |
+
'mdy' => 'mm/dd/yyyy',
|
105 |
+
'dmy' => 'dd/mm/yyyy',
|
106 |
+
'dmy_dash' => 'dd-mm-yyyy',
|
107 |
+
'dmy_dot' => 'dd.mm.yyyy',
|
108 |
+
'ymd_slash' => 'yyyy/mm/dd',
|
109 |
+
'ymd_dash' => 'yyyy-mm-dd',
|
110 |
+
'ymd_dot' => 'yyyy.mm.dd'
|
111 |
+
);
|
112 |
+
$format_name = ! empty( $formats[ $format ] ) ? $formats[ $format ] : '';
|
113 |
+
$message = $format_name && rgar( $field, 'dateType' ) == 'datepicker' ? sprintf( esc_html__( 'Please enter a valid date in the format (%s).', 'gravityforms' ), $format_name ) : esc_html__( 'Please enter a valid date.', 'gravityforms' );
|
114 |
+
|
115 |
+
/*این شرط مشخص میکنه فقط اگر خطایی وجود نداشت و یا اگر خطا مربوط به ولیدیت تاریخ بود وارد بررسی شود*/
|
116 |
+
if ( ! empty( $result['message'] ) && $message != $result['message'] ) {
|
117 |
+
return $result;
|
118 |
+
}
|
119 |
+
|
120 |
+
if ( is_array( $value ) && rgempty( 0, $value ) && rgempty( 1, $value ) && rgempty( 2, $value ) ) {
|
121 |
+
$value = null;
|
122 |
+
}
|
123 |
+
|
124 |
+
if ( ! empty( $value ) ) {
|
125 |
+
$date = GFCommon::parse_date( $value, $format );
|
126 |
+
$day = intval( rgar( $date, 'day' ) );
|
127 |
+
$month = intval( rgar( $date, 'month' ) );
|
128 |
+
$year = intval( rgar( $date, 'year' ) );
|
129 |
+
|
130 |
+
$result['is_valid'] = GF_jcheckdate( $month, $day, $year );
|
131 |
+
if ( ! $result['is_valid'] && empty( $result['message'] ) ) {
|
132 |
+
$result['message'] = $message;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
}
|
134 |
}
|
135 |
}
|
136 |
+
|
137 |
return $result;
|
138 |
}
|
139 |
|
140 |
+
public function jalali_predefined_choices( $choices ) {
|
141 |
+
|
142 |
+
$month['ماه های ایران'] = array(
|
143 |
+
'فروردین',
|
144 |
+
'اردیبهشت',
|
145 |
+
'خرداد',
|
146 |
+
'تیر',
|
147 |
+
'مرداد',
|
148 |
+
'شهریور',
|
149 |
+
'مهر',
|
150 |
+
'آبان',
|
151 |
+
'آذر',
|
152 |
+
'دی',
|
153 |
+
'بهمن',
|
154 |
+
'اسفند'
|
155 |
+
);
|
156 |
+
|
157 |
+
return array_merge( $month, $choices );
|
158 |
}
|
159 |
+
|
160 |
}
|
161 |
|
162 |
+
new GFPersian_JalaliDate();
|
includes/class-live-preview.php
CHANGED
@@ -1,106 +1,112 @@
|
|
1 |
-
<?php if ( ! defined('ABSPATH') )
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
add_filter( 'gform_form_actions', array( $this, 'gform_form_actions' ), 10, 2 );
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
$args = array(
|
30 |
-
'label'
|
31 |
-
'description'
|
32 |
-
'public'
|
33 |
'publicly_queryable' => true,
|
34 |
-
'has_archive'
|
35 |
-
'can_export'
|
36 |
-
'supports'
|
37 |
);
|
38 |
-
|
39 |
register_post_type( $this->post_type, $args );
|
40 |
-
|
41 |
// create preview post
|
42 |
$preview_post = get_posts( array( 'post_type' => $this->post_type ) );
|
43 |
-
if( empty( $preview_post ) ) {
|
44 |
-
|
45 |
-
'post_type'
|
46 |
-
'post_title'
|
47 |
'post_status' => 'publish'
|
48 |
) );
|
49 |
}
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
57 |
return;
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
61 |
// quick hack for GF to ensure scripts/styles are loaded correctly
|
62 |
-
foreach( $wp_query->posts as &$post ) {
|
63 |
$post->post_content = $this->get_shortcode();
|
64 |
}
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
add_filter( 'the_content', array( $this, 'modify_preview_post_content' ) );
|
72 |
-
|
73 |
-
}
|
74 |
-
|
75 |
-
public function gform_form_actions( $form_actions , $form_id ) {
|
76 |
-
|
77 |
-
|
78 |
-
if ( !empty($_GET['trash']) && $_GET['trash'] == 1 )
|
79 |
return $form_actions;
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
86 |
$sub_menu_items = array();
|
87 |
-
|
88 |
$sub_menu_items[] = array(
|
89 |
'url' => $ajax_true_url,
|
90 |
-
'label' =>
|
91 |
'capabilities' => $capabilities
|
92 |
);
|
93 |
-
|
94 |
$sub_menu_items[] = array(
|
95 |
'url' => $ajax_false_url,
|
96 |
-
'label' =>
|
97 |
'capabilities' => $capabilities
|
98 |
);
|
99 |
-
|
100 |
$form_actions['live_preview'] = array(
|
101 |
-
'label' =>
|
102 |
'icon' => '<i class="fa fa-cogs fa-lg"></i>',
|
103 |
-
'title' =>
|
104 |
'url' => '',
|
105 |
'menu_class' => 'gf_form_toolbar_settings',
|
106 |
'link_class' => 'gf_toolbar_active',
|
@@ -108,83 +114,83 @@ class GFParsi_LivePreview {
|
|
108 |
'capabilities' => $capabilities,
|
109 |
'priority' => 650,
|
110 |
);
|
111 |
-
|
112 |
return $form_actions;
|
113 |
}
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
125 |
<script type="text/javascript">
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
</script>
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
public function is_applicable_page() {
|
145 |
-
return in_array( rgget( 'page' ), array( 'gf_edit_forms', 'gf_entries' ) ) && rgget( 'id' );
|
146 |
-
}
|
147 |
-
|
148 |
public function load_preview_template( $template ) {
|
149 |
-
|
150 |
}
|
151 |
-
|
152 |
-
|
153 |
return $this->get_shortcode();
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
|
|
|
|
|
|
|
|
173 |
return "[gravityform id='$id' title='$title' description='$description' ajax='$ajax']";
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
return array_filter( array(
|
178 |
'id' => rgget( 'id' ),
|
179 |
'title' => rgget( 'title' ),
|
180 |
'description' => rgget( 'description' ),
|
181 |
'ajax' => rgget( 'ajax' )
|
182 |
) );
|
183 |
-
|
184 |
-
|
185 |
-
public function is_live_preview() {
|
186 |
-
return is_post_type_archive( $this->post_type );
|
187 |
-
}
|
188 |
-
|
189 |
}
|
190 |
-
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_LivePreview extends GFPersian_Core {
|
6 |
+
|
7 |
+
private $post_type = 'gf_live_preview';
|
8 |
+
private $_args;
|
9 |
+
|
10 |
+
public function __construct( $args = array() ) {
|
11 |
+
|
12 |
+
if ( $this->option( 'live_preview', '1' ) != '1' ) {
|
13 |
+
return;
|
14 |
+
}
|
15 |
+
|
16 |
+
if ( ! property_exists( 'GFCommon', 'version' ) || version_compare( GFCommon::$version, '1.8', '<' ) ) {
|
17 |
+
return;
|
18 |
+
}
|
19 |
+
|
20 |
+
$this->_args = wp_parse_args( $args, array(
|
21 |
+
'id' => 0,
|
22 |
+
'title' => true,
|
23 |
+
'description' => true,
|
24 |
+
'ajax' => true
|
25 |
+
) );
|
26 |
+
|
27 |
+
add_action( 'init', array( $this, 'register_preview_post_type' ) );
|
28 |
+
add_action( 'wp', array( $this, 'maybe_load_preview_functionality' ) );
|
29 |
+
add_action( 'admin_footer', array( $this, 'display_preview_link' ) );
|
30 |
add_filter( 'gform_form_actions', array( $this, 'gform_form_actions' ), 10, 2 );
|
31 |
+
}
|
32 |
+
|
33 |
+
public function register_preview_post_type() {
|
34 |
+
|
35 |
$args = array(
|
36 |
+
'label' => 'پیشنمایش زنده',
|
37 |
+
'description' => 'پیشنمایش فرم در فرانت اند به صورت یک پست تایپ مجازی',
|
38 |
+
'public' => false,
|
39 |
'publicly_queryable' => true,
|
40 |
+
'has_archive' => true,
|
41 |
+
'can_export' => false,
|
42 |
+
'supports' => false
|
43 |
);
|
44 |
+
|
45 |
register_post_type( $this->post_type, $args );
|
46 |
+
|
47 |
// create preview post
|
48 |
$preview_post = get_posts( array( 'post_type' => $this->post_type ) );
|
49 |
+
if ( empty( $preview_post ) ) {
|
50 |
+
wp_insert_post( array(
|
51 |
+
'post_type' => $this->post_type,
|
52 |
+
'post_title' => 'پیشنمایش زنده',
|
53 |
'post_status' => 'publish'
|
54 |
) );
|
55 |
}
|
56 |
+
|
57 |
+
}
|
58 |
+
|
59 |
+
public function maybe_load_preview_functionality() {
|
60 |
+
|
61 |
+
global $wp_query;
|
62 |
+
|
63 |
+
if ( ! is_post_type_archive( $this->post_type ) ) {
|
64 |
return;
|
65 |
+
}
|
66 |
+
|
67 |
+
add_filter( 'template_include', array( $this, 'load_preview_template' ) );
|
68 |
+
add_filter( 'the_content', array( $this, 'modify_preview_post_content' ) );
|
69 |
+
|
70 |
// quick hack for GF to ensure scripts/styles are loaded correctly
|
71 |
+
foreach ( $wp_query->posts as &$post ) {
|
72 |
$post->post_content = $this->get_shortcode();
|
73 |
}
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
public function gform_form_actions( $form_actions, $form_id ) {
|
78 |
+
|
79 |
+
if ( ! empty( $_GET['trash'] ) && $_GET['trash'] == 1 ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
return $form_actions;
|
81 |
+
}
|
82 |
+
|
83 |
+
$capabilities = array(
|
84 |
+
'gravityforms_view_entries',
|
85 |
+
'gravityforms_edit_entries',
|
86 |
+
'gravityforms_delete_entries'
|
87 |
+
);
|
88 |
+
|
89 |
+
$ajax_true_url = get_bloginfo( "wpurl" ) . '/?post_type=' . $this->post_type . '&id=' . $form_id;
|
90 |
+
$ajax_false_url = get_bloginfo( "wpurl" ) . '/?post_type=' . $this->post_type . '&ajax=false&id=' . $form_id;
|
91 |
+
|
92 |
$sub_menu_items = array();
|
93 |
+
|
94 |
$sub_menu_items[] = array(
|
95 |
'url' => $ajax_true_url,
|
96 |
+
'label' => 'حالت آیجکس فعال',
|
97 |
'capabilities' => $capabilities
|
98 |
);
|
99 |
+
|
100 |
$sub_menu_items[] = array(
|
101 |
'url' => $ajax_false_url,
|
102 |
+
'label' => 'حالت آیجکس غیرفعال',
|
103 |
'capabilities' => $capabilities
|
104 |
);
|
105 |
+
|
106 |
$form_actions['live_preview'] = array(
|
107 |
+
'label' => 'پیشنمایش زنده',
|
108 |
'icon' => '<i class="fa fa-cogs fa-lg"></i>',
|
109 |
+
'title' => 'پیشنمایش زنده',
|
110 |
'url' => '',
|
111 |
'menu_class' => 'gf_form_toolbar_settings',
|
112 |
'link_class' => 'gf_toolbar_active',
|
114 |
'capabilities' => $capabilities,
|
115 |
'priority' => 650,
|
116 |
);
|
117 |
+
|
118 |
return $form_actions;
|
119 |
}
|
120 |
+
|
121 |
+
public function display_preview_link() {
|
122 |
+
|
123 |
+
if ( ! in_array( rgget( 'page' ), array(
|
124 |
+
'gf_edit_forms',
|
125 |
+
'gf_entries'
|
126 |
+
) ) || ! rgget( 'id' ) || apply_filters( 'gf_live_preview_page', false ) ) {
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
|
130 |
+
$form_id = apply_filters( 'gf_live_preview_id', rgget( 'id' ) );
|
131 |
+
$ajax_true_url = get_bloginfo( "wpurl" ) . '/?post_type=' . $this->post_type . '&id=' . $form_id;
|
132 |
+
$ajax_false_url = get_bloginfo( "wpurl" ) . '/?post_type=' . $this->post_type . '&ajax=false&id=' . $form_id;
|
133 |
+
?>
|
134 |
+
|
135 |
<script type="text/javascript">
|
136 |
+
(function ($) {
|
137 |
+
$('<li class="gf_form_toolbar_preview">' +
|
138 |
+
'<a style="position:relative" id="gf-live-preview" target="_blank" href="<?php echo $ajax_true_url; ?>" class="" >' +
|
139 |
+
'<i class="fa fa-eye" style="position: absolute; text-shadow: 0px 0px 5px rgb(255, 255, 255); z-index: 99; line-height: 7px; left: 0px font-size: 9px; background-color: rgb(243, 243, 243);"></i>' +
|
140 |
+
'<i class="fa fa-file-o" style="margin-left: 5px; line-height: 12px; font-size: 18px; position: relative;"></i>' +
|
141 |
+
'پیش نمایش زنده' +
|
142 |
+
'</a>' +
|
143 |
+
'<div class="gf_submenu"><ul>' +
|
144 |
+
'<li class=""><a target="_blank" href="<?php echo $ajax_true_url; ?>">حالت آیجکس فعال</a></li>' +
|
145 |
+
'<li class=""><a target="_blank" href="<?php echo $ajax_false_url; ?>">حالت آیجکس غیرفعال</a></li>' +
|
146 |
+
'</ul></div>' +
|
147 |
+
'</li>')
|
148 |
+
.insertAfter('li.gf_form_toolbar_preview');
|
149 |
+
})(jQuery);
|
150 |
</script>
|
151 |
+
<?php
|
152 |
+
}
|
153 |
+
|
|
|
|
|
|
|
|
|
154 |
public function load_preview_template( $template ) {
|
155 |
+
return get_page_template();
|
156 |
}
|
157 |
+
|
158 |
+
public function modify_preview_post_content( $content ) {
|
159 |
return $this->get_shortcode();
|
160 |
+
}
|
161 |
+
|
162 |
+
public function get_shortcode( $args = array() ) {
|
163 |
+
|
164 |
+
if ( ! is_user_logged_in() ) {
|
165 |
+
return '<p>برای دسترسی به این قسمت باید لاگین شوید.</p>' . wp_login_form( array( 'echo' => false ) );
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( ! GFCommon::current_user_can_any( 'gravityforms_preview_forms' ) ) {
|
169 |
+
return 'شما مجوز دسترسی به این بخش را ندارید.';
|
170 |
+
}
|
171 |
+
|
172 |
+
if ( empty( $args ) ) {
|
173 |
+
$args = $this->get_shortcode_parameters_from_query_string();
|
174 |
+
}
|
175 |
+
|
176 |
+
extract( wp_parse_args( $args, $this->_args ) );
|
177 |
+
|
178 |
+
$title = ! empty( $title ) && $title === true ? 'true' : 'false';
|
179 |
+
$description = ! empty( $description ) && $description === true ? 'true' : 'false';
|
180 |
+
$ajax = ! empty( $ajax ) && $ajax === true ? 'true' : 'false';
|
181 |
+
$id = ! empty( $id ) && $id > 0 ? $id : 0;
|
182 |
+
|
183 |
return "[gravityform id='$id' title='$title' description='$description' ajax='$ajax']";
|
184 |
+
}
|
185 |
+
|
186 |
+
public function get_shortcode_parameters_from_query_string() {
|
187 |
return array_filter( array(
|
188 |
'id' => rgget( 'id' ),
|
189 |
'title' => rgget( 'title' ),
|
190 |
'description' => rgget( 'description' ),
|
191 |
'ajax' => rgget( 'ajax' )
|
192 |
) );
|
193 |
+
}
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
+
|
196 |
+
new GFPersian_LivePreview();
|
includes/class-melli-code.php
DELETED
@@ -1,434 +0,0 @@
|
|
1 |
-
<?php if ( ! defined('ABSPATH') ) exit;
|
2 |
-
|
3 |
-
class GFParsi_MelliCode {
|
4 |
-
|
5 |
-
private $field = array();
|
6 |
-
|
7 |
-
public function __construct() {
|
8 |
-
|
9 |
-
if( is_admin() ) {
|
10 |
-
add_filter('gform_add_field_buttons' , array( $this, 'button'));
|
11 |
-
add_filter('gform_field_type_title' , array( $this, 'title'));
|
12 |
-
add_filter('gform_editor_js_set_default_values' , array( $this, 'label'));
|
13 |
-
add_action('gform_editor_js' , array( $this, 'settings'));
|
14 |
-
add_action('gform_field_standard_settings' , array( $this, 'standard_settings'), 10, 2);
|
15 |
-
add_filter('gform_tooltips' , array( $this, 'tooltips'));
|
16 |
-
add_filter('gform_admin_pre_render' , array( $this ,'admin_conditional_logic' ) );
|
17 |
-
}
|
18 |
-
|
19 |
-
add_action('gform_field_input' , array( $this, 'input'), 10, 5);
|
20 |
-
add_action('gform_field_css_class' , array( $this, 'classes'), 10, 3);
|
21 |
-
add_action('gform_pre_submission' , array( $this, 'pre_submission' ) );
|
22 |
-
add_filter('gform_field_content' , array( $this, 'city'), 10, 5);
|
23 |
-
add_filter('gform_field_validation' , array( $this, 'validator'), 10, 4);
|
24 |
-
add_action('wp_footer' , array( $this, 'js'));
|
25 |
-
add_action('gform_enqueue_scripts' , array( $this, 'external_js') , 10 , 2 );
|
26 |
-
}
|
27 |
-
|
28 |
-
public function button( $field_groups ) {
|
29 |
-
foreach( $field_groups as &$group ){
|
30 |
-
if( $group["name"] == "advanced_fields" ){
|
31 |
-
$group["fields"][] = array(
|
32 |
-
"class"=>"button",
|
33 |
-
"value" => __('National ID', 'GF_FA'),
|
34 |
-
"onclick" => "StartAddField('mellicart');"
|
35 |
-
);
|
36 |
-
|
37 |
-
}
|
38 |
-
}
|
39 |
-
return $field_groups;
|
40 |
-
}
|
41 |
-
|
42 |
-
public function title($type) {
|
43 |
-
if ($type == 'mellicart') {
|
44 |
-
return __('National ID', 'GF_FA');
|
45 |
-
}
|
46 |
-
}
|
47 |
-
|
48 |
-
public function label(){
|
49 |
-
?>
|
50 |
-
case "mellicart" :
|
51 |
-
field.label = '<?php _e('National ID', 'GF_FA') ?>';
|
52 |
-
break;
|
53 |
-
<?php
|
54 |
-
}
|
55 |
-
|
56 |
-
public function classes($classes, $field, $form){
|
57 |
-
if( $field["type"] == "mellicart" ){
|
58 |
-
$classes .= " gform_melli_code";
|
59 |
-
}
|
60 |
-
return $classes;
|
61 |
-
}
|
62 |
-
|
63 |
-
public function tooltips( $tooltips ) {
|
64 |
-
$tooltips['gform_melli_code_city'] = __('<h6>نمایش لحظه ای شهر از روی کد ملی </h6>نمایش شهر و پیغام زیر فیلد کد ملی بعد از پر شدن فیلد . تذکر : در صورتی که این گزینه را فعال نمایید ،ممکن است فراخوانی شهر های ایران با توجه به زیاد بودن آنها سبب سنگین شدن صفحه گردد.' , 'GF_FA');
|
65 |
-
$tooltips['gform_melli_code_seperate'] = __('<h6>جدا سازی ارقام</h6>در صورتی که این گزینه را فعال نمایید ، پس از پر شدن فیلد کد ملی ، <strong>در صورتی که کد ملی وارد شده صحیح تشخصی داده شود</strong> ؛ کد ملی به صورت زیر در خواهد آمد و در غیر این صورت علی صحیح نبودن کد ملی زیر فیلد نمایش داده خواهد شد :<br>xxx-xxxxxx-x' , 'GF_FA');
|
66 |
-
$tooltips['gform_melli_code_abnormal'] = __('با توجه به اینکه کد ملی فقط باید به صورت عدد باشد ، در صورتی که کاراکتری غیر از عدد وارد شده باشد پیغام خطا نمایش داده خواهد شد .<br/>پیغام پیشفرض : کد ملی فقط باید به صورت عدد وارد شود .' , 'GF_FA');
|
67 |
-
$tooltips['gform_melli_code_len'] = __('با توجه به اینکه کد ملی می بایست 10 رقمی باشد اگر تعداد رقم وارد شده ، اشتباه باشد پیغام خطا نمایش داده خواهد شد .<br>پیغام پیشفرض : کد ملی می بایست 10 رقمی باشد . تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند .' , 'GF_FA');
|
68 |
-
$tooltips['gform_melli_code_dup'] = __('در صورتی که از تب وِیژگی تیک گزینه بدون تکرار را زده باشید ؛ بعد از پر شدن فرم و زدن دکمه ارسال پیغامی مبتنی بر تکراری بودن کد ملی نمایش داده خواهد شد . <br/>پیغام پیشفرض : این کد ملی توسط فرد دیگری ثبت شده است .' , 'GF_FA');
|
69 |
-
$tooltips['gform_melli_code_noStandard'] = __('در صورتی که کد ملی وارد شده مطابق با الگوریتم کشور نباشد پیغام خطا نمایش داده خواهد شد .<br/>پیغام پیشفرض : کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .' , 'GF_FA');
|
70 |
-
return $tooltips;
|
71 |
-
}
|
72 |
-
|
73 |
-
public function input($input, $field, $value, $lead_id, $form_id ){
|
74 |
-
|
75 |
-
if ( $field["type"] == "mellicart" ) {
|
76 |
-
|
77 |
-
$is_admin = is_admin();
|
78 |
-
$is_frontend = ! $is_admin;
|
79 |
-
$is_form_editor = ( $is_admin && GFForms::get( 'view' ) != 'entry' );
|
80 |
-
$is_entry_page = ( $is_admin && GFForms::get( 'view' ) == 'entry' );
|
81 |
-
|
82 |
-
if ( ! $is_admin && ( RGFormsModel::get_input_type( $field ) == 'adminonly_hidden') ) {
|
83 |
-
return '';
|
84 |
-
}
|
85 |
-
|
86 |
-
$field_id = $field["id"];
|
87 |
-
$form_id = $is_admin && empty($form_id) ? rgget("id") : $form_id;
|
88 |
-
|
89 |
-
$disabled_text = ( $is_admin && GFForms::get( 'view' ) != 'entry' ) ? "disabled='disabled'" : '';
|
90 |
-
|
91 |
-
$size = rgar($field, "size");
|
92 |
-
$class_suffix = GFForms::get( 'view' ) == 'entry' ? '_admin' : '';
|
93 |
-
$class = $size . $class_suffix;
|
94 |
-
|
95 |
-
$html5_attributes = '';
|
96 |
-
|
97 |
-
$tabindex = GFCommon::get_tabindex();
|
98 |
-
|
99 |
-
|
100 |
-
//$this->get_conditional_logic_event( 'keyup' ) //text or radio
|
101 |
-
//$this->get_conditional_logic_event( 'change' ) //select
|
102 |
-
//$this->get_conditional_logic_event( 'click' ) // checkbox or radio
|
103 |
-
//note : radio has keyup and click
|
104 |
-
$logic_event = ! $is_form_editor && ! $is_entry_page ? $field->get_conditional_logic_event( 'keyup' ) : '';
|
105 |
-
|
106 |
-
$input = '<div class="ginput_container ginput_container_text ginput_container_melli_code">';
|
107 |
-
$input .= '<input onblur="melli_code_'.$field_id.'(this);" name="input_'.$field_id.'" id="input_'.$form_id.'_'.$field_id.'" type="text" value="'.esc_attr($value).'" class="melli_code '.esc_attr($size).'" '.$tabindex.' '.$logic_event.' '.$html5_attributes.' '.$disabled_text.'/>';
|
108 |
-
$input .= '</div>';
|
109 |
-
|
110 |
-
if ( $is_frontend ) {
|
111 |
-
$input .= '<span class="city melli_code" id="city_'.$field_id.'"></span>';
|
112 |
-
}
|
113 |
-
|
114 |
-
}
|
115 |
-
|
116 |
-
return $input;
|
117 |
-
}
|
118 |
-
|
119 |
-
public function settings(){ ?>
|
120 |
-
<script type='text/javascript'>
|
121 |
-
fieldSettings["mellicart"] = ".placeholder_setting, .input_mask_setting, .label_placement_setting, .prepopulate_field_setting, .conditional_logic_field_setting, .label_setting, .admin_label_setting, .size_setting, .rules_setting, .visibility_setting, .duplicate_setting, .default_value_setting, .description_setting, .css_class_setting, .mellicart_setting";
|
122 |
-
jQuery(document).bind("gform_load_field_settings", function(event, field, form){
|
123 |
-
jQuery("#field_mellicart").attr("checked", field["field_mellicart"] == true);
|
124 |
-
jQuery("#field_mellicart_sp").attr("checked", field["field_mellicart_sp"] == true);
|
125 |
-
jQuery("#field_mellicart_sp1").val(field["field_mellicart_sp1"]);
|
126 |
-
jQuery("#field_mellicart_sp2").val(field["field_mellicart_sp2"]);
|
127 |
-
jQuery("#field_mellicart_sp3").val(field["field_mellicart_sp3"]);
|
128 |
-
jQuery("#field_mellicart_sp4").val(field["field_mellicart_sp4"]);
|
129 |
-
});
|
130 |
-
</script>
|
131 |
-
<?php
|
132 |
-
}
|
133 |
-
|
134 |
-
|
135 |
-
public function admin_conditional_logic( $form ) {
|
136 |
-
|
137 |
-
if ( GFCommon::is_entry_detail() ) {
|
138 |
-
return $form;
|
139 |
-
}
|
140 |
-
|
141 |
-
echo "<script type='text/javascript'>" .
|
142 |
-
" gform.addFilter('gform_is_conditional_logic_field', function (isConditionalLogicField, field) {" .
|
143 |
-
" return field.type == 'mellicart' ? true : isConditionalLogicField;" .
|
144 |
-
' });' .
|
145 |
-
" gform.addFilter('gform_conditional_logic_operators', function (operators, objectType, fieldId) {" .
|
146 |
-
' var targetField = GetFieldById(fieldId);' .
|
147 |
-
" if (targetField && targetField['type'] == 'mellicart') {" .
|
148 |
-
" operators = {'is':'is','isnot':'isNot', '>':'greaterThan', '<':'lessThan', 'contains':'contains', 'starts_with':'startsWith', 'ends_with':'endsWith'};" .
|
149 |
-
' }' .
|
150 |
-
' return operators;' .
|
151 |
-
' });' .
|
152 |
-
'</script>';
|
153 |
-
|
154 |
-
return $form;
|
155 |
-
}
|
156 |
-
|
157 |
-
public function standard_settings( $position, $form_id ){
|
158 |
-
|
159 |
-
if( $position == 50 ){ ?>
|
160 |
-
|
161 |
-
<li class="mellicart_setting field_setting">
|
162 |
-
|
163 |
-
<input type="checkbox" id="field_mellicart" onclick="SetFieldProperty('field_mellicart', this.checked);" />
|
164 |
-
<label for="field_mellicart" class="inline">
|
165 |
-
<?php _e("نمایش شهر بر اساس کد ملی", "GF_FA"); ?>
|
166 |
-
<?php gform_tooltip("gform_melli_code_city"); ?>
|
167 |
-
</label>
|
168 |
-
|
169 |
-
|
170 |
-
<br/>
|
171 |
-
<input type="checkbox" id="field_mellicart_sp" onclick="SetFieldProperty('field_mellicart_sp', this.checked);" />
|
172 |
-
<label for="field_mellicart_sp" class="inline">
|
173 |
-
<?php _e("جدا سازی خودکار ارقام توسط خط فاصله", "GF_FA"); ?>
|
174 |
-
<?php gform_tooltip("gform_melli_code_seperate"); ?>
|
175 |
-
</label>
|
176 |
-
<br/>
|
177 |
-
|
178 |
-
|
179 |
-
<br/>
|
180 |
-
<label for="field_mellicart_sp1" >
|
181 |
-
<?php _e("پیغام زمانی که مقدار وارد شده شامل کاراکتر غیر عددی باشد", "GF_FA"); ?>
|
182 |
-
<?php gform_tooltip("gform_melli_code_abnormal"); ?>
|
183 |
-
</label>
|
184 |
-
<input type="text" class="fieldwidth-3" id="field_mellicart_sp1" size="35" onkeyup="SetFieldProperty('field_mellicart_sp1', this.value);" />
|
185 |
-
<br/>
|
186 |
-
|
187 |
-
|
188 |
-
<br/>
|
189 |
-
<label for="field_mellicart_sp2" >
|
190 |
-
<?php _e("پیغام زمانیکه تعداد ارقام وارد شده استاندارد نباشد", "GF_FA"); ?>
|
191 |
-
<?php gform_tooltip("gform_melli_code_len"); ?>
|
192 |
-
</label>
|
193 |
-
<input type="text" class="fieldwidth-3" id="field_mellicart_sp2" size="35" onkeyup="SetFieldProperty('field_mellicart_sp2', this.value);" />
|
194 |
-
<br/>
|
195 |
-
|
196 |
-
|
197 |
-
<br/>
|
198 |
-
<label for="field_mellicart_sp3" >
|
199 |
-
<?php _e("پیغام زمانیکه کد ملی وارد شده قبلا ثبت شده باشد", "GF_FA"); ?>
|
200 |
-
<?php gform_tooltip("gform_melli_code_dup"); ?>
|
201 |
-
</label>
|
202 |
-
<input type="text" class="fieldwidth-3" id="field_mellicart_sp3" size="35" onkeyup="SetFieldProperty('field_mellicart_sp3', this.value);" />
|
203 |
-
<br/>
|
204 |
-
|
205 |
-
|
206 |
-
<br/>
|
207 |
-
<label for="field_mellicart_sp4" >
|
208 |
-
<?php _e("پیغام زمانیکه کد ملی وارد شده مطابق با الگوی ملی نباشد", "GF_FA"); ?>
|
209 |
-
<?php gform_tooltip("gform_melli_code_noStandard"); ?>
|
210 |
-
</label>
|
211 |
-
<input type="text" class="fieldwidth-3" id="field_mellicart_sp4" size="35" onkeyup="SetFieldProperty('field_mellicart_sp4', this.value);" />
|
212 |
-
<br/>
|
213 |
-
|
214 |
-
|
215 |
-
</li>
|
216 |
-
<?php
|
217 |
-
}
|
218 |
-
}
|
219 |
-
|
220 |
-
|
221 |
-
public function pre_submission( $form ) {
|
222 |
-
|
223 |
-
$mellicart_fields = GFCommon::get_fields_by_type( $form, array( 'mellicart' ) );
|
224 |
-
|
225 |
-
foreach ( (array) $mellicart_fields as $field ) {
|
226 |
-
|
227 |
-
$input_name = "input_{$field['id']}";
|
228 |
-
$input_value = ! rgempty( $input_name ) ? rgpost( $input_name ) : '';
|
229 |
-
|
230 |
-
if ( !empty( $input_value ) ) {
|
231 |
-
|
232 |
-
if ( strlen($input_value) == 8 ) {
|
233 |
-
$_POST["input_{$field['id']}"] = '00'.$input_value;
|
234 |
-
}
|
235 |
-
elseif ( strlen($input_value) == 9 ) {
|
236 |
-
$_POST["input_{$field['id']}"] = '0'.$input_value;
|
237 |
-
}
|
238 |
-
else {
|
239 |
-
$_POST["input_{$field['id']}"] = $input_value;
|
240 |
-
}
|
241 |
-
}
|
242 |
-
}
|
243 |
-
}
|
244 |
-
|
245 |
-
public function city( $content, $field, $value, $lead_id, $form_id ){
|
246 |
-
|
247 |
-
if ( $field['type'] == 'mellicart' ) {
|
248 |
-
if ( ! is_admin() ) {
|
249 |
-
$this->field[] = $field;
|
250 |
-
}
|
251 |
-
}
|
252 |
-
return $content;
|
253 |
-
}
|
254 |
-
|
255 |
-
public function external_js( $form , $ajax ) {
|
256 |
-
|
257 |
-
$melli_code = GFCommon::get_fields_by_type( $form, array( 'mellicart' ) );
|
258 |
-
|
259 |
-
foreach ( (array) $melli_code as $field ) {
|
260 |
-
|
261 |
-
$is_seperate = gfa_get('field_mellicart_sp', $field);
|
262 |
-
$is_seperate = !empty($is_seperate) ? $is_seperate : false;
|
263 |
-
|
264 |
-
$show_city = gfa_get('field_mellicart', $field);
|
265 |
-
$show_city = !empty($show_city) ? $show_city : false;
|
266 |
-
|
267 |
-
if ( $show_city || $is_seperate) {
|
268 |
-
wp_register_script( 'gform_mellicode', GF_PARSI_URL . 'assets/js/melli-code.min.js', array() , GF_PARSI_VERSION, false );
|
269 |
-
wp_enqueue_script( 'gform_mellicode' );
|
270 |
-
break;
|
271 |
-
}
|
272 |
-
}
|
273 |
-
}
|
274 |
-
|
275 |
-
public function js() {
|
276 |
-
|
277 |
-
$fields = $this->field;
|
278 |
-
|
279 |
-
if ( empty($fields) )
|
280 |
-
return;
|
281 |
-
|
282 |
-
foreach( (array) $fields as $field ) {
|
283 |
-
|
284 |
-
$is_seperate = gfa_get('field_mellicart_sp', $field);
|
285 |
-
$is_seperate = !empty($is_seperate) && $is_seperate ? 1 : 0;
|
286 |
-
|
287 |
-
$show_city = gfa_get('field_mellicart', $field);
|
288 |
-
$show_city = !empty($show_city) && $show_city ? 1 : 0;
|
289 |
-
|
290 |
-
if ( !$show_city && !$is_seperate )
|
291 |
-
return;
|
292 |
-
|
293 |
-
$message1 = gfa_get('field_mellicart_sp1', $field);
|
294 |
-
$message1 = !empty($message1) ? $message1 : __('کد ملی فقط باید به صورت عدد وارد شود .', 'GF_FA');
|
295 |
-
|
296 |
-
$message2 = gfa_get('field_mellicart_sp2', $field);
|
297 |
-
$message2 = !empty($message2) ? $message2 : __('کد ملی می بایست 10 رقمی باشد .', 'GF_FA');
|
298 |
-
|
299 |
-
$message3 = gfa_get('field_mellicart_sp4', $field);
|
300 |
-
$message3 = !empty($message3) ? $message3 : __('کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .', 'GF_FA');
|
301 |
-
?>
|
302 |
-
|
303 |
-
<script type="text/javascript">
|
304 |
-
function melli_code_<?php echo $field['id']; ?> (melli_code) {
|
305 |
-
var field_id = "<?php echo $field['id'] ?>";
|
306 |
-
var message1 = "<?php echo $message1 ?>";
|
307 |
-
var message2 = "<?php echo $message2 ?>";
|
308 |
-
var message3 = "<?php echo $message3 ?>";
|
309 |
-
var show_city = <?php echo $show_city ?>;
|
310 |
-
var is_seperate = <?php echo $is_seperate ?>;
|
311 |
-
melli_code_function( melli_code, field_id , message1 , message2 , message3 , is_seperate , show_city);
|
312 |
-
}
|
313 |
-
</script>
|
314 |
-
|
315 |
-
<?php
|
316 |
-
}
|
317 |
-
}
|
318 |
-
|
319 |
-
public function is_valid( $melli_code = '' ){
|
320 |
-
|
321 |
-
if ( !empty($melli_code) ) {
|
322 |
-
|
323 |
-
$_melli_code = $melli_code;
|
324 |
-
|
325 |
-
if( strlen($melli_code) == 8 )
|
326 |
-
$_melli_code = '00' . $melli_code;
|
327 |
-
|
328 |
-
if( strlen($melli_code) == 9 )
|
329 |
-
$_melli_code = '0' . $melli_code;
|
330 |
-
|
331 |
-
$pre_check = array(
|
332 |
-
'0000000000',
|
333 |
-
'1111111111',
|
334 |
-
'2222222222',
|
335 |
-
'3333333333',
|
336 |
-
'4444444444',
|
337 |
-
'5555555555',
|
338 |
-
'6666666666',
|
339 |
-
'7777777777',
|
340 |
-
'8888888888',
|
341 |
-
'9999999999',
|
342 |
-
);
|
343 |
-
|
344 |
-
if( in_array( $_melli_code , $pre_check ) )
|
345 |
-
return 2;
|
346 |
-
|
347 |
-
if( ! is_numeric($melli_code) )
|
348 |
-
return 4;
|
349 |
-
|
350 |
-
$melli_code = (string) preg_replace('/[^0-9]/','',$melli_code);
|
351 |
-
|
352 |
-
if( strlen($melli_code) > 10 || strlen($melli_code) <8 )
|
353 |
-
return 3;
|
354 |
-
|
355 |
-
$melli_code = $_melli_code;
|
356 |
-
|
357 |
-
$list_code = str_split($melli_code);
|
358 |
-
$last = (int) $list_code[9];
|
359 |
-
unset($list_code[9]);
|
360 |
-
|
361 |
-
$i = 10;
|
362 |
-
$sum = 0;
|
363 |
-
foreach( $list_code as $key => $val ) {
|
364 |
-
$sum += intval($val) * $i;
|
365 |
-
$i--;
|
366 |
-
}
|
367 |
-
|
368 |
-
$mod =(int) $sum % 11;
|
369 |
-
|
370 |
-
if($mod >= 2)
|
371 |
-
$mod = 11 - $mod;
|
372 |
-
if ($mod != $last)
|
373 |
-
return 2;
|
374 |
-
else
|
375 |
-
return 1;
|
376 |
-
}
|
377 |
-
|
378 |
-
return false;
|
379 |
-
}
|
380 |
-
|
381 |
-
|
382 |
-
public function validator($result, $value, $form, $field){
|
383 |
-
|
384 |
-
if ( $field["type"] == 'mellicart' ) {
|
385 |
-
|
386 |
-
$melli_code = !empty($value) ? str_replace( '-', '', $value) : '';
|
387 |
-
|
388 |
-
$is_valid = $this->is_valid($melli_code);
|
389 |
-
|
390 |
-
if ( $is_valid == 4 ) {
|
391 |
-
$message = gfa_get('field_mellicart_sp1', $field);
|
392 |
-
$result['message'] = !empty($message) ? $message : __('کد ملی فقط باید به صورت عدد وارد شود .' , 'GF_FA');
|
393 |
-
$result['is_valid'] = false;
|
394 |
-
return $result;
|
395 |
-
}
|
396 |
-
|
397 |
-
if ( $is_valid == 3 ){
|
398 |
-
$message = gfa_get('field_mellicart_sp2', $field);
|
399 |
-
$result['message'] = !empty($message) ? $message : __('کد ملی می بایست 10 رقمی باشد . تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند .' , 'GF_FA');
|
400 |
-
$result['is_valid'] = false;
|
401 |
-
return $result;
|
402 |
-
}
|
403 |
-
|
404 |
-
if ( $is_valid == 2 ) {
|
405 |
-
$message = gfa_get('field_mellicart_sp4', $field);
|
406 |
-
$result['message'] = !empty($message) ? $message : __('کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد .' , 'GF_FA');
|
407 |
-
$result['is_valid'] = false;
|
408 |
-
return $result;
|
409 |
-
}
|
410 |
-
|
411 |
-
if ( $field['noDuplicates'] ) {
|
412 |
-
|
413 |
-
if( strlen($melli_code) == 8 )
|
414 |
-
$melli_code = '00' . $melli_code;
|
415 |
-
|
416 |
-
if( strlen($melli_code) == 9 )
|
417 |
-
$melli_code = '0' . $melli_code;
|
418 |
-
|
419 |
-
if ( RGFormsModel::is_duplicate($form['id'], $field, $melli_code) ) {
|
420 |
-
$message = gfa_get('field_mellicart_sp3', $field);
|
421 |
-
$result['message'] = !empty($message) ? $message : __('این کد ملی توسط فرد دیگری ثبت شده است .' , 'GF_FA');
|
422 |
-
$result['is_valid'] = false;
|
423 |
-
return $result;
|
424 |
-
}
|
425 |
-
}
|
426 |
-
}
|
427 |
-
|
428 |
-
return $result;
|
429 |
-
}
|
430 |
-
|
431 |
-
|
432 |
-
}
|
433 |
-
|
434 |
-
new GFParsi_MelliCode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-merge-tag.php
ADDED
@@ -0,0 +1,672 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Merge_Tags extends GFPersian_Core {
|
6 |
+
|
7 |
+
public static $_entry = null;
|
8 |
+
private $entry_time = 0;
|
9 |
+
|
10 |
+
public function __construct() {
|
11 |
+
|
12 |
+
if ( $this->option( 'add_merge_tags', '1' ) == '1' ) {
|
13 |
+
|
14 |
+
add_filter( 'gform_admin_pre_render', array( $this, 'merge_tags_keys' ) );
|
15 |
+
add_filter( 'gform_replace_merge_tags', array( $this, 'merge_tags_values' ), 999, 7 );
|
16 |
+
/*------------------------------------------------------------*/
|
17 |
+
//todo:enable for next updates if was needed
|
18 |
+
if ( apply_filters( 'enable_subtotal_merge_tag', false ) ) {
|
19 |
+
add_filter( 'gform_pre_render', array( $this, 'maybe_replace_subtotal_merge_tag' ) );
|
20 |
+
add_filter( 'gform_pre_validation', array( $this, 'maybe_replace_subtotal_merge_tag' ), 10, 1 );
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
if ( $this->option( 'post_content_merge_tags', '1' ) == '1' ) {
|
25 |
+
|
26 |
+
$entry_time = $this->option( 'entry_time', '0' );
|
27 |
+
if ( intval( $entry_time ) > 0 ) {
|
28 |
+
$this->entry_time = intval( $entry_time ) * 60;
|
29 |
+
}
|
30 |
+
|
31 |
+
add_filter( 'the_content', array( $this, 'merge_tags_values_post_content' ), 1 );
|
32 |
+
add_filter( 'gform_confirmation', array( $this, 'confirmation_append_entry' ), 20, 3 );
|
33 |
+
}
|
34 |
+
|
35 |
+
if ( $this->option( 'pre_submission_merge_tags', '1' ) == '1' ) {
|
36 |
+
add_filter( 'gform_pre_render', array( $this, 'merge_tags_pre_submission' ) );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
/*-------------------------------------------------------------*/
|
41 |
+
/*--------Start of Persian Gravity Merge Tags------------------*/
|
42 |
+
/*-------------------------------------------------------------*/
|
43 |
+
public static function get_merge_tags( $form ) {
|
44 |
+
$merge_tags = array(
|
45 |
+
'{rtl_start}' => 'ابتدای راستچین سازی',
|
46 |
+
'{rtl_end}' => 'انتهای راستچین سازی',
|
47 |
+
'{transaction_id}' => __( 'Transaction Id', 'gravityforms' ),
|
48 |
+
'{transaction_id_table}' => sprintf( 'جدول %s', __( 'Transaction Id', 'gravityforms' ) ),
|
49 |
+
'{payment_gateway}' => 'عنوان درگاه پرداخت',
|
50 |
+
'{payment_gateway_table}' => 'جدول درگاه پرداخت',
|
51 |
+
'{payment_status}' => 'عنوان وضعیت پرداخت',
|
52 |
+
'{payment_status_table}' => 'جدول وضعیت پرداخت',
|
53 |
+
'{payment_table}' => sprintf( 'جدول پرداخت (وضعیت - نام درگاه - %s)', __( 'Transaction Id', 'gravityforms' ) ),
|
54 |
+
);
|
55 |
+
|
56 |
+
if ( GFCommon::has_post_field( rgar( $form, 'fields' ) ) ) {
|
57 |
+
$merge_tags['{post_permalink}'] = 'لینک پست';
|
58 |
+
}
|
59 |
+
|
60 |
+
return $merge_tags;
|
61 |
+
}
|
62 |
+
|
63 |
+
public function merge_tags_keys( $form ) { ?>
|
64 |
+
|
65 |
+
<script type="text/javascript">
|
66 |
+
gform.addFilter('gform_merge_tags', function (mergeTags, elementId, hideAllFields, excludeFieldTypes, isPrepop, option) {
|
67 |
+
mergeTags['gf_persian'] = {
|
68 |
+
label: 'گرویتی فرم پارسی',
|
69 |
+
tags: []
|
70 |
+
};
|
71 |
+
<?php foreach ( self::get_merge_tags( $form ) as $key => $val ) { ?>
|
72 |
+
mergeTags['gf_persian'].tags.push({tag: '<?php echo $key ?>', label: '<?php echo $val ?>'});
|
73 |
+
<?php } ?>
|
74 |
+
return mergeTags;
|
75 |
+
});
|
76 |
+
|
77 |
+
<?php
|
78 |
+
/*todo:enable for next updates if was needed*/
|
79 |
+
if ( apply_filters( 'enable_subtotal_merge_tag', false ) ) :?>
|
80 |
+
jQuery(document).ready(function ($) {
|
81 |
+
$('#field_calculation_formula_variable_select').find('optgroup').eq(0).append('<option value="{subtotal}">مجموع قیمت ها</option>');
|
82 |
+
});
|
83 |
+
<?php endif; ?>
|
84 |
+
</script>
|
85 |
+
<?php
|
86 |
+
return $form;
|
87 |
+
}
|
88 |
+
|
89 |
+
public function merge_tags_values( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) {
|
90 |
+
|
91 |
+
//supprots deprecated merge tags
|
92 |
+
$deprecated_tags = array(
|
93 |
+
'{payment_pack}' => '{payment_table}',
|
94 |
+
'{payment_status_css}' => '{payment_status_table}',
|
95 |
+
'{transaction_id_css}' => '{transaction_id_table}',
|
96 |
+
'{payment_gateway_css}' => '{payment_gateway_table}',
|
97 |
+
);
|
98 |
+
|
99 |
+
$text = str_ireplace( array_keys( $deprecated_tags ), array_values( $deprecated_tags ), $text );
|
100 |
+
|
101 |
+
$entry = GFAPI::get_entry( rgar( $entry, 'id' ) );
|
102 |
+
$transaction_id = rgar( $entry, 'transaction_id' );
|
103 |
+
$payment_status = GFPersian_Payments::_payment_status( $entry );
|
104 |
+
$payment_gateway = gform_get_meta( rgar( $entry, 'id' ), 'payment_gateway' );
|
105 |
+
|
106 |
+
$merge_tags = array(
|
107 |
+
'{transaction_id}' => $transaction_id,
|
108 |
+
'{payment_gateway}' => $payment_gateway,
|
109 |
+
'{payment_status}' => strip_tags( $payment_status ),
|
110 |
+
);
|
111 |
+
|
112 |
+
$tabled_tags = array(
|
113 |
+
'{payment_status_table}' => array( 'وضعیت پرداخت', $payment_status ),
|
114 |
+
'{payment_gateway_table}' => array( 'درگاه پرداخت', $payment_gateway ),
|
115 |
+
'{transaction_id_table}' => array( __( 'Transaction Id', 'gravityforms' ), $transaction_id ),
|
116 |
+
);
|
117 |
+
|
118 |
+
foreach ( $tabled_tags as $tag => $value ) {
|
119 |
+
|
120 |
+
if ( empty( $value[1] ) ) {
|
121 |
+
$merge_tags[ $tag ] = '';
|
122 |
+
continue;
|
123 |
+
}
|
124 |
+
ob_start(); ?>
|
125 |
+
<tr bgcolor="<?php echo esc_attr( apply_filters( 'gform_email_background_color_label', '#EAF2FA', $tag, $entry ) ); ?>">
|
126 |
+
<td colspan="2" style="padding:5px !important">
|
127 |
+
<font style="font-family: sans-serif; font-size:12px;"><strong><?php echo $value[0]; ?></strong></font>
|
128 |
+
</td>
|
129 |
+
</tr>
|
130 |
+
<tr bgcolor="#FFFFFF">
|
131 |
+
<td width="20"> </td>
|
132 |
+
<td style="padding:5px !important">
|
133 |
+
<font style="font-family:sans-serif;font-size:12px"><?php echo $value[1]; ?></font>
|
134 |
+
</td>
|
135 |
+
</tr>
|
136 |
+
<?php
|
137 |
+
$merge_tags[ $tag ] = ob_get_clean();
|
138 |
+
}
|
139 |
+
$merge_tags['{payment_table}'] = $merge_tags['{payment_status_table}'] . $merge_tags['{payment_gateway_table}'] . $merge_tags['{transaction_id_table}'];
|
140 |
+
|
141 |
+
foreach ( $merge_tags as $key => $value ) {
|
142 |
+
if ( ! empty( $value ) && stripos( $key, '_table}' ) !== false ) {
|
143 |
+
$merge_tags[ $key ] = '
|
144 |
+
<table width="99%" border="0" cellpadding="1" cellspacing="0" bgcolor="#EAEAEA">
|
145 |
+
<tr>
|
146 |
+
<td>
|
147 |
+
<table width="100%" border="0" cellpadding="5" cellspacing="0" bgcolor="#FFFFFF">' . $merge_tags[ $key ] . '</table>
|
148 |
+
</td>
|
149 |
+
</tr>
|
150 |
+
</table>';
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
$merge_tags = array_merge( $merge_tags, array(
|
155 |
+
'{rtl_start}' => '<div style="text-align: right !important; direction: rtl !important;">',
|
156 |
+
'{rtl_end}' => '</div>',
|
157 |
+
'{post_permalink}' => rgar( $entry, 'post_id' ) ? get_permalink( rgar( $entry, 'post_id' ) ) : '',
|
158 |
+
) );
|
159 |
+
|
160 |
+
return str_replace( array_keys( $merge_tags ), array_values( $merge_tags ), $text );
|
161 |
+
}
|
162 |
+
/*-------------------------------------------------------------*/
|
163 |
+
/*--------End of Persian Gravity Merge Tags--------------------*/
|
164 |
+
/*-------------------------------------------------------------*/
|
165 |
+
|
166 |
+
|
167 |
+
/*-------------------------------------------------------------*/
|
168 |
+
/*--------Start of Subtotal Merge Tags-------------------------*/
|
169 |
+
/*-------------------------------------------------------------*/
|
170 |
+
public function maybe_replace_subtotal_merge_tag( $form, $filter_tags = true ) {
|
171 |
+
|
172 |
+
foreach ( $form['fields'] as &$field ) {
|
173 |
+
|
174 |
+
if ( current_filter() == 'gform_pre_render' ) {
|
175 |
+
$filter_tags = false;
|
176 |
+
if ( rgar( $field, 'origCalculationFormula' ) ) {
|
177 |
+
$field['calculationFormula'] = $field['origCalculationFormula'];
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
if ( ! $this->has_subtotal_merge_tag( $field ) ) {
|
182 |
+
continue;
|
183 |
+
}
|
184 |
+
|
185 |
+
$subtotal_merge_tags = $this->get_subtotal_merge_tag_string( $form, $field, $filter_tags );
|
186 |
+
$field['origCalculationFormula'] = $field['calculationFormula'];
|
187 |
+
$field['calculationFormula'] = str_replace( '{subtotal}', $subtotal_merge_tags, $field['calculationFormula'] );
|
188 |
+
}
|
189 |
+
|
190 |
+
return $form;
|
191 |
+
}
|
192 |
+
|
193 |
+
public function get_subtotal_merge_tag_string( $form, $current_field, $filter_tags = false ) {
|
194 |
+
|
195 |
+
$product_fields = array();
|
196 |
+
|
197 |
+
foreach ( $form["fields"] as $field ) {
|
198 |
+
|
199 |
+
if ( ! in_array( $field["type"], array( 'product', 'shopping_cart' ) ) ) {
|
200 |
+
continue;
|
201 |
+
}
|
202 |
+
|
203 |
+
switch ( $field["type"] ) {
|
204 |
+
case 'product':
|
205 |
+
$option_fields = GFCommon::get_product_fields_by_type( $form, array( "option" ), $field['id'] );
|
206 |
+
// can only have 1 quantity field
|
207 |
+
$quantity_field = GFCommon::get_product_fields_by_type( $form, array( "quantity" ), $field['id'] );
|
208 |
+
$quantity_field = rgar( $quantity_field, 0 );
|
209 |
+
$product_fields[] = array(
|
210 |
+
'product' => $field,
|
211 |
+
'options' => $option_fields,
|
212 |
+
'quantity' => $quantity_field
|
213 |
+
);
|
214 |
+
break;
|
215 |
+
|
216 |
+
case 'shopping_cart':
|
217 |
+
//todo : for next update
|
218 |
+
break;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
$shipping_field = GFCommon::get_fields_by_type( $form, array( "shipping" ) );
|
222 |
+
$pricing_fields = array( "products" => $product_fields, "shipping" => $shipping_field );
|
223 |
+
|
224 |
+
$product_tag_groups = array();
|
225 |
+
foreach ( $pricing_fields['products'] as $product ) {
|
226 |
+
|
227 |
+
$product_field = rgar( $product, 'product' );
|
228 |
+
$option_fields = rgar( $product, 'options' );
|
229 |
+
$quantity_field = rgar( $product, 'quantity' );
|
230 |
+
|
231 |
+
// do not include current field in subtotal
|
232 |
+
if ( $product_field['id'] == $current_field['id'] ) {
|
233 |
+
continue;
|
234 |
+
}
|
235 |
+
|
236 |
+
$product_tags = GFCommon::get_field_merge_tags( $product_field );
|
237 |
+
$quantity_tag = 1;
|
238 |
+
|
239 |
+
// if a single product type, only get the "price" merge tag
|
240 |
+
if ( in_array( GFFormsModel::get_input_type( $product_field ), array(
|
241 |
+
'singleproduct',
|
242 |
+
'calculation',
|
243 |
+
'hiddenproduct'
|
244 |
+
) ) ) {
|
245 |
+
|
246 |
+
// single products provide quantity merge tag
|
247 |
+
if ( empty( $quantity_field ) && ! rgar( $product_field, 'disableQuantity' ) ) {
|
248 |
+
$quantity_tag = $product_tags[2]['tag'];
|
249 |
+
}
|
250 |
+
|
251 |
+
$product_tags = array( $product_tags[1] );
|
252 |
+
}
|
253 |
+
|
254 |
+
// if quantity field is provided for product, get merge tag
|
255 |
+
if ( ! empty( $quantity_field ) ) {
|
256 |
+
$quantity_tag = GFCommon::get_field_merge_tags( $quantity_field );
|
257 |
+
$quantity_tag = $quantity_tag[0]['tag'];
|
258 |
+
}
|
259 |
+
|
260 |
+
|
261 |
+
if ( is_numeric( $quantity_tag ) ) {
|
262 |
+
$qty_value = $quantity_tag;
|
263 |
+
} else {
|
264 |
+
// extract qty input ID from the merge tag
|
265 |
+
preg_match_all( '/{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/mi', $quantity_tag, $matches, PREG_SET_ORDER );
|
266 |
+
$qty_input_id = rgars( $matches, '0/1' );
|
267 |
+
$qty_value = rgpost( 'input_' . str_replace( '.', '_', $qty_input_id ) );
|
268 |
+
}
|
269 |
+
|
270 |
+
if ( $filter_tags && floatval( $qty_value ) <= 0 ) {
|
271 |
+
continue;
|
272 |
+
}
|
273 |
+
|
274 |
+
$product_tags = wp_list_pluck( $product_tags, 'tag' );
|
275 |
+
$option_tags = array();
|
276 |
+
|
277 |
+
foreach ( $option_fields as $option_field ) {
|
278 |
+
|
279 |
+
if ( is_array( $option_field['inputs'] ) ) {
|
280 |
+
|
281 |
+
$choice_number = 1;
|
282 |
+
|
283 |
+
foreach ( $option_field['inputs'] as &$input ) {
|
284 |
+
|
285 |
+
//hack to skip numbers ending in 0. so that 5.1 doesn't conflict with 5.10
|
286 |
+
if ( $choice_number % 10 == 0 ) {
|
287 |
+
$choice_number ++;
|
288 |
+
}
|
289 |
+
|
290 |
+
$input['id'] = $option_field['id'] . '.' . $choice_number ++;
|
291 |
+
|
292 |
+
}
|
293 |
+
}
|
294 |
+
|
295 |
+
$new_options_tags = GFCommon::get_field_merge_tags( $option_field );
|
296 |
+
if ( ! is_array( $new_options_tags ) ) {
|
297 |
+
continue;
|
298 |
+
}
|
299 |
+
|
300 |
+
if ( GFFormsModel::get_input_type( $option_field ) == 'checkbox' ) {
|
301 |
+
array_shift( $new_options_tags );
|
302 |
+
}
|
303 |
+
|
304 |
+
$option_tags = array_merge( $option_tags, $new_options_tags );
|
305 |
+
}
|
306 |
+
|
307 |
+
$option_tags = wp_list_pluck( $option_tags, 'tag' );
|
308 |
+
|
309 |
+
$product_tag_groups[] = '( ( ' . implode( ' + ', array_merge( $product_tags, $option_tags ) ) . ' ) * ' . $quantity_tag . ' )';
|
310 |
+
|
311 |
+
}
|
312 |
+
|
313 |
+
$shipping_tag = 0;
|
314 |
+
//Shipping should not be included in subtotal, correct?
|
315 |
+
if ( rgar( $pricing_fields, 'shipping' ) ) {
|
316 |
+
$shipping_tag = GFCommon::get_field_merge_tags( rgars( $pricing_fields, 'shipping/0' ) );
|
317 |
+
$shipping_tag = $shipping_tag[0]['tag'];
|
318 |
+
}
|
319 |
+
|
320 |
+
$subtotal_merge_tags = '( ( ' . implode( ' + ', $product_tag_groups ) . ' ) + ' . $shipping_tag . ' )';
|
321 |
+
|
322 |
+
return $subtotal_merge_tags;
|
323 |
+
}
|
324 |
+
|
325 |
+
public function has_subtotal_merge_tag( $field ) {
|
326 |
+
|
327 |
+
// check if form is passed
|
328 |
+
if ( isset( $field['fields'] ) ) {
|
329 |
+
|
330 |
+
$form = $field;
|
331 |
+
foreach ( $form['fields'] as $field ) {
|
332 |
+
if ( $this->has_subtotal_merge_tag( $field ) ) {
|
333 |
+
return true;
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
} else {
|
338 |
+
|
339 |
+
if ( isset( $field['calculationFormula'] ) && strpos( $field['calculationFormula'], '{subtotal}' ) !== false ) {
|
340 |
+
return true;
|
341 |
+
}
|
342 |
+
|
343 |
+
}
|
344 |
+
|
345 |
+
return false;
|
346 |
+
}
|
347 |
+
/*-------------------------------------------------------------*/
|
348 |
+
/*--------End of Subtotal Merge Tags---------------------------*/
|
349 |
+
/*-------------------------------------------------------------*/
|
350 |
+
|
351 |
+
|
352 |
+
/*-------------------------------------------------------------*/
|
353 |
+
/*--------Start of Post Content Merge Tags---------------------*/
|
354 |
+
/*-------------------------------------------------------------*/
|
355 |
+
public function merge_tags_values_post_content( $post_content ) {
|
356 |
+
|
357 |
+
$entry_time = $this->entry_time;
|
358 |
+
|
359 |
+
if ( ! self::$_entry ) {
|
360 |
+
|
361 |
+
$entry_id = rgget( 'entry' );
|
362 |
+
|
363 |
+
if ( $entry_id ) {
|
364 |
+
if ( ! $entry_time || ! is_numeric( $entry_id ) || intval( $entry_id ) <= 0 ) {
|
365 |
+
|
366 |
+
if ( method_exists( 'GFCommon', 'openssl_decrypt' ) ) {
|
367 |
+
$entry_id = GFCommon::openssl_decrypt( $entry_id );
|
368 |
+
} elseif ( method_exists( 'GFCommon', 'decrypt' ) ) {
|
369 |
+
$entry_id = GFCommon::decrypt( $entry_id );
|
370 |
+
}
|
371 |
+
$entry_id = intval( $entry_id );
|
372 |
+
}
|
373 |
+
} else {
|
374 |
+
$post = get_post();
|
375 |
+
if ( $post ) {
|
376 |
+
$entry_id = get_post_meta( $post->ID, '_gform-entry-id', true );
|
377 |
+
}
|
378 |
+
}
|
379 |
+
|
380 |
+
if ( $entry_id ) {
|
381 |
+
$entry = GFAPI::get_entry( $entry_id );
|
382 |
+
}
|
383 |
+
|
384 |
+
self::$_entry = ! empty( $entry ) && $entry ? $entry : false;
|
385 |
+
}
|
386 |
+
$entry = self::$_entry;
|
387 |
+
|
388 |
+
if ( ! $entry ) {
|
389 |
+
$post_content = $this->replace_field_label_merge_tags( $post_content, '' );
|
390 |
+
} else {
|
391 |
+
|
392 |
+
if ( $entry_time ) {
|
393 |
+
$confirm_time = gform_get_meta( rgar( $entry, 'id' ), 'gform_page_confirm_time' );
|
394 |
+
if ( empty( $confirm_time ) ) {
|
395 |
+
gform_update_meta( $entry['id'], 'gform_page_confirm_time', time() );
|
396 |
+
} elseif ( $confirm_time + $entry_time < time() ) {
|
397 |
+
return $this->replace_field_label_merge_tags( $post_content, '' );
|
398 |
+
}
|
399 |
+
}
|
400 |
+
|
401 |
+
$form = GFFormsModel::get_form_meta( $entry['form_id'] );
|
402 |
+
$post_content = $this->replace_field_label_merge_tags( $post_content, $form );
|
403 |
+
$post_content = GFCommon::replace_variables( $post_content, $form, $entry, false, false, false );
|
404 |
+
}
|
405 |
+
|
406 |
+
return $post_content;
|
407 |
+
}
|
408 |
+
|
409 |
+
public function replace_field_label_merge_tags( $text, $form ) {
|
410 |
+
|
411 |
+
if ( ! empty( $form ) ) {
|
412 |
+
|
413 |
+
preg_match_all( '/{([^:]+?)}/', $text, $matches, PREG_SET_ORDER );
|
414 |
+
if ( empty( $matches ) ) {
|
415 |
+
return $text;
|
416 |
+
}
|
417 |
+
|
418 |
+
foreach ( $matches as $match ) {
|
419 |
+
|
420 |
+
list( $search, $field_label ) = $match;
|
421 |
+
|
422 |
+
foreach ( $form['fields'] as $field ) {
|
423 |
+
|
424 |
+
$matches_admin_label = rgar( $field, 'adminLabel' ) == $field_label;
|
425 |
+
$matches_field_label = false;
|
426 |
+
|
427 |
+
if ( is_array( $field['inputs'] ) ) {
|
428 |
+
foreach ( $field['inputs'] as $input ) {
|
429 |
+
if ( GFFormsModel::get_label( $field, $input['id'] ) == $field_label ) {
|
430 |
+
$matches_field_label = true;
|
431 |
+
$input_id = $input['id'];
|
432 |
+
break;
|
433 |
+
}
|
434 |
+
}
|
435 |
+
} else {
|
436 |
+
$matches_field_label = GFFormsModel::get_label( $field ) == $field_label;
|
437 |
+
$input_id = $field['id'];
|
438 |
+
}
|
439 |
+
|
440 |
+
if ( ! $matches_admin_label && ! $matches_field_label ) {
|
441 |
+
continue;
|
442 |
+
}
|
443 |
+
|
444 |
+
$replace = sprintf( '{%s:%s}', $field_label, (string) $input_id );
|
445 |
+
$text = str_replace( $search, $replace, $text );
|
446 |
+
|
447 |
+
break;
|
448 |
+
}
|
449 |
+
}
|
450 |
+
} else {
|
451 |
+
|
452 |
+
/*
|
453 |
+
preg_match_all( '/{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/mi', $text, $matches, PREG_SET_ORDER );
|
454 |
+
if( !empty( $matches ) ) {
|
455 |
+
foreach( $matches as $match ) {
|
456 |
+
if ( isset($match[0]))
|
457 |
+
$text = str_replace( $match[0], '' , $text );
|
458 |
+
}
|
459 |
+
}
|
460 |
+
|
461 |
+
unset($matches);
|
462 |
+
|
463 |
+
preg_match_all( '/{([^:]+?)}/', $text, $matches, PREG_SET_ORDER );
|
464 |
+
if( !empty( $matches ) ) {
|
465 |
+
foreach( $matches as $match ) {
|
466 |
+
if ( isset($match[0]))
|
467 |
+
$text = str_replace( $match[0], '' , $text );
|
468 |
+
}
|
469 |
+
}
|
470 |
+
*/
|
471 |
+
|
472 |
+
}
|
473 |
+
|
474 |
+
return $text;
|
475 |
+
}
|
476 |
+
|
477 |
+
public function confirmation_append_entry( $confirmation, $form, $entry ) {
|
478 |
+
|
479 |
+
$is_ajax_redirect = is_string( $confirmation ) && strpos( $confirmation, 'gformRedirect' );
|
480 |
+
$is_redirect = is_array( $confirmation ) && isset( $confirmation['redirect'] );
|
481 |
+
|
482 |
+
if ( ! $is_ajax_redirect && ! $is_redirect ) {
|
483 |
+
return $confirmation;
|
484 |
+
}
|
485 |
+
|
486 |
+
$entry_id = $entry['id'];
|
487 |
+
|
488 |
+
if ( ! $this->entry_time ) {
|
489 |
+
if ( method_exists( 'GFCommon', 'openssl_encrypt' ) ) {
|
490 |
+
$entry_id = rawurlencode( GFCommon::openssl_encrypt( $entry_id ) );
|
491 |
+
} elseif ( method_exists( 'GFCommon', 'encrypt' ) ) {
|
492 |
+
$entry_id = rawurlencode( GFCommon::encrypt( $entry_id ) );
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
if ( $is_ajax_redirect ) {
|
497 |
+
preg_match_all( '/gformRedirect.+?(http.+?)(?=\'|")/', $confirmation, $matches, PREG_SET_ORDER );
|
498 |
+
list( $full_match, $url ) = $matches[0];
|
499 |
+
$redirect_url = add_query_arg( array( 'entry' => $entry_id ), $url );
|
500 |
+
$confirmation = str_replace( $url, $redirect_url, $confirmation );
|
501 |
+
} else {
|
502 |
+
$redirect_url = add_query_arg( array( 'entry' => $entry_id ), $confirmation['redirect'] );
|
503 |
+
$confirmation['redirect'] = $redirect_url;
|
504 |
+
}
|
505 |
+
|
506 |
+
return $confirmation;
|
507 |
+
}
|
508 |
+
/*-------------------------------------------------------------*/
|
509 |
+
/*--------End of Post Content Merge Tags-----------------------*/
|
510 |
+
/*-------------------------------------------------------------*/
|
511 |
+
|
512 |
+
|
513 |
+
/*-------------------------------------------------------------*/
|
514 |
+
/*--------Start of Pre Submission Merge Tags-------------------*/
|
515 |
+
/*-------------------------------------------------------------*/
|
516 |
+
public function merge_tags_pre_submission( $form ) {
|
517 |
+
|
518 |
+
if ( function_exists( 'is_checkout' ) && is_checkout() ) {
|
519 |
+
return $form;
|
520 |
+
}
|
521 |
+
|
522 |
+
$current_page = isset( GFFormDisplay::$submission[ $form['id'] ] ) && isset( GFFormDisplay::$submission[ $form['id'] ]['page_number'] ) ? GFFormDisplay::$submission[ $form['id'] ]['page_number'] : 1;
|
523 |
+
//$fields = array();
|
524 |
+
|
525 |
+
if ( empty( $form['fields'] ) || ! is_array( $form['fields'] ) ) {
|
526 |
+
return $form;
|
527 |
+
}
|
528 |
+
|
529 |
+
// get all HTML fields on the current page
|
530 |
+
foreach ( $form['fields'] as &$field ) {
|
531 |
+
|
532 |
+
// skip all fields on the first page
|
533 |
+
if ( rgar( $field, 'pageNumber' ) <= 1 ) {
|
534 |
+
continue;
|
535 |
+
}
|
536 |
+
|
537 |
+
$default_value = rgar( $field, 'defaultValue' );
|
538 |
+
preg_match_all( '/{.+}/', $default_value, $matches, PREG_SET_ORDER );
|
539 |
+
if ( ! empty( $matches ) ) {
|
540 |
+
// if default value needs to be replaced but is not on current page, wait until on the current page to replace it
|
541 |
+
if ( rgar( $field, 'pageNumber' ) != $current_page ) {
|
542 |
+
$field['defaultValue'] = '';
|
543 |
+
} else {
|
544 |
+
$field['defaultValue'] = $this->preview_replace_variables( $default_value, $form );
|
545 |
+
}
|
546 |
+
}
|
547 |
+
|
548 |
+
// only run 'content' filter for fields on the current page
|
549 |
+
if ( rgar( $field, 'pageNumber' ) != $current_page ) {
|
550 |
+
continue;
|
551 |
+
}
|
552 |
+
|
553 |
+
$html_content = rgar( $field, 'content' );
|
554 |
+
preg_match_all( '/{.+}/', $html_content, $matches, PREG_SET_ORDER );
|
555 |
+
if ( ! empty( $matches ) ) {
|
556 |
+
$field['content'] = $this->preview_replace_variables( $html_content, $form );
|
557 |
+
}
|
558 |
+
|
559 |
+
}
|
560 |
+
|
561 |
+
return $form;
|
562 |
+
}
|
563 |
+
|
564 |
+
public function preview_special_merge_tags( $value, $input_id, $merge_tag, $field ) {
|
565 |
+
|
566 |
+
// added to prevent overriding :noadmin filter (and other filters that remove fields)
|
567 |
+
if ( ! $value ) {
|
568 |
+
return $value;
|
569 |
+
}
|
570 |
+
|
571 |
+
$input_type = RGFormsModel::get_input_type( $field );
|
572 |
+
|
573 |
+
$is_upload_field = in_array( $input_type, array( 'post_image', 'fileupload' ) );
|
574 |
+
$is_multi_input = is_array( rgar( $field, 'inputs' ) );
|
575 |
+
$is_input = intval( $input_id ) != $input_id;
|
576 |
+
|
577 |
+
if ( ! $is_upload_field && ! $is_multi_input ) {
|
578 |
+
return $value;
|
579 |
+
}
|
580 |
+
|
581 |
+
// if is individual input of multi-input field, return just that input value
|
582 |
+
if ( $is_input ) {
|
583 |
+
return $value;
|
584 |
+
}
|
585 |
+
|
586 |
+
$form = RGFormsModel::get_form_meta( $field['formId'] );
|
587 |
+
$entry = $this->create_entry( $form );
|
588 |
+
$currency = GFCommon::get_currency();
|
589 |
+
|
590 |
+
if ( is_array( rgar( $field, 'inputs' ) ) ) {
|
591 |
+
$value = RGFormsModel::get_lead_field_value( $entry, $field );
|
592 |
+
|
593 |
+
return GFCommon::get_lead_field_display( $field, $value, $currency );
|
594 |
+
}
|
595 |
+
|
596 |
+
$input_name = "input_{$field['id']}";
|
597 |
+
|
598 |
+
$file_info = RGFormsModel::get_temp_filename( $form['id'], $input_name );
|
599 |
+
$source = RGFormsModel::get_upload_url( $form['id'] ) . "/tmp/" . $file_info["temp_filename"];
|
600 |
+
|
601 |
+
$value = '';
|
602 |
+
if ( $file_info ) {
|
603 |
+
switch ( RGFormsModel::get_input_type( $field ) ) {
|
604 |
+
case "post_image":
|
605 |
+
list( , $image_title, $image_caption, $image_description ) = explode( "|:|", $entry[ $field['id'] ] );
|
606 |
+
$value = ! empty( $source ) ? $source . "|:|" . $image_title . "|:|" . $image_caption . "|:|" . $image_description : "";
|
607 |
+
break;
|
608 |
+
|
609 |
+
case "fileupload" :
|
610 |
+
$value = $source;
|
611 |
+
break;
|
612 |
+
|
613 |
+
}
|
614 |
+
}
|
615 |
+
|
616 |
+
switch ( $input_type ) {
|
617 |
+
case 'fileupload':
|
618 |
+
|
619 |
+
if ( ! empty( $value ) ) {
|
620 |
+
$input_name = "input_" . str_replace( '.', '_', $field['id'] );
|
621 |
+
$file_info = RGFormsModel::get_temp_filename( $form['id'], $input_name );
|
622 |
+
$value = esc_attr( str_replace( " ", "%20", $value ) );
|
623 |
+
$value = "<a href='$value' target='_blank' title='" . __( "Click to view", "gravityforms" ) . "'>" . $file_info['uploaded_filename'] . "</a>";
|
624 |
+
}
|
625 |
+
break;
|
626 |
+
default:
|
627 |
+
$value = GFCommon::get_lead_field_display( $field, $value, $currency );
|
628 |
+
break;
|
629 |
+
}
|
630 |
+
|
631 |
+
return $value;
|
632 |
+
}
|
633 |
+
|
634 |
+
public function preview_replace_variables( $content, $form ) {
|
635 |
+
|
636 |
+
$entry = $this->create_entry( $form );
|
637 |
+
|
638 |
+
// add filter that will handle getting temporary URLs for file uploads and post image fields (removed below)
|
639 |
+
// beware, the RGFormsModel::create_lead() function also triggers the gform_merge_tag_filter at some point and will
|
640 |
+
// result in an infinite loop if not called first above
|
641 |
+
add_filter( 'gform_merge_tag_filter', array( $this, 'preview_special_merge_tags' ), 10, 4 );
|
642 |
+
|
643 |
+
$content = GFCommon::replace_variables( $content, $form, $entry, false, false, false );
|
644 |
+
|
645 |
+
// remove filter so this function is not applied after preview functionality is complete
|
646 |
+
remove_filter( 'gform_merge_tag_filter', array( $this, 'preview_special_merge_tags' ) );
|
647 |
+
|
648 |
+
return $content;
|
649 |
+
}
|
650 |
+
|
651 |
+
public function create_entry( $form ) {
|
652 |
+
|
653 |
+
if ( empty( self::$_entry ) ) {
|
654 |
+
self::$_entry = GFFormsModel::create_lead( $form );
|
655 |
+
if ( class_exists( 'GFCache' ) ) {
|
656 |
+
foreach ( $form['fields'] as &$field ) {
|
657 |
+
if ( GFFormsModel::get_input_type( $field ) == 'total' ) {
|
658 |
+
GFCache::delete( 'GFFormsModel::get_lead_field_value__' . $field['id'] );
|
659 |
+
}
|
660 |
+
}
|
661 |
+
}
|
662 |
+
}
|
663 |
+
|
664 |
+
return self::$_entry;
|
665 |
+
}
|
666 |
+
/*-------------------------------------------------------------*/
|
667 |
+
/*--------End of Pre Submission Merge Tags---------------------*/
|
668 |
+
/*-------------------------------------------------------------*/
|
669 |
+
|
670 |
+
}
|
671 |
+
|
672 |
+
new GFPersian_Merge_Tags;
|
includes/class-multi-page-navi.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Multipage_Navigation extends GFPersian_Core {
|
6 |
+
|
7 |
+
public $_args = array();
|
8 |
+
|
9 |
+
private static $script_displayed;
|
10 |
+
|
11 |
+
public function __construct() {
|
12 |
+
|
13 |
+
if ( is_admin() || $this->option( 'multipage_nav', '1' ) != '1' ) {
|
14 |
+
return;
|
15 |
+
}
|
16 |
+
|
17 |
+
$this->_args = array(
|
18 |
+
'activate_on_last_page' => $this->option( 'multipage_nav_last', '1' )
|
19 |
+
);
|
20 |
+
|
21 |
+
add_filter( 'gform_pre_render', array( $this, 'output_navigation_script' ), 10, 2 );
|
22 |
+
}
|
23 |
+
|
24 |
+
public function output_navigation_script( $form, $is_ajax ) {
|
25 |
+
|
26 |
+
// only apply this to multi-page forms
|
27 |
+
if ( empty( $form['pagination']['pages'] ) || ! is_array( $form['pagination']['pages'] ) || count( $form['pagination']['pages'] ) <= 1 ) {
|
28 |
+
return $form;
|
29 |
+
}
|
30 |
+
|
31 |
+
$this->register_script( $form );
|
32 |
+
|
33 |
+
if ( ! $this->_args['activate_on_last_page'] || $this->is_last_page( $form ) || $this->is_last_page_reached() ) {
|
34 |
+
add_filter( "gform_form_tag_{$form['id']}", function ( $tag ) {
|
35 |
+
return $tag . '<input id="gform_multi_page_nav_last_page_reached" name="gform_multi_page_nav_last_page_reached" value="1" type="hidden" />';
|
36 |
+
} );
|
37 |
+
}
|
38 |
+
|
39 |
+
// only output the gform_multi_page_nav object once regardless of how many forms are being displayed
|
40 |
+
// also do not output again on ajax submissions
|
41 |
+
if ( self::$script_displayed || ( $is_ajax && rgpost( 'gform_submit' ) ) ) {
|
42 |
+
return $form;
|
43 |
+
}
|
44 |
+
?>
|
45 |
+
|
46 |
+
<script type="text/javascript">
|
47 |
+
|
48 |
+
(function ($) {
|
49 |
+
|
50 |
+
window.gform_multi_page_navObj = function (args) {
|
51 |
+
|
52 |
+
this.formId = args.formId;
|
53 |
+
this.formElem = jQuery('form#gform_' + this.formId);
|
54 |
+
this.currentPage = args.currentPage;
|
55 |
+
this.lastPage = args.lastPage;
|
56 |
+
this.activateOnLastPage = args.activateOnLastPage;
|
57 |
+
|
58 |
+
this.init = function () {
|
59 |
+
|
60 |
+
// if this form is ajax-enabled, we'll need to get the current page via JS
|
61 |
+
if (this.isAjax())
|
62 |
+
this.currentPage = this.getCurrentPage();
|
63 |
+
|
64 |
+
if (!this.isLastPage() && !this.isLastPageReached())
|
65 |
+
return;
|
66 |
+
|
67 |
+
var gform_multi_page_nav = this;
|
68 |
+
var steps = $('form#gform_' + this.formId + ' .gf_step');
|
69 |
+
|
70 |
+
steps.each(function () {
|
71 |
+
|
72 |
+
var stepNumber = parseInt($(this).find('span.gf_step_number').text());
|
73 |
+
|
74 |
+
if (stepNumber != gform_multi_page_nav.currentPage) {
|
75 |
+
$(this).html(gform_multi_page_nav.createPageLink(stepNumber, $(this).html()))
|
76 |
+
.addClass('gform_multi_page_nav-step-linked');
|
77 |
+
} else {
|
78 |
+
$(this).addClass('gform_multi_page_nav-step-current');
|
79 |
+
}
|
80 |
+
|
81 |
+
});
|
82 |
+
|
83 |
+
$(document).on('click', '#gform_' + this.formId + ' a.gform_multi_page_nav-page-link', function (event) {
|
84 |
+
event.preventDefault();
|
85 |
+
|
86 |
+
var hrefArray = $(this).attr('href').split('#');
|
87 |
+
if (hrefArray.length >= 2) {
|
88 |
+
var pageNumber = hrefArray.pop();
|
89 |
+
gform_multi_page_nav.postToPage(pageNumber, !$(this).hasClass('gform_multi_page_navmp-default'));
|
90 |
+
}
|
91 |
+
|
92 |
+
});
|
93 |
+
|
94 |
+
};
|
95 |
+
|
96 |
+
this.createPageLink = function (stepNumber, HTML) {
|
97 |
+
return '<a href="#' + stepNumber + '" class="gform_multi_page_nav-page-link gform_multi_page_nav-default">' + HTML + '</a>';
|
98 |
+
};
|
99 |
+
|
100 |
+
this.postToPage = function (page) {
|
101 |
+
this.formElem.append('<input type="hidden" name="gform_multi_page_nav_page_change" value="1" />');
|
102 |
+
this.formElem.find('input[name="gform_target_page_number_' + this.formId + '"]').val(page);
|
103 |
+
this.formElem.submit();
|
104 |
+
};
|
105 |
+
|
106 |
+
this.getCurrentPage = function () {
|
107 |
+
return this.formElem.find('input#gform_source_page_number_' + this.formId).val();
|
108 |
+
};
|
109 |
+
|
110 |
+
this.isLastPage = function () {
|
111 |
+
return this.currentPage >= this.lastPage;
|
112 |
+
};
|
113 |
+
|
114 |
+
this.isLastPageReached = function () {
|
115 |
+
return this.formElem.find('input[name="gform_multi_page_nav_last_page_reached"]').val() == true;
|
116 |
+
};
|
117 |
+
|
118 |
+
this.isAjax = function () {
|
119 |
+
return this.formElem.attr('target') == 'gform_ajax_frame_' + this.formId;
|
120 |
+
};
|
121 |
+
|
122 |
+
this.init();
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
})(jQuery);
|
127 |
+
|
128 |
+
</script>
|
129 |
+
|
130 |
+
<?php
|
131 |
+
self::$script_displayed = true;
|
132 |
+
|
133 |
+
return $form;
|
134 |
+
}
|
135 |
+
|
136 |
+
public function register_script( $form ) {
|
137 |
+
|
138 |
+
$page_number = GFFormDisplay::get_current_page( $form['id'] );
|
139 |
+
$last_page = count( $form['pagination']['pages'] );
|
140 |
+
|
141 |
+
$args = array(
|
142 |
+
'formId' => $form['id'],
|
143 |
+
'currentPage' => $page_number,
|
144 |
+
'lastPage' => $last_page,
|
145 |
+
'activateOnLastPage' => $this->_args['activate_on_last_page'],
|
146 |
+
);
|
147 |
+
|
148 |
+
$script = "window.gform_multi_page_nav = new gform_multi_page_navObj(" . json_encode( $args ) . ");";
|
149 |
+
GFFormDisplay::add_init_script( $form['id'], 'gform_multi_page_nav', GFFormDisplay::ON_PAGE_RENDER, $script );
|
150 |
+
|
151 |
+
}
|
152 |
+
|
153 |
+
public function is_last_page( $form ) {
|
154 |
+
|
155 |
+
$page_number = GFFormDisplay::get_current_page( $form['id'] );
|
156 |
+
$last_page = count( $form['pagination']['pages'] );
|
157 |
+
|
158 |
+
return $page_number >= $last_page;
|
159 |
+
}
|
160 |
+
|
161 |
+
public function is_last_page_reached() {
|
162 |
+
return rgpost( 'gform_multi_page_nav_last_page_reached' );
|
163 |
+
}
|
164 |
+
|
165 |
+
}
|
166 |
+
|
167 |
+
new GFPersian_Multipage_Navigation();
|
includes/class-multipage-navigation.php
DELETED
@@ -1,160 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
-
|
3 |
-
class GFParsi_MultipageNavigation {
|
4 |
-
|
5 |
-
public $_args = array();
|
6 |
-
|
7 |
-
private static $script_displayed;
|
8 |
-
|
9 |
-
function __construct() {
|
10 |
-
|
11 |
-
if ( is_admin() )
|
12 |
-
return;
|
13 |
-
|
14 |
-
$this->_args = array(
|
15 |
-
'activate_on_last_page' => apply_filters( 'gf_mn_activate_on_last_page' , true )
|
16 |
-
);
|
17 |
-
|
18 |
-
add_filter( 'gform_pre_render', array( $this, 'output_navigation_script' ), 10, 2 );
|
19 |
-
}
|
20 |
-
|
21 |
-
function output_navigation_script( $form, $is_ajax ) {
|
22 |
-
|
23 |
-
// only apply this to multi-page forms
|
24 |
-
if( count($form['pagination']['pages']) <= 1 )
|
25 |
-
return $form;
|
26 |
-
|
27 |
-
$this->register_script( $form );
|
28 |
-
|
29 |
-
if( ! $this->_args['activate_on_last_page'] || $this->is_last_page( $form ) || $this->is_last_page_reached() ) {
|
30 |
-
$input = '<input id="gfir_last_page_reached" name="gfir_last_page_reached" value="1" type="hidden" />';
|
31 |
-
add_filter( "gform_form_tag_{$form['id']}", create_function('$a', 'return $a . \'' . $input . '\';' ) );
|
32 |
-
}
|
33 |
-
|
34 |
-
// only output the gfirmpn object once regardless of how many forms are being displayed
|
35 |
-
// also do not output again on ajax submissions
|
36 |
-
if( self::$script_displayed || ( $is_ajax && rgpost('gform_submit') ))
|
37 |
-
return $form;
|
38 |
-
|
39 |
-
?>
|
40 |
-
|
41 |
-
<script type="text/javascript">
|
42 |
-
|
43 |
-
(function($){
|
44 |
-
|
45 |
-
window.gfirmpnObj = function( args ) {
|
46 |
-
|
47 |
-
this.formId = args.formId;
|
48 |
-
this.formElem = jQuery('form#gform_' + this.formId);
|
49 |
-
this.currentPage = args.currentPage;
|
50 |
-
this.lastPage = args.lastPage;
|
51 |
-
this.activateOnLastPage = args.activateOnLastPage;
|
52 |
-
|
53 |
-
this.init = function() {
|
54 |
-
|
55 |
-
// if this form is ajax-enabled, we'll need to get the current page via JS
|
56 |
-
if( this.isAjax() )
|
57 |
-
this.currentPage = this.getCurrentPage();
|
58 |
-
|
59 |
-
if( !this.isLastPage() && !this.isLastPageReached() )
|
60 |
-
return;
|
61 |
-
|
62 |
-
var gfirmpn = this;
|
63 |
-
var steps = $('form#gform_' + this.formId + ' .gf_step');
|
64 |
-
|
65 |
-
steps.each(function(){
|
66 |
-
|
67 |
-
var stepNumber = parseInt( $(this).find('span.gf_step_number').text() );
|
68 |
-
|
69 |
-
if( stepNumber != gfirmpn.currentPage ) {
|
70 |
-
$(this).html( gfirmpn.createPageLink( stepNumber, $(this).html() ) )
|
71 |
-
.addClass('gfir-step-linked');
|
72 |
-
} else {
|
73 |
-
$(this).addClass('gfir-step-current');
|
74 |
-
}
|
75 |
-
|
76 |
-
});
|
77 |
-
|
78 |
-
$(document).on('click', '#gform_' + this.formId + ' a.gfirmpn-page-link', function(event){
|
79 |
-
event.preventDefault();
|
80 |
-
|
81 |
-
var hrefArray = $(this).attr('href').split('#');
|
82 |
-
if( hrefArray.length >= 2 ) {
|
83 |
-
var pageNumber = hrefArray.pop();
|
84 |
-
gfirmpn.postToPage( pageNumber, ! $( this ).hasClass( 'gfirmp-default' ) );
|
85 |
-
}
|
86 |
-
|
87 |
-
});
|
88 |
-
|
89 |
-
}
|
90 |
-
|
91 |
-
this.createPageLink = function( stepNumber, HTML ) {
|
92 |
-
return '<a href="#' + stepNumber + '" class="gfirmpn-page-link gfirmpn-default">' + HTML + '</a>';
|
93 |
-
}
|
94 |
-
|
95 |
-
this.postToPage = function( page ) {
|
96 |
-
this.formElem.append('<input type="hidden" name="gfir_page_change" value="1" />');
|
97 |
-
this.formElem.find( 'input[name="gform_target_page_number_' + this.formId + '"]' ).val( page );
|
98 |
-
this.formElem.submit();
|
99 |
-
}
|
100 |
-
|
101 |
-
this.getCurrentPage = function() {
|
102 |
-
return this.formElem.find( 'input#gform_source_page_number_' + this.formId ).val();
|
103 |
-
}
|
104 |
-
|
105 |
-
this.isLastPage = function() {
|
106 |
-
return this.currentPage >= this.lastPage;
|
107 |
-
}
|
108 |
-
|
109 |
-
this.isLastPageReached = function() {
|
110 |
-
return this.formElem.find('input[name="gfir_last_page_reached"]').val() == true;
|
111 |
-
}
|
112 |
-
|
113 |
-
this.isAjax = function() {
|
114 |
-
return this.formElem.attr('target') == 'gform_ajax_frame_' + this.formId;
|
115 |
-
}
|
116 |
-
|
117 |
-
this.init();
|
118 |
-
|
119 |
-
}
|
120 |
-
|
121 |
-
})(jQuery);
|
122 |
-
|
123 |
-
</script>
|
124 |
-
|
125 |
-
<?php
|
126 |
-
self::$script_displayed = true;
|
127 |
-
return $form;
|
128 |
-
}
|
129 |
-
|
130 |
-
function register_script( $form ) {
|
131 |
-
|
132 |
-
$page_number = GFFormDisplay::get_current_page($form['id']);
|
133 |
-
$last_page = count($form['pagination']['pages']);
|
134 |
-
|
135 |
-
$args = array(
|
136 |
-
'formId' => $form['id'],
|
137 |
-
'currentPage' => $page_number,
|
138 |
-
'lastPage' => $last_page,
|
139 |
-
'activateOnLastPage' => $this->_args['activate_on_last_page'],
|
140 |
-
);
|
141 |
-
|
142 |
-
$script = "window.gfirmpn = new gfirmpnObj(" . json_encode( $args ) . ");";
|
143 |
-
GFFormDisplay::add_init_script( $form['id'], 'gfirmpn', GFFormDisplay::ON_PAGE_RENDER, $script );
|
144 |
-
|
145 |
-
}
|
146 |
-
|
147 |
-
function is_last_page( $form ) {
|
148 |
-
|
149 |
-
$page_number = GFFormDisplay::get_current_page($form['id']);
|
150 |
-
$last_page = count($form['pagination']['pages']);
|
151 |
-
|
152 |
-
return $page_number >= $last_page;
|
153 |
-
}
|
154 |
-
|
155 |
-
function is_last_page_reached() {
|
156 |
-
return rgpost('gfir_last_page_reached');
|
157 |
-
}
|
158 |
-
|
159 |
-
}
|
160 |
-
$gfir_multipage_navigation = new GFParsi_MultipageNavigation( array() );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-national-id.php
ADDED
@@ -0,0 +1,434 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_National_ID extends GFPersian_Core {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
|
9 |
+
if ( $this->option( 'national_id', '1' ) != '1' ) {
|
10 |
+
return;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( is_admin() ) {
|
14 |
+
add_filter( 'gform_add_field_buttons', array( $this, 'button' ) );
|
15 |
+
add_filter( 'gform_field_type_title', array( $this, 'title' ) );
|
16 |
+
add_filter( 'gform_editor_js_set_default_values', array( $this, 'label' ) );
|
17 |
+
add_action( 'gform_editor_js', array( $this, 'settings' ) );
|
18 |
+
add_action( 'gform_field_standard_settings', array( $this, 'standard_settings' ), 10, 2 );
|
19 |
+
add_filter( 'gform_tooltips', array( $this, 'tooltips' ) );
|
20 |
+
add_filter( 'gform_admin_pre_render', array( $this, 'admin_conditional_logic' ) );
|
21 |
+
}
|
22 |
+
|
23 |
+
add_action( 'gform_field_input', array( $this, 'input' ), 10, 5 );
|
24 |
+
add_action( 'gform_field_css_class', array( $this, 'classes' ), 10, 3 );
|
25 |
+
add_action( 'gform_pre_submission', array( $this, 'pre_submission' ) );
|
26 |
+
add_filter( 'gform_field_validation', array( $this, 'validator' ), 10, 4 );
|
27 |
+
add_action( 'gform_enqueue_scripts', array( $this, 'frontend_script' ), 10, 2 );
|
28 |
+
}
|
29 |
+
|
30 |
+
public function button( $field_groups ) {
|
31 |
+
|
32 |
+
foreach ( $field_groups as &$group ) {
|
33 |
+
if ( $group['name'] == 'gf_persian_fields' ) {
|
34 |
+
$group['fields'][] = array(
|
35 |
+
'class' => 'button',
|
36 |
+
'value' => 'کد ملی',
|
37 |
+
'data-type' => 'ir_national_id',
|
38 |
+
//'onclick' => "StartAddField('ir_national_id');"//deprecated
|
39 |
+
);
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
return $field_groups;
|
44 |
+
}
|
45 |
+
|
46 |
+
public function title( $type ) {
|
47 |
+
if ( $type == 'ir_national_id' ) {
|
48 |
+
return 'کد ملی';
|
49 |
+
}
|
50 |
+
|
51 |
+
return $type;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function label() { ?>
|
55 |
+
case 'ir_national_id':
|
56 |
+
field.label = 'کد ملی';
|
57 |
+
break;
|
58 |
+
<?php
|
59 |
+
}
|
60 |
+
|
61 |
+
public function classes( $classes, $field, $form ) {
|
62 |
+
if ( $field['type'] == 'ir_national_id' ) {
|
63 |
+
$classes .= ' gform_ir_national_id';
|
64 |
+
}
|
65 |
+
|
66 |
+
return $classes;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function tooltips( $tooltips ) {
|
70 |
+
$tooltips['tooltip_showLocation'] = '<h6>نمایش لحظه ای شهر از روی کد ملی </h6>نمایش شهر و پیغام زیر فیلد کد ملی بعد از پر شدن فیلد. تذکر : در صورتی که این گزینه را فعال نمایید ،ممکن است فراخوانی شهر های ایران با توجه به زیاد بودن آنها سبب سنگین شدن صفحه گردد.';
|
71 |
+
$tooltips['tooltip_showSeperator'] = '<h6>جدا سازی ارقام</h6>در صورتی که این گزینه را فعال نمایید ، پس از پر شدن فیلد کد ملی ، <strong>در صورتی که کد ملی وارد شده صحیح تشخصی داده شود</strong> ؛ کد ملی به صورت زیر در خواهد آمد و در غیر این صورت علی صحیح نبودن کد ملی زیر فیلد نمایش داده خواهد شد :<br>xxx-xxxxxx-x';
|
72 |
+
$tooltips['tooltip_forceEnglish'] = '<h6>تبدیل اعداد فارسی و عربی به انگلیسی</h6>در صورتی که کاربر کد ملی خود را به صورت انگلیسی وارد نکند با خطا مواجه خواهد شد. پس با فعالسازی این گزینه اعداد وارد شده برای کد ملی را به صورت خودکار به انگلیسی تبدیل کنید.';
|
73 |
+
$tooltips['tooltip_notDigitError'] = 'با توجه به اینکه کد ملی فقط باید به صورت عدد باشد ، در صورتی که کاراکتری غیر از عدد وارد شده باشد پیغام خطا نمایش داده خواهد شد.<br/>پیغام پیشفرض : کد ملی فقط باید به صورت عدد وارد شود.';
|
74 |
+
$tooltips['tooltip_qtyDigitError'] = 'با توجه به اینکه کد ملی می بایست 10 رقمی باشد اگر تعداد رقم وارد شده ، اشتباه باشد پیغام خطا نمایش داده خواهد شد.<br>پیغام پیشفرض : کد ملی می بایست 10 رقمی باشد. تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند.';
|
75 |
+
$tooltips['tooltip_duplicateError'] = 'در صورتی که از تب وِیژگی تیک گزینه بدون تکرار را زده باشید ؛ بعد از پر شدن فرم و زدن دکمه ارسال پیغامی مبتنی بر تکراری بودن کد ملی نمایش داده خواهد شد. <br/>پیغام پیشفرض : این کد ملی توسط فرد دیگری ثبت شده است.';
|
76 |
+
$tooltips['tooltip_isInvalidError'] = 'در صورتی که کد ملی وارد شده مطابق با الگوریتم کشور نباشد پیغام خطا نمایش داده خواهد شد.<br/>پیغام پیشفرض : کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد.';
|
77 |
+
|
78 |
+
return $tooltips;
|
79 |
+
}
|
80 |
+
|
81 |
+
public function input( $input, $field, $value, $entry_id, $form_id ) {
|
82 |
+
|
83 |
+
if ( $field['type'] == 'ir_national_id' ) {
|
84 |
+
|
85 |
+
$field_id = $field['id'];
|
86 |
+
$form_id = ! empty( $form_id ) ? $form_id : rgget( 'id' );
|
87 |
+
$is_admin = is_admin();
|
88 |
+
$is_frontend = ! $is_admin;
|
89 |
+
$is_entry_detail = GFCommon::is_entry_detail();
|
90 |
+
$is_form_editor = GFCommon::is_form_editor();
|
91 |
+
|
92 |
+
if ( $is_frontend && RGFormsModel::get_input_type( $field ) == 'adminonly_hidden' ) {
|
93 |
+
return '';
|
94 |
+
}
|
95 |
+
|
96 |
+
$size = rgar( $field, 'size' );
|
97 |
+
$class_suffix = $is_entry_detail ? '_admin' : '';
|
98 |
+
$class = $size . $class_suffix;
|
99 |
+
|
100 |
+
$input_id = $is_entry_detail || $is_form_editor || $form_id == 0 ? "input_$field_id" : 'input_' . $form_id . "_$field_id";
|
101 |
+
|
102 |
+
$tabindex = GFCommon::get_tabindex();
|
103 |
+
$disabled_text = $is_form_editor ? "disabled='disabled'" : '';
|
104 |
+
|
105 |
+
$max_length = rgar( $field, 'showSeperator' ) ? 12 : 10;
|
106 |
+
$max_length = "maxlength='{$max_length}'";
|
107 |
+
/*
|
108 |
+
$this->get_conditional_logic_event( 'keyup' ) //text or radio
|
109 |
+
$this->get_conditional_logic_event( 'change' ) //select
|
110 |
+
$this->get_conditional_logic_event( 'click' ) // checkbox or radio
|
111 |
+
//note : radio has keyup and click
|
112 |
+
*/
|
113 |
+
|
114 |
+
$logic_event = ! $is_form_editor && ! $is_entry_detail ? $field->get_conditional_logic_event( 'keyup' ) : '';
|
115 |
+
|
116 |
+
$placeholder_attribute = $field->get_field_placeholder_attribute();
|
117 |
+
$required_attribute = $field->isRequired ? 'aria-required="true"' : '';
|
118 |
+
$invalid_attribute = $field->failed_validation ? 'aria-invalid="true"' : 'aria-invalid="false"';
|
119 |
+
$html5_attributes = " {$placeholder_attribute} {$required_attribute} {$invalid_attribute} {$max_length} ";
|
120 |
+
|
121 |
+
$input = '<div class="ginput_container ginput_container_text ginput_container_ir_national_id">';
|
122 |
+
$input .= '<input onblur="ir_national_id_' . $field_id . '(this);" name="input_' . $field_id . '" id="' . $input_id . '" type="text" value="' . esc_attr( $value ) . '" class="ir_national_id ' . esc_attr( $class ) . '" ' . $tabindex . ' ' . $logic_event . ' ' . $html5_attributes . ' ' . $disabled_text . '/>';
|
123 |
+
$input .= '</div>';
|
124 |
+
|
125 |
+
if ( $is_frontend ) {
|
126 |
+
$input .= '<span class="ir_national_id_location" id="ir_national_id_location_' . $field_id . '"></span>';
|
127 |
+
}
|
128 |
+
}
|
129 |
+
|
130 |
+
return $input;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function settings() { ?>
|
134 |
+
<script type='text/javascript'>
|
135 |
+
fieldSettings["ir_national_id"] = ".placeholder_setting, .input_mask_setting, .label_placement_setting, .prepopulate_field_setting, .conditional_logic_field_setting, .label_setting, .admin_label_setting, .size_setting, .rules_setting, .visibility_setting, .duplicate_setting, .default_value_setting, .description_setting, .css_class_setting, .ir_national_id_setting";
|
136 |
+
jQuery(document).bind('gform_load_field_settings', function (event, field, form) {
|
137 |
+
jQuery("#showLocation").attr("checked", field["showLocation"] == true);
|
138 |
+
jQuery("#showSeperator").attr("checked", field["showSeperator"] == true);
|
139 |
+
jQuery("#forceEnglish").attr("checked", field["forceEnglish"] == true);
|
140 |
+
jQuery("#notDigitError").val(field["notDigitError"]);
|
141 |
+
jQuery("#qtyDigitError").val(field["qtyDigitError"]);
|
142 |
+
jQuery("#duplicateError").val(field["duplicateError"]);
|
143 |
+
jQuery("#isInvalidError").val(field["isInvalidError"]);
|
144 |
+
});
|
145 |
+
</script>
|
146 |
+
<?php
|
147 |
+
}
|
148 |
+
|
149 |
+
|
150 |
+
public function admin_conditional_logic( $form ) {
|
151 |
+
|
152 |
+
if ( GFCommon::is_entry_detail() ) {
|
153 |
+
return $form;
|
154 |
+
}
|
155 |
+
|
156 |
+
echo "<script type='text/javascript'>" .
|
157 |
+
" gform.addFilter('gform_is_conditional_logic_field', function (isConditionalLogicField, field) {" .
|
158 |
+
" return field.type == 'ir_national_id' ? true : isConditionalLogicField;" .
|
159 |
+
' });' .
|
160 |
+
" gform.addFilter('gform_conditional_logic_operators', function (operators, objectType, fieldId) {" .
|
161 |
+
' var targetField = GetFieldById(fieldId);' .
|
162 |
+
" if (targetField && targetField['type'] == 'ir_national_id') {" .
|
163 |
+
" operators = {'is':'is','isnot':'isNot', '>':'greaterThan', '<':'lessThan', 'contains':'contains', 'starts_with':'startsWith', 'ends_with':'endsWith'};" .
|
164 |
+
' }' .
|
165 |
+
' return operators;' .
|
166 |
+
' });' .
|
167 |
+
'</script>';
|
168 |
+
|
169 |
+
return $form;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function standard_settings( $position, $form_id ) {
|
173 |
+
|
174 |
+
if ( $position == 50 ) { ?>
|
175 |
+
|
176 |
+
<li class="ir_national_id_setting field_setting">
|
177 |
+
|
178 |
+
<input type="checkbox" id="showLocation"
|
179 |
+
onclick="SetFieldProperty('showLocation', this.checked);"/>
|
180 |
+
<label for="showLocation" class="inline">
|
181 |
+
نمایش شهر بر اساس کد ملی
|
182 |
+
<?php gform_tooltip( "tooltip_showLocation" ); ?>
|
183 |
+
</label>
|
184 |
+
|
185 |
+
<br/>
|
186 |
+
<input type="checkbox" id="showSeperator"
|
187 |
+
onclick="SetFieldProperty('showSeperator', this.checked);"/>
|
188 |
+
<label for="showSeperator" class="inline">
|
189 |
+
جداسازی خودکار ارقام توسط خط فاصله
|
190 |
+
<?php gform_tooltip( "tooltip_showSeperator" ); ?>
|
191 |
+
</label>
|
192 |
+
|
193 |
+
<br/>
|
194 |
+
<input type="checkbox" id="forceEnglish"
|
195 |
+
onclick="SetFieldProperty('forceEnglish', this.checked);"/>
|
196 |
+
<label for="forceEnglish" class="inline">
|
197 |
+
تبدیل خودکار اعداد فارسی و عربی به انگلیسی
|
198 |
+
<?php gform_tooltip( "tooltip_forceEnglish" ); ?>
|
199 |
+
</label>
|
200 |
+
<br/>
|
201 |
+
|
202 |
+
<br/>
|
203 |
+
<label for="notDigitError">
|
204 |
+
پیغام زمانی که مقدار وارد شده شامل کاراکتر غیر عددی باشد
|
205 |
+
<?php gform_tooltip( "tooltip_notDigitError" ); ?>
|
206 |
+
</label>
|
207 |
+
<input type="text" class="fieldwidth-3" id="notDigitError" size="35"
|
208 |
+
onkeyup="SetFieldProperty('notDigitError', this.value);"/>
|
209 |
+
<br/>
|
210 |
+
|
211 |
+
<br/>
|
212 |
+
<label for="qtyDigitError">
|
213 |
+
پیغام زمانیکه تعداد ارقام وارد شده استاندارد نباشد
|
214 |
+
<?php gform_tooltip( "tooltip_qtyDigitError" ); ?>
|
215 |
+
</label>
|
216 |
+
<input type="text" class="fieldwidth-3" id="qtyDigitError" size="35"
|
217 |
+
onkeyup="SetFieldProperty('qtyDigitError', this.value);"/>
|
218 |
+
<br/>
|
219 |
+
|
220 |
+
<br/>
|
221 |
+
<label for="isInvalidError">
|
222 |
+
پیغام زمانیکه کد ملی وارد شده مطابق با الگوی ملی نباشد
|
223 |
+
<?php gform_tooltip( "tooltip_isInvalidError" ); ?>
|
224 |
+
</label>
|
225 |
+
<input type="text" class="fieldwidth-3" id="isInvalidError" size="35"
|
226 |
+
onkeyup="SetFieldProperty('isInvalidError', this.value);"/>
|
227 |
+
<br/>
|
228 |
+
|
229 |
+
<br/>
|
230 |
+
<label for="duplicateError">
|
231 |
+
پیغام زمانیکه کد ملی وارد شده قبلا ثبت شده باشد
|
232 |
+
<?php gform_tooltip( "tooltip_duplicateError" ); ?>
|
233 |
+
</label>
|
234 |
+
<input type="text" class="fieldwidth-3" id="duplicateError" size="35"
|
235 |
+
onkeyup="SetFieldProperty('duplicateError', this.value);"/>
|
236 |
+
<br/>
|
237 |
+
</li>
|
238 |
+
<?php
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
public function frontend_script( $form, $ajax ) {
|
243 |
+
|
244 |
+
$flag_js = $flag_fn = false;
|
245 |
+
$fields = GFCommon::get_fields_by_type( $form, array( 'ir_national_id' ) );
|
246 |
+
|
247 |
+
foreach ( (array) $fields as $field ) {
|
248 |
+
|
249 |
+
$location = rgar( $field, 'showLocation', 0 ) ? 1 : 0;
|
250 |
+
$seperator = rgar( $field, 'showSeperator', 0 ) ? 1 : 0;
|
251 |
+
$forceEnglish = rgar( $field, 'forceEnglish', 0 ) ? 1 : 0;
|
252 |
+
|
253 |
+
if ( ! $flag_js && ( $location + $seperator ) ) {
|
254 |
+
|
255 |
+
$flag_js = true;
|
256 |
+
|
257 |
+
wp_dequeue_script( 'gform_ir_national_id' );
|
258 |
+
wp_deregister_script( 'gform_ir_national_id' );
|
259 |
+
|
260 |
+
wp_register_script( 'gform_ir_national_id', GF_PERSIAN_URL . 'assets/js/national_id.min.js', array(), GF_PERSIAN_VERSION, false );
|
261 |
+
wp_enqueue_script( 'gform_ir_national_id' );
|
262 |
+
}
|
263 |
+
?>
|
264 |
+
<script type="text/javascript">
|
265 |
+
<?php if ( ! $flag_fn && $forceEnglish) : ?>
|
266 |
+
function ir_national_id_to_english(number) {
|
267 |
+
return number.replace(/[۰|٠]/g, '0').replace(/[۱|١]/g, '1')
|
268 |
+
.replace(/[۲|٢]/g, '2').replace(/[۳|٣]/g, '3')
|
269 |
+
.replace(/[۴|٤]/g, '4').replace(/[۵|٥]/g, '5').replace(/[۶|٦]/g, '6')
|
270 |
+
.replace(/[۷|٧]/g, '7').replace(/[۸|٨]/g, '8').replace(/[۹|٩]/g, '9')
|
271 |
+
}
|
272 |
+
<?php $flag_fn = true; endif;?>
|
273 |
+
function ir_national_id_<?php echo $field['id']; ?>(_this) {
|
274 |
+
<?php if ( $forceEnglish ) : ?>
|
275 |
+
_this.value = ir_national_id_to_english(_this.value);
|
276 |
+
<?php endif;
|
277 |
+
if ( $location + $seperator ) : ?>
|
278 |
+
var field_id = "<?php echo $field['id'] ?>";
|
279 |
+
var message1 = "<?php echo rgar( $field, 'notDigitError', 'کد ملی فقط باید به صورت عدد وارد شود.' ); ?>";
|
280 |
+
var message2 = "<?php echo rgar( $field, 'qtyDigitError', 'کد ملی می بایست 10 رقمی باشد.' ); ?>";
|
281 |
+
var message3 = "<?php echo rgar( $field, 'isInvalidError', 'کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد.' ); ?>";
|
282 |
+
GFPersian_National_ID_Handler(_this, field_id, message1, message2, message3, <?php echo $seperator ?>, <?php echo $location ?>);
|
283 |
+
jQuery(_this).trigger('change');
|
284 |
+
<?php endif;?>
|
285 |
+
}
|
286 |
+
</script>
|
287 |
+
<?php
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
public function is_valid( $value = '' ) {
|
292 |
+
|
293 |
+
if ( ! empty( $value ) ) {
|
294 |
+
|
295 |
+
$_value = $value;
|
296 |
+
|
297 |
+
if ( strlen( $value ) == 8 ) {
|
298 |
+
$_value = '00' . $value;
|
299 |
+
}
|
300 |
+
|
301 |
+
if ( strlen( $value ) == 9 ) {
|
302 |
+
$_value = '0' . $value;
|
303 |
+
}
|
304 |
+
|
305 |
+
$pre_check = array(
|
306 |
+
'0000000000',
|
307 |
+
'1111111111',
|
308 |
+
'2222222222',
|
309 |
+
'3333333333',
|
310 |
+
'4444444444',
|
311 |
+
'5555555555',
|
312 |
+
'6666666666',
|
313 |
+
'7777777777',
|
314 |
+
'8888888888',
|
315 |
+
'9999999999',
|
316 |
+
'0123456789',
|
317 |
+
);
|
318 |
+
|
319 |
+
if ( in_array( $_value, $pre_check ) ) {
|
320 |
+
return 2;
|
321 |
+
}
|
322 |
+
|
323 |
+
if ( ! is_numeric( $value ) ) {
|
324 |
+
return 4;
|
325 |
+
}
|
326 |
+
|
327 |
+
$value = (string) preg_replace( '/[^0-9]/', '', $value );
|
328 |
+
|
329 |
+
if ( strlen( $value ) > 10 || strlen( $value ) < 8 ) {
|
330 |
+
return 3;
|
331 |
+
}
|
332 |
+
|
333 |
+
$value = $_value;
|
334 |
+
|
335 |
+
$list_code = str_split( $value );
|
336 |
+
$last = (int) $list_code[9];
|
337 |
+
unset( $list_code[9] );
|
338 |
+
|
339 |
+
$i = 10;
|
340 |
+
$sum = 0;
|
341 |
+
foreach ( $list_code as $key => $val ) {
|
342 |
+
$sum += intval( $val ) * $i;
|
343 |
+
$i --;
|
344 |
+
}
|
345 |
+
|
346 |
+
$mod = (int) $sum % 11;
|
347 |
+
|
348 |
+
if ( $mod >= 2 ) {
|
349 |
+
$mod = 11 - $mod;
|
350 |
+
}
|
351 |
+
if ( $mod != $last ) {
|
352 |
+
return 2;
|
353 |
+
} else {
|
354 |
+
return 1;
|
355 |
+
}
|
356 |
+
}
|
357 |
+
|
358 |
+
return false;
|
359 |
+
}
|
360 |
+
|
361 |
+
public function validator( $result, $value, $form, $field ) {
|
362 |
+
|
363 |
+
if ( $field['type'] == 'ir_national_id' ) {
|
364 |
+
|
365 |
+
$value = ! empty( $value ) ? str_replace( '-', '', $value ) : '';
|
366 |
+
$is_valid = $this->is_valid( $value );
|
367 |
+
|
368 |
+
if ( $is_valid == 4 ) {
|
369 |
+
$result['is_valid'] = false;
|
370 |
+
$result['message'] = rgar( $field, 'notDigitError', 'کد ملی فقط باید به صورت عدد وارد شود.' );
|
371 |
+
|
372 |
+
return $result;
|
373 |
+
}
|
374 |
+
|
375 |
+
if ( $is_valid == 3 ) {
|
376 |
+
$result['is_valid'] = false;
|
377 |
+
$result['message'] = rgar( $field, 'qtyDigitError', 'کد ملی می بایست 10 رقمی باشد. تنها در صورتی مجاز به استفاده از کد های 8 یا 9 رقمی هستید که ارقام سمت چپ 0 باشند.' );
|
378 |
+
|
379 |
+
return $result;
|
380 |
+
}
|
381 |
+
|
382 |
+
if ( $is_valid == 2 ) {
|
383 |
+
$result['is_valid'] = false;
|
384 |
+
$result['message'] = rgar( $field, 'isInvalidError', 'کد ملی وارد شده مطابق با استانداردهای کشور نمی باشد.' );
|
385 |
+
|
386 |
+
return $result;
|
387 |
+
}
|
388 |
+
|
389 |
+
if ( $field['noDuplicates'] ) {
|
390 |
+
|
391 |
+
if ( strlen( $value ) == 8 ) {
|
392 |
+
$value = '00' . $value;
|
393 |
+
}
|
394 |
+
|
395 |
+
if ( strlen( $value ) == 9 ) {
|
396 |
+
$value = '0' . $value;
|
397 |
+
}
|
398 |
+
|
399 |
+
if ( RGFormsModel::is_duplicate( $form['id'], $field, $value ) ) {
|
400 |
+
$result['is_valid'] = false;
|
401 |
+
$result['message'] = rgar( $field, 'duplicateError', 'این کد ملی توسط فرد دیگری ثبت شده است.' );
|
402 |
+
|
403 |
+
return $result;
|
404 |
+
}
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
return $result;
|
409 |
+
}
|
410 |
+
|
411 |
+
public function pre_submission( $form ) {
|
412 |
+
|
413 |
+
$ir_national_id_fields = GFCommon::get_fields_by_type( $form, array( 'ir_national_id' ) );
|
414 |
+
|
415 |
+
foreach ( (array) $ir_national_id_fields as $field ) {
|
416 |
+
|
417 |
+
$input_name = "input_{$field['id']}";
|
418 |
+
$input_value = rgpost( $input_name );
|
419 |
+
|
420 |
+
if ( ! empty( $input_value ) ) {
|
421 |
+
|
422 |
+
if ( strlen( $input_value ) == 8 ) {
|
423 |
+
$_POST["input_{$field['id']}"] = '00' . $input_value;
|
424 |
+
} elseif ( strlen( $input_value ) == 9 ) {
|
425 |
+
$_POST["input_{$field['id']}"] = '0' . $input_value;
|
426 |
+
} else {
|
427 |
+
$_POST["input_{$field['id']}"] = $input_value;
|
428 |
+
}
|
429 |
+
}
|
430 |
+
}
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
new GFPersian_National_ID();
|
includes/class-news-letter.php
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php if ( ! defined('ABSPATH') ) exit;
|
2 |
-
|
3 |
-
class GFParsi_Newsletter {
|
4 |
-
|
5 |
-
private static $instance = null;
|
6 |
-
|
7 |
-
public static function get_instance() {
|
8 |
-
if( null == self::$instance )
|
9 |
-
self::$instance = new self;
|
10 |
-
return self::$instance;
|
11 |
-
}
|
12 |
-
|
13 |
-
private function __construct() {
|
14 |
-
add_filter( 'gform_notification_events', array( $this, 'add_manual_notification_event' ) );
|
15 |
-
add_filter( 'gform_before_resend_notifications', array( $this, 'add_notification_filter' ) );
|
16 |
-
}
|
17 |
-
|
18 |
-
public function add_notification_filter( $form ) {
|
19 |
-
add_filter( 'gform_notification', array( $this, 'evaluate_notification_conditional_logic' ), 10, 3 );
|
20 |
-
return $form;
|
21 |
-
}
|
22 |
-
|
23 |
-
public function add_manual_notification_event( $events ) {
|
24 |
-
$events['manual'] = __( 'Newsletter', 'GF_FA' );
|
25 |
-
return $events;
|
26 |
-
}
|
27 |
-
|
28 |
-
public function evaluate_notification_conditional_logic( $notification, $form, $entry ) {
|
29 |
-
|
30 |
-
// if it fails conditional logic, suppress it
|
31 |
-
if( $notification['event'] == 'manual' && ! GFCommon::evaluate_conditional_logic( rgar( $notification, 'conditionalLogic' ), $form, $entry ) ) {
|
32 |
-
add_filter( 'gform_pre_send_email', array( $this, 'abort_next_notification' ) );
|
33 |
-
}
|
34 |
-
|
35 |
-
return $notification;
|
36 |
-
}
|
37 |
-
|
38 |
-
public function abort_next_notification( $args ) {
|
39 |
-
remove_filter( 'gform_pre_send_email', array( $this, 'abort_next_notification' ) );
|
40 |
-
$args['abort_email'] = true;
|
41 |
-
return $args;
|
42 |
-
}
|
43 |
-
|
44 |
-
}
|
45 |
-
|
46 |
-
function GFParsi_Newsletter() {
|
47 |
-
return GFParsi_Newsletter::get_instance();
|
48 |
-
}
|
49 |
-
|
50 |
-
GFParsi_Newsletter();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-payments.php
ADDED
@@ -0,0 +1,499 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Payments extends GFPersian_Core {
|
6 |
+
|
7 |
+
public function __construct() {
|
8 |
+
|
9 |
+
if ( $this->option( 'payments', '1' ) != '1' ) {
|
10 |
+
return;
|
11 |
+
}
|
12 |
+
|
13 |
+
$version = self::get_gform_version();
|
14 |
+
if ( version_compare( $version, '2.3-dev-1', '>=' ) ) {
|
15 |
+
add_filter( 'gform_is_duplicate', array( $this, 'better_noDuplicate_2_3_dev_1' ), 10, 4 );
|
16 |
+
} elseif ( class_exists( 'GFParsi' ) ) {
|
17 |
+
GFParsi::better_noDuplicate_hook( $version );
|
18 |
+
}
|
19 |
+
|
20 |
+
add_filter( 'gform_payment_status', array( $this, 'payment_status_entry' ) );
|
21 |
+
add_action( 'gform_entries_first_column', array( $this, 'payment_detail_entries' ), 10, 5 );
|
22 |
+
add_filter( 'admin_print_footer_scripts', array( $this, 'payment_status_conditional_logic' ) );
|
23 |
+
|
24 |
+
add_action( 'gform_notification_ui_settings', array( $this, 'payment_status_hint' ), 10, 3 );
|
25 |
+
add_action( 'gform_confirmation_ui_settings', array( $this, 'payment_status_hint' ), 10, 3 );
|
26 |
+
|
27 |
+
add_filter( 'gform_entry_meta', array( $this, 'gform_entry_meta' ) );
|
28 |
+
add_filter( 'gform_is_value_match', array( $this, 'is_value_match' ), 10, 6 );
|
29 |
+
}
|
30 |
+
|
31 |
+
public static function _payment_status( $entry, $only_name = false, $status = '' ) {
|
32 |
+
|
33 |
+
$status = ! empty( $status ) ? $status : rgar( $entry, 'payment_status' );
|
34 |
+
|
35 |
+
$status = ucfirst( $status );
|
36 |
+
|
37 |
+
if ( in_array( $status, array( 'Completed', 'Paid', 'Active', 'Approved' ) ) ) {
|
38 |
+
$status = array( '#3d804c', 'موفق' );
|
39 |
+
|
40 |
+
} elseif ( $status == 'Failed' ) {
|
41 |
+
$status = array( '#ff4b44', 'ناموفق' );
|
42 |
+
|
43 |
+
} elseif ( $status == 'Cancelled' ) {
|
44 |
+
$status = array( '#FFA500', 'منصرف شده' );
|
45 |
+
|
46 |
+
} elseif ( ! empty( $status ) ) {
|
47 |
+
$status = array( '#3399FF', 'در انتظار پرداخت' );
|
48 |
+
|
49 |
+
} else {
|
50 |
+
$status = array();
|
51 |
+
}
|
52 |
+
|
53 |
+
if ( empty( $status[0] ) || empty( $status[1] ) ) {
|
54 |
+
return '';
|
55 |
+
}
|
56 |
+
|
57 |
+
if ( $only_name ) {
|
58 |
+
return $status[1];
|
59 |
+
}
|
60 |
+
|
61 |
+
return "<span style='color: {$status[0]}'>{$status[1]}</span>";
|
62 |
+
}
|
63 |
+
|
64 |
+
public function payment_status_entry( $status ) {
|
65 |
+
|
66 |
+
if ( GFCommon::is_entry_detail() ) {
|
67 |
+
$status = self::_payment_status( '', false, $status );
|
68 |
+
}
|
69 |
+
|
70 |
+
return $status;
|
71 |
+
}
|
72 |
+
|
73 |
+
public function payment_detail_entries( $form_id, $field_id, $value, $entry, $query_string ) {
|
74 |
+
|
75 |
+
$url = remove_query_arg( array( 's', 'field_id', 'operator' ) );
|
76 |
+
$urls = array();
|
77 |
+
|
78 |
+
$status = self::_payment_status( $entry );
|
79 |
+
if ( ! empty( $status ) ) {
|
80 |
+
|
81 |
+
$url = add_query_arg( array(
|
82 |
+
's' => ucfirst( rgar( $entry, 'payment_status' ) ),
|
83 |
+
'field_id' => 'payment_status',
|
84 |
+
'operator' => 'is'
|
85 |
+
), $url );
|
86 |
+
|
87 |
+
$urls[] = '<a href="' . $url . '"> ' . $status . ' </a>';
|
88 |
+
}
|
89 |
+
|
90 |
+
$gateway = gform_get_meta( rgar( $entry, 'id' ), 'payment_gateway' );
|
91 |
+
if ( ! empty( $gateway ) ) {
|
92 |
+
$url = add_query_arg( array(
|
93 |
+
's' => $gateway,
|
94 |
+
'field_id' => 'payment_gateway',
|
95 |
+
'operator' => 'is'
|
96 |
+
), $url );
|
97 |
+
$urls[] = '<a href="' . $url . '" style="color:black"> ' . $gateway . ' </a>';
|
98 |
+
}
|
99 |
+
|
100 |
+
if ( ! empty( $urls ) ) {
|
101 |
+
echo implode( ' - ', $urls );
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
public function better_noDuplicate_2_3_dev_1( $count, $form_id, $field, $value ) {
|
106 |
+
|
107 |
+
global $wpdb;
|
108 |
+
|
109 |
+
$entry_meta_table_name = GFFormsModel::get_entry_meta_table_name();
|
110 |
+
$entry_table_name = GFFormsModel::get_entry_table_name();
|
111 |
+
|
112 |
+
switch ( GFFormsModel::get_input_type( $field ) ) {
|
113 |
+
case 'time':
|
114 |
+
$value = sprintf( "%02d:%02d %s", $value[0], $value[1], $value[2] );
|
115 |
+
break;
|
116 |
+
case 'date':
|
117 |
+
$value = GFFormsModel::prepare_date( $field->dateFormat, $value );
|
118 |
+
break;
|
119 |
+
case 'number':
|
120 |
+
$value = GFCommon::clean_number( $value, $field->numberFormat );
|
121 |
+
break;
|
122 |
+
case 'phone':
|
123 |
+
$value = str_replace( array( ')', '(', '-', ' ' ), '', $value );
|
124 |
+
$sql_comparison = 'replace( replace( replace( replace( ld.value, ")", "" ), "(", "" ), "-", "" ), " ", "" ) = %s';
|
125 |
+
break;
|
126 |
+
case 'email':
|
127 |
+
$value = is_array( $value ) ? rgar( $value, 0 ) : $value;
|
128 |
+
break;
|
129 |
+
}
|
130 |
+
|
131 |
+
$inner_sql_template = "SELECT %s as input, ld.entry_id
|
132 |
+
FROM {$entry_meta_table_name} ld
|
133 |
+
INNER JOIN {$entry_table_name} l ON l.id = ld.entry_id\n";
|
134 |
+
|
135 |
+
|
136 |
+
$inner_sql_template .= "WHERE l.form_id=%d AND ld.form_id=%d
|
137 |
+
AND ld.meta_key = %s
|
138 |
+
AND (payment_status IS NULL OR LOWER(payment_status) IN ('', 'approved', 'approve', 'completed', 'complete', 'actived', 'active', 'paid'))
|
139 |
+
AND status='active' AND ld.meta_value = %s";
|
140 |
+
|
141 |
+
$sql = "SELECT count(distinct input) as match_count FROM ( ";
|
142 |
+
|
143 |
+
$input_count = 1;
|
144 |
+
if ( is_array( $field->get_entry_inputs() ) ) {
|
145 |
+
$input_count = sizeof( $field->inputs );
|
146 |
+
$inner_sql = '';
|
147 |
+
foreach ( $field->inputs as $input ) {
|
148 |
+
$union = empty( $inner_sql ) ? '' : ' UNION ALL ';
|
149 |
+
$inner_sql .= $union . $wpdb->prepare( $inner_sql_template, $input['id'], $form_id, $form_id, $input['id'], $value[ $input['id'] ] );
|
150 |
+
}
|
151 |
+
} else {
|
152 |
+
$inner_sql = $wpdb->prepare( $inner_sql_template, $field->id, $form_id, $form_id, $field->id, $value );
|
153 |
+
}
|
154 |
+
|
155 |
+
$sql .= $inner_sql . "
|
156 |
+
) as count
|
157 |
+
GROUP BY entry_id
|
158 |
+
ORDER BY match_count DESC";
|
159 |
+
|
160 |
+
$count = gf_apply_filters( array(
|
161 |
+
'gform_is_duplicate_better',
|
162 |
+
$form_id
|
163 |
+
), $wpdb->get_var( $sql ), $form_id, $field, $value );
|
164 |
+
|
165 |
+
return $count != null && $count >= $input_count;
|
166 |
+
}
|
167 |
+
|
168 |
+
/*-----------------------------------------------------------------------------------*/
|
169 |
+
/*-----------------------------------------------------------------------------------*/
|
170 |
+
/*-----------------------------------------------------------------------------------*/
|
171 |
+
/*-----------------------------------------------------------------------------------*/
|
172 |
+
|
173 |
+
public function payment_status_hint( $ui_settings, $notif_confirm, $form ) {
|
174 |
+
|
175 |
+
if ( ! empty( rgar( $notif_confirm, 'isDefault' ) ) ) {
|
176 |
+
return $ui_settings;
|
177 |
+
}
|
178 |
+
|
179 |
+
$current_action = current_action();
|
180 |
+
if ( stripos( $current_action, 'confirmation' ) !== false ) {
|
181 |
+
$current_action = 'تاییدیه';
|
182 |
+
} else {
|
183 |
+
$current_action = 'اعلان';
|
184 |
+
}
|
185 |
+
|
186 |
+
$ui_settings['payment_status_hint'] = '
|
187 |
+
<tr>
|
188 |
+
<th><label for="stickylist_confirmation_type">وضعیت پرداخت</label></th>
|
189 |
+
<td>' . sprintf( 'برای محدود کردن این %s به وضعیت پرداخت های مورد نظر، از طریق منطق شرطی بالا وضعیت پرداخت مورد نظر را ست نمایید. توجه نمایید که همه درگاه های پرداخت از وضعیت "انصرافی" پشتیبانی نمیکنند. ضمن اینکه نسخه درگاه پرداخت ایرانی شما باید حداقل 2.3 باشد.', $current_action ) . '</td>
|
190 |
+
</tr>';
|
191 |
+
|
192 |
+
return $ui_settings;
|
193 |
+
}
|
194 |
+
|
195 |
+
public function payment_status_conditional_logic() {
|
196 |
+
|
197 |
+
if ( ! $this->is_gravity_page() || ! in_array( rgget( 'subview' ), array( 'confirmation', 'notification' ) ) ) {
|
198 |
+
return;
|
199 |
+
}
|
200 |
+
?>
|
201 |
+
|
202 |
+
<script type="text/javascript">
|
203 |
+
if (window.gform) {
|
204 |
+
gform.addFilter('gform_conditional_logic_fields', function (options, form, selectedFieldId) {
|
205 |
+
options.push({
|
206 |
+
label: 'وضعیت پرداخت',
|
207 |
+
value: 'payment_status'
|
208 |
+
});
|
209 |
+
return options;
|
210 |
+
});
|
211 |
+
jQuery(document).ready(function ($) {
|
212 |
+
var $InputsRefreshTimeout = false;
|
213 |
+
var baseSelector = '.gf_conditional_logic_rules_container';
|
214 |
+
$(document).bind('gform_load_field_settings', function (event, field) {
|
215 |
+
$(document).find(baseSelector + ' select[id*="_rule_field_"]').each(function () {
|
216 |
+
ConditionalLogicPaymentStatus($(this));
|
217 |
+
});
|
218 |
+
});
|
219 |
+
$(document).on('change', baseSelector + ' select[id*="_rule_field_"]', function () {
|
220 |
+
ConditionalLogicPaymentStatus($(this));
|
221 |
+
});
|
222 |
+
$(document).on('change', baseSelector + ' select[id*="_rule_operator_"]', function () {
|
223 |
+
ConditionalLogicPaymentStatus($(this).prev('select'));
|
224 |
+
});
|
225 |
+
$(document).on('change', baseSelector + ' .add_field_choice', function () {
|
226 |
+
delayedRefreshPaymentStatusInputs();
|
227 |
+
});
|
228 |
+
gform.addFilter('gform_conditional_logic_values_input', function (fields) {
|
229 |
+
delayedRefreshPaymentStatusInputs();
|
230 |
+
return fields;
|
231 |
+
});
|
232 |
+
|
233 |
+
function delayedRefreshPaymentStatusInputs() {
|
234 |
+
$InputsRefreshTimeout = setTimeout(function () {
|
235 |
+
$(document).find(baseSelector + ' select[id*="_rule_field_"]').each(function () {
|
236 |
+
ConditionalLogicPaymentStatus($(this));
|
237 |
+
});
|
238 |
+
}, 10);
|
239 |
+
}
|
240 |
+
|
241 |
+
function ConditionalLogicPaymentStatus($select) {
|
242 |
+
var value = $select.val();
|
243 |
+
if (value == 'payment_status') {
|
244 |
+
var $_input,
|
245 |
+
bits = $select.attr('id').split('_'),
|
246 |
+
index = bits[bits.length - 1],
|
247 |
+
prep = bits.indexOf('rule'),
|
248 |
+
prefix = bits.slice(0, prep).join('_'),
|
249 |
+
$input = $('#{0}_rule_value_{1}'.format(prefix, index)),
|
250 |
+
$operator = $('#{0}_rule_operator_{1}'.format(prefix, index));
|
251 |
+
$operator.find(":not(option[value^='is'])").each(function () {
|
252 |
+
$(this).remove();
|
253 |
+
});
|
254 |
+
var input_value, input_name, input_id;
|
255 |
+
input_value = 'completed';
|
256 |
+
if (typeof $input.val() != 'undefined' && $input.val().length)
|
257 |
+
input_value = $input.val();
|
258 |
+
if (typeof $input.attr('id') != 'undefined')
|
259 |
+
input_id = $input.attr('id');
|
260 |
+
else
|
261 |
+
input_id = $operator.attr('id').replace('operator', 'value');
|
262 |
+
if (typeof $input.attr('name') != 'undefined')
|
263 |
+
input_name = $input.attr('name');
|
264 |
+
else
|
265 |
+
input_name = input_id;
|
266 |
+
var options = '<option value="completed">موفق</option>';
|
267 |
+
options += '<option value="failed">ناموفق</option>';
|
268 |
+
options += '<option value="cancelled">انصرافی</option>';
|
269 |
+
options = options.replace(/ selected="selected"/g, '');
|
270 |
+
options = options.replace("value=\"" + input_value + "\"", "value=\"" + input_value + "\" selected=\"selected\"");
|
271 |
+
if (typeof $input[0] == 'undefined') {
|
272 |
+
$operator.after('<input id="paymetn_statuses_temp"/>');
|
273 |
+
$_input = $('#paymetn_statuses_temp')[0];
|
274 |
+
} else {
|
275 |
+
$_input = $input[0];
|
276 |
+
}
|
277 |
+
$_input.outerHTML = "<select value='" + input_value + "' id='" + input_id + "' name='" + input_name + "' class='gfield_rule_select gfield_rule_value_dropdown'>" + options + "</select>";
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
delayedRefreshPaymentStatusInputs();
|
282 |
+
});
|
283 |
+
}
|
284 |
+
</script>
|
285 |
+
<?php
|
286 |
+
}
|
287 |
+
|
288 |
+
public function gform_entry_meta( $metas ) {
|
289 |
+
$metas['payment_status'] = 'payment_status';
|
290 |
+
|
291 |
+
return $metas;
|
292 |
+
}
|
293 |
+
|
294 |
+
public function is_value_match( $is_match, $field_value/*entry['payment_status']*/, $rule_value, $rule_operator, $source_field = null, $rule ) {
|
295 |
+
|
296 |
+
if ( $rule['fieldId'] == 'payment_status' ) {
|
297 |
+
|
298 |
+
$field_value = strtolower( $field_value );
|
299 |
+
|
300 |
+
if ( in_array( $field_value, array( 'completed', 'paid', 'active', 'approved' ) ) ) {
|
301 |
+
$field_value = 'completed';
|
302 |
+
}
|
303 |
+
|
304 |
+
$rule_value = ! empty( $rule_value ) ? $rule_value : 'completed';
|
305 |
+
|
306 |
+
remove_filter( 'gform_is_value_match', array( $this, __FUNCTION__ ) );
|
307 |
+
$is_match = GFFormsModel::is_value_match( $field_value, $rule_value, $rule_operator );
|
308 |
+
add_filter( 'gform_is_value_match', array( $this, __FUNCTION__ ), 10, 6 );
|
309 |
+
}
|
310 |
+
|
311 |
+
return $is_match;
|
312 |
+
}
|
313 |
+
/*-----------------------------------------------------------------------------------*/
|
314 |
+
/*-----------------------------------------------------------------------------------*/
|
315 |
+
/*-----------------------------------------------------------------------------------*/
|
316 |
+
/*-----------------------------------------------------------------------------------*/
|
317 |
+
public static function notification( $form, $entry ) {
|
318 |
+
$entry = GFAPI::get_entry( rgar( $entry, 'id' ) );
|
319 |
+
$notifications = GFCommon::get_notifications_to_send( 'form_submission', $form, $entry );
|
320 |
+
$_notifications = array();
|
321 |
+
foreach ( (array) $notifications as $notification ) {
|
322 |
+
$logic = rgar( $notification, 'conditionalLogic' );
|
323 |
+
$rules = rgar( $logic, 'rules' );
|
324 |
+
if ( empty( $rules ) ) {
|
325 |
+
continue;
|
326 |
+
}
|
327 |
+
$fieldIds = wp_list_pluck( $rules, 'fieldId' );
|
328 |
+
if ( in_array( 'payment_status', $fieldIds ) ) {
|
329 |
+
$_notifications[] = $notification;
|
330 |
+
}
|
331 |
+
}
|
332 |
+
if ( ! empty( $_notifications ) ) {
|
333 |
+
$_notifications = wp_list_pluck( $_notifications, 'id' );
|
334 |
+
GFCommon::send_notifications( $_notifications, $form, $entry );
|
335 |
+
}
|
336 |
+
}
|
337 |
+
|
338 |
+
public static function confirmation( $form, $entry, $fault ) {
|
339 |
+
|
340 |
+
if ( ! class_exists( "GFFormDisplay" ) ) {
|
341 |
+
require_once( GFCommon::get_base_path() . "/form_display.php" );
|
342 |
+
}
|
343 |
+
|
344 |
+
$entry = GFAPI::get_entry( rgar( $entry, 'id' ) );
|
345 |
+
$confirmation = GFFormDisplay::handle_confirmation( $form, $entry );
|
346 |
+
if ( is_array( $confirmation ) && isset( $confirmation["redirect"] ) ) {
|
347 |
+
header( "Location: {$confirmation["redirect"]}" );
|
348 |
+
exit;
|
349 |
+
}
|
350 |
+
$fault = ! empty( $fault ) ? $fault : '';
|
351 |
+
$confirmation = str_ireplace( '{fault}', $fault, $confirmation );
|
352 |
+
GFFormDisplay::$submission[ $form['id'] ] = array(
|
353 |
+
"is_confirmation" => true,
|
354 |
+
"confirmation_message" => $confirmation,
|
355 |
+
"form" => $form,
|
356 |
+
"entry" => $entry,
|
357 |
+
"lead" => $entry
|
358 |
+
);
|
359 |
+
}
|
360 |
+
|
361 |
+
public static function currency( $entry = '', $form = '' ) {
|
362 |
+
|
363 |
+
if ( is_numeric( $entry ) ) {
|
364 |
+
$entry = GFAPI::get_entry( $entry );
|
365 |
+
}
|
366 |
+
|
367 |
+
if ( rgar( $entry, 'currency' ) ) {
|
368 |
+
return rgar( $entry, 'currency' );
|
369 |
+
}
|
370 |
+
|
371 |
+
if ( is_numeric( $form ) ) {
|
372 |
+
$form = GFAPI::get_form( $form );
|
373 |
+
}
|
374 |
+
|
375 |
+
if ( rgar( $form, 'currency' ) ) {
|
376 |
+
return rgar( $form, 'currency' );
|
377 |
+
}
|
378 |
+
|
379 |
+
return GFCommon::get_currency();
|
380 |
+
}
|
381 |
+
|
382 |
+
public static function amount( $amount, $to_currency = 'IRR', $entry = '', $form = '' ) {
|
383 |
+
|
384 |
+
$currency = self::currency( $entry, $form );
|
385 |
+
|
386 |
+
if ( in_array( $currency, array( 'IRHR', 'IRHT' ) ) ) {
|
387 |
+
$currency = str_ireplace( 'H', '', $currency );
|
388 |
+
$amount *= 1000;
|
389 |
+
}
|
390 |
+
|
391 |
+
if ( $currency == 'IRR' && $to_currency == 'IRT' ) {
|
392 |
+
$amount /= 10;
|
393 |
+
}
|
394 |
+
|
395 |
+
if ( $currency == 'IRT' && $to_currency == 'IRR' ) {
|
396 |
+
$amount *= 10;
|
397 |
+
}
|
398 |
+
|
399 |
+
return $amount;
|
400 |
+
}
|
401 |
+
|
402 |
+
public static function check_verification( $entry, $gateway, $params ) {
|
403 |
+
|
404 |
+
if ( empty( $params ) || trim( $params ) == '' ) {
|
405 |
+
return false;
|
406 |
+
}
|
407 |
+
|
408 |
+
$params = self::params_verification( $gateway, $params );
|
409 |
+
|
410 |
+
$table_name = '';
|
411 |
+
if ( method_exists( 'GFFormsModel', 'get_lead_meta_table_name' ) ) {
|
412 |
+
$table_name = GFFormsModel::get_lead_meta_table_name();
|
413 |
+
}
|
414 |
+
if ( version_compare( self::get_gform_version(), '2.3-dev-1', '>=' ) ) {
|
415 |
+
if ( method_exists( 'GFFormsModel', 'get_entry_meta_table_name' ) ) {
|
416 |
+
$table_name = GFFormsModel::get_entry_meta_table_name();
|
417 |
+
}
|
418 |
+
}
|
419 |
+
|
420 |
+
if ( ! empty( $table_name ) ) {
|
421 |
+
|
422 |
+
global $wpdb;
|
423 |
+
$check = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table_name} WHERE meta_key='_verification_params' AND meta_value='%s'", $params ) );
|
424 |
+
|
425 |
+
if ( ! empty( $check ) ) {
|
426 |
+
|
427 |
+
if ( is_numeric( $entry ) ) {
|
428 |
+
$entry = GFAPI::get_entry( $entry );
|
429 |
+
}
|
430 |
+
|
431 |
+
$entry["payment_date"] = gmdate( "Y-m-d H:i:s" );
|
432 |
+
$entry["payment_status"] = "Failed";
|
433 |
+
$entry["payment_amount"] = 0;
|
434 |
+
$entry["is_fulfilled"] = 0;
|
435 |
+
GFAPI::update_entry( $entry );
|
436 |
+
|
437 |
+
global $current_user;
|
438 |
+
$user_id = 0;
|
439 |
+
$user_name = 'مهمان';
|
440 |
+
if ( $current_user && $user_data = get_userdata( $current_user->ID ) ) {
|
441 |
+
$user_id = $current_user->ID;
|
442 |
+
$user_name = $user_data->display_name;
|
443 |
+
}
|
444 |
+
|
445 |
+
$Message = 'تراکنش ناموفق ::: نتیجه تراکنش قبلا مشخص شده بود و تراکنش دوباره تکرار شد.';
|
446 |
+
|
447 |
+
RGFormsModel::add_note( $entry["id"], $user_id, $user_name, $Message );
|
448 |
+
|
449 |
+
$form = GFAPI::get_form( rgar( $entry, 'form_id' ) );
|
450 |
+
|
451 |
+
self::notification( $form, $entry );
|
452 |
+
self::confirmation( $form, $entry, $Message );
|
453 |
+
|
454 |
+
return true;
|
455 |
+
}
|
456 |
+
}
|
457 |
+
|
458 |
+
return false;
|
459 |
+
}
|
460 |
+
|
461 |
+
public static function set_verification( $entry, $gateway, $params ) {
|
462 |
+
|
463 |
+
if ( empty( $params ) || trim( $params ) == '' ) {
|
464 |
+
return false;
|
465 |
+
}
|
466 |
+
|
467 |
+
if ( ! is_numeric( $entry ) ) {
|
468 |
+
$entry = rgar( $entry, 'id' );
|
469 |
+
}
|
470 |
+
|
471 |
+
$params = self::params_verification( $gateway, $params );
|
472 |
+
|
473 |
+
gform_update_meta( $entry, '_verification_params', $params );
|
474 |
+
}
|
475 |
+
|
476 |
+
private static function params_verification( $gateway, $params ) {
|
477 |
+
if ( is_array( $params ) || is_object( $params ) ) {
|
478 |
+
$params = implode( '_', (array) $params );
|
479 |
+
}
|
480 |
+
|
481 |
+
return trim( $gateway . '_' . $params );
|
482 |
+
}
|
483 |
+
|
484 |
+
private static function get_gform_version() {
|
485 |
+
$version = GFCommon::$version;
|
486 |
+
if ( method_exists( 'GFFormsModel', 'get_database_version' ) ) {
|
487 |
+
$version = GFFormsModel::get_database_version();
|
488 |
+
}
|
489 |
+
|
490 |
+
return $version;
|
491 |
+
}
|
492 |
+
|
493 |
+
public static function nusoap() {
|
494 |
+
require_once 'lib/nusoap.php';
|
495 |
+
}
|
496 |
+
|
497 |
+
}
|
498 |
+
|
499 |
+
new GFPersian_Payments;
|
includes/class-post-content-merge-tags.php
DELETED
@@ -1,249 +0,0 @@
|
|
1 |
-
<?php if ( ! defined('ABSPATH') ) exit;
|
2 |
-
|
3 |
-
class GFParsi_Post_Content_Merge_Tags {
|
4 |
-
|
5 |
-
public static $_entry = null;
|
6 |
-
|
7 |
-
private static $instance = null;
|
8 |
-
|
9 |
-
public static function get_instance( $args = array() ) {
|
10 |
-
|
11 |
-
if( self::$instance == null )
|
12 |
-
self::$instance = new self( $args );
|
13 |
-
|
14 |
-
return self::$instance;
|
15 |
-
}
|
16 |
-
|
17 |
-
function __construct( $args ) {
|
18 |
-
|
19 |
-
if( ! class_exists( 'GFForms' ) )
|
20 |
-
return;
|
21 |
-
|
22 |
-
$this->_args = wp_parse_args( $args, array(
|
23 |
-
'auto_append_lead' => true, // true, false or array of form IDs
|
24 |
-
'encrypt_lead' => false,
|
25 |
-
) );
|
26 |
-
|
27 |
-
add_filter( 'the_content', array( $this, 'replace_merge_tags' ), 1 );
|
28 |
-
add_filter( 'gform_replace_merge_tags', array( $this, 'replace_encrypt_entry_id_merge_tag' ), 10, 3 );
|
29 |
-
|
30 |
-
if( ! empty( $this->_args['auto_append_lead'] ) ) {
|
31 |
-
add_filter( 'gform_confirmation', array( $this, 'append_lead_parameter' ), 20, 3 );
|
32 |
-
}
|
33 |
-
|
34 |
-
}
|
35 |
-
|
36 |
-
function replace_merge_tags( $post_content ) {
|
37 |
-
|
38 |
-
$entry = $this->get_entry();
|
39 |
-
if( ! $entry )
|
40 |
-
return $this->replace_field_label_merge_tags( $post_content, '' );
|
41 |
-
|
42 |
-
|
43 |
-
$confirm_time = gform_get_meta( rgar($entry,'id') , 'gform_page_confirm_time');
|
44 |
-
|
45 |
-
if ( !empty($confirm_time) && $confirm_time + 90 < time() )
|
46 |
-
return $this->replace_field_label_merge_tags( $post_content, '' );
|
47 |
-
|
48 |
-
if (empty($confirm_time))
|
49 |
-
gform_update_meta($entry['id'], 'gform_page_confirm_time', time() );
|
50 |
-
|
51 |
-
$form = GFFormsModel::get_form_meta( $entry['form_id'] );
|
52 |
-
|
53 |
-
$post_content = $this->replace_field_label_merge_tags( $post_content, $form );
|
54 |
-
$post_content = GFCommon::replace_variables( $post_content, $form, $entry, false, false, false );
|
55 |
-
|
56 |
-
return $post_content;
|
57 |
-
}
|
58 |
-
|
59 |
-
function replace_field_label_merge_tags( $text, $form ) {
|
60 |
-
|
61 |
-
if ( !empty($form) ) {
|
62 |
-
|
63 |
-
preg_match_all( '/{([^:]+?)}/', $text, $matches, PREG_SET_ORDER );
|
64 |
-
if( empty( $matches ) )
|
65 |
-
return $text;
|
66 |
-
|
67 |
-
foreach( $matches as $match ) {
|
68 |
-
|
69 |
-
list( $search, $field_label ) = $match;
|
70 |
-
|
71 |
-
foreach( $form['fields'] as $field ) {
|
72 |
-
|
73 |
-
$full_input_id = false;
|
74 |
-
$matches_admin_label = rgar( $field, 'adminLabel' ) == $field_label;
|
75 |
-
$matches_field_label = false;
|
76 |
-
|
77 |
-
if( is_array( $field['inputs'] ) ) {
|
78 |
-
foreach( $field['inputs'] as $input ) {
|
79 |
-
if( GFFormsModel::get_label( $field, $input['id'] ) == $field_label ) {
|
80 |
-
$matches_field_label = true;
|
81 |
-
$input_id = $input['id'];
|
82 |
-
break;
|
83 |
-
}
|
84 |
-
}
|
85 |
-
} else {
|
86 |
-
$matches_field_label = GFFormsModel::get_label( $field ) == $field_label;
|
87 |
-
$input_id = $field['id'];
|
88 |
-
}
|
89 |
-
|
90 |
-
if( ! $matches_admin_label && ! $matches_field_label )
|
91 |
-
continue;
|
92 |
-
|
93 |
-
$replace = sprintf( '{%s:%s}', $field_label, (string) $input_id );
|
94 |
-
$text = str_replace( $search, $replace, $text );
|
95 |
-
|
96 |
-
break;
|
97 |
-
}
|
98 |
-
}
|
99 |
-
}
|
100 |
-
else {
|
101 |
-
|
102 |
-
/*
|
103 |
-
preg_match_all( '/{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/mi', $text, $matches, PREG_SET_ORDER );
|
104 |
-
if( !empty( $matches ) ) {
|
105 |
-
foreach( $matches as $match ) {
|
106 |
-
if ( isset($match[0]))
|
107 |
-
$text = str_replace( $match[0], '' , $text );
|
108 |
-
}
|
109 |
-
}
|
110 |
-
|
111 |
-
unset($matches);
|
112 |
-
|
113 |
-
preg_match_all( '/{([^:]+?)}/', $text, $matches, PREG_SET_ORDER );
|
114 |
-
if( !empty( $matches ) ) {
|
115 |
-
foreach( $matches as $match ) {
|
116 |
-
if ( isset($match[0]))
|
117 |
-
$text = str_replace( $match[0], '' , $text );
|
118 |
-
}
|
119 |
-
}
|
120 |
-
*/
|
121 |
-
|
122 |
-
}
|
123 |
-
|
124 |
-
return $text;
|
125 |
-
}
|
126 |
-
|
127 |
-
function replace_encrypt_entry_id_merge_tag( $text, $form, $entry ) {
|
128 |
-
|
129 |
-
if( strpos( $text, '{encrypted_entry_id}' ) === false ) {
|
130 |
-
return $text;
|
131 |
-
}
|
132 |
-
|
133 |
-
// $entry is not always a "full" entry
|
134 |
-
$entry_id = rgar( $entry, 'id' );
|
135 |
-
if( $entry_id ) {
|
136 |
-
$entry_id = $this->prepare_lead( $entry['id'], true );
|
137 |
-
}
|
138 |
-
|
139 |
-
return str_replace( '{encrypted_entry_id}', $entry_id, $text );
|
140 |
-
}
|
141 |
-
|
142 |
-
function append_lead_parameter( $confirmation, $form, $entry ) {
|
143 |
-
|
144 |
-
$is_ajax_redirect = is_string( $confirmation ) && strpos( $confirmation, 'gformRedirect' );
|
145 |
-
$is_redirect = is_array( $confirmation ) && isset( $confirmation['redirect'] );
|
146 |
-
|
147 |
-
if( ! $this->is_auto_lead_enabled( $form ) || ! ( $is_ajax_redirect || $is_redirect ) ) {
|
148 |
-
return $confirmation;
|
149 |
-
}
|
150 |
-
|
151 |
-
$lead = $this->prepare_lead( $entry['id'] );
|
152 |
-
|
153 |
-
if( $is_ajax_redirect ) {
|
154 |
-
preg_match_all( '/gformRedirect.+?(http.+?)(?=\'|")/', $confirmation, $matches, PREG_SET_ORDER );
|
155 |
-
list( $full_match, $url ) = $matches[0];
|
156 |
-
$redirect_url = add_query_arg( array( 'lead' => $lead ), $url );
|
157 |
-
$confirmation = str_replace( $url, $redirect_url, $confirmation );
|
158 |
-
} else {
|
159 |
-
$redirect_url = add_query_arg( array( 'lead' => $lead ), $confirmation['redirect'] );
|
160 |
-
$confirmation['redirect'] = $redirect_url;
|
161 |
-
}
|
162 |
-
|
163 |
-
return $confirmation;
|
164 |
-
}
|
165 |
-
|
166 |
-
function prepare_lead( $entry_id, $force_encrypt = false ) {
|
167 |
-
|
168 |
-
$lead = $entry_id;
|
169 |
-
$do_encrypt = $force_encrypt || $this->_args['encrypt_lead'];
|
170 |
-
|
171 |
-
if( $do_encrypt && is_callable( array( 'GFCommon', 'encrypt' ) ) ) {
|
172 |
-
$lead = rawurlencode( GFCommon::encrypt( $lead ) );
|
173 |
-
}
|
174 |
-
|
175 |
-
return $lead;
|
176 |
-
}
|
177 |
-
|
178 |
-
function get_entry() {
|
179 |
-
|
180 |
-
if( ! self::$_entry ) {
|
181 |
-
|
182 |
-
$entry_id = $this->get_entry_id();
|
183 |
-
if( ! $entry_id )
|
184 |
-
return false;
|
185 |
-
|
186 |
-
$entry = GFFormsModel::get_lead( $entry_id );
|
187 |
-
if( empty( $entry ) )
|
188 |
-
return false;
|
189 |
-
|
190 |
-
self::$_entry = $entry;
|
191 |
-
|
192 |
-
}
|
193 |
-
|
194 |
-
return self::$_entry;
|
195 |
-
}
|
196 |
-
|
197 |
-
function get_entry_id() {
|
198 |
-
|
199 |
-
$entry_id = rgget( 'lead' );
|
200 |
-
if( $entry_id ) {
|
201 |
-
return $this->maybe_decrypt_entry_id( $entry_id );
|
202 |
-
}
|
203 |
-
|
204 |
-
$post = get_post();
|
205 |
-
if( $post ) {
|
206 |
-
$entry_id = get_post_meta( $post->ID, '_gform-entry-id', true );
|
207 |
-
}
|
208 |
-
|
209 |
-
return $entry_id ? $entry_id : false;
|
210 |
-
}
|
211 |
-
|
212 |
-
function maybe_decrypt_entry_id( $entry_id ) {
|
213 |
-
|
214 |
-
// if encryption is enabled, 'lead' parameter MUST be encrypted
|
215 |
-
$do_encrypt = $this->_args['encrypt_lead'];
|
216 |
-
|
217 |
-
if( ! $entry_id ) {
|
218 |
-
return null;
|
219 |
-
} else if( ! $do_encrypt && is_numeric( $entry_id ) && intval( $entry_id ) > 0 ) {
|
220 |
-
return $entry_id;
|
221 |
-
} else {
|
222 |
-
// gEYs6Cqzh1akKc7Y4RGkV8HtcJqQZRmNH+ONxuFEvXM
|
223 |
-
// 0FSCGpzzmt+4Y05fFsJ4ipRZfqD/zdi2ecEeMMRKCjc=
|
224 |
-
$entry_id = is_callable( array( 'GFCommon', 'decrypt' ) ) ? GFCommon::decrypt( $entry_id ) : $entry_id;
|
225 |
-
return intval( $entry_id );
|
226 |
-
}
|
227 |
-
|
228 |
-
}
|
229 |
-
|
230 |
-
function is_auto_lead_enabled( $form ) {
|
231 |
-
|
232 |
-
$auto_append_lead = $this->_args['auto_append_lead'];
|
233 |
-
|
234 |
-
if( is_bool( $auto_append_lead ) && $auto_append_lead === true )
|
235 |
-
return true;
|
236 |
-
|
237 |
-
if( is_array( $auto_append_lead ) && in_array( $form['id'], $auto_append_lead ) )
|
238 |
-
return true;
|
239 |
-
|
240 |
-
return false;
|
241 |
-
}
|
242 |
-
|
243 |
-
}
|
244 |
-
|
245 |
-
function GFParsi_Post_Content_Merge_Tags( $args = array() ) {
|
246 |
-
return GFParsi_Post_Content_Merge_Tags::get_instance( $args );
|
247 |
-
}
|
248 |
-
|
249 |
-
GFParsi_Post_Content_Merge_Tags();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-pre-submission.php
DELETED
@@ -1,194 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
-
exit;
|
3 |
-
}
|
4 |
-
|
5 |
-
class GFParsi_PreSubmission {
|
6 |
-
|
7 |
-
private static $lead;
|
8 |
-
|
9 |
-
public static function init() {
|
10 |
-
add_filter( 'gform_pre_render', array( __class__, 'replace_merge_tags' ) );
|
11 |
-
}
|
12 |
-
|
13 |
-
public static function replace_merge_tags( $form ) {
|
14 |
-
|
15 |
-
if ( function_exists( 'is_checkout' ) && is_checkout() ) {
|
16 |
-
return $form;
|
17 |
-
}
|
18 |
-
|
19 |
-
$current_page = isset( GFFormDisplay::$submission[ $form['id'] ] ) && isset( GFFormDisplay::$submission[ $form['id'] ]['page_number'] ) ? GFFormDisplay::$submission[ $form['id'] ]['page_number'] : 1;
|
20 |
-
$fields = array();
|
21 |
-
|
22 |
-
// get all HTML fields on the current page
|
23 |
-
foreach ( $form['fields'] as &$field ) {
|
24 |
-
|
25 |
-
// skip all fields on the first page
|
26 |
-
if ( rgar( $field, 'pageNumber' ) <= 1 ) {
|
27 |
-
continue;
|
28 |
-
}
|
29 |
-
|
30 |
-
$default_value = rgar( $field, 'defaultValue' );
|
31 |
-
preg_match_all( '/{.+}/', $default_value, $matches, PREG_SET_ORDER );
|
32 |
-
if ( ! empty( $matches ) ) {
|
33 |
-
// if default value needs to be replaced but is not on current page, wait until on the current page to replace it
|
34 |
-
if ( rgar( $field, 'pageNumber' ) != $current_page ) {
|
35 |
-
$field['defaultValue'] = '';
|
36 |
-
} else {
|
37 |
-
$field['defaultValue'] = self::preview_replace_variables( $default_value, $form );
|
38 |
-
}
|
39 |
-
}
|
40 |
-
|
41 |
-
// only run 'content' filter for fields on the current page
|
42 |
-
if ( rgar( $field, 'pageNumber' ) != $current_page ) {
|
43 |
-
continue;
|
44 |
-
}
|
45 |
-
|
46 |
-
$html_content = rgar( $field, 'content' );
|
47 |
-
preg_match_all( '/{.+}/', $html_content, $matches, PREG_SET_ORDER );
|
48 |
-
if ( ! empty( $matches ) ) {
|
49 |
-
$field['content'] = self::preview_replace_variables( $html_content, $form );
|
50 |
-
}
|
51 |
-
|
52 |
-
}
|
53 |
-
|
54 |
-
return $form;
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Adds special support for file upload, post image and multi input merge tags.
|
59 |
-
*/
|
60 |
-
public static function preview_special_merge_tags( $value, $input_id, $merge_tag, $field ) {
|
61 |
-
|
62 |
-
// added to prevent overriding :noadmin filter (and other filters that remove fields)
|
63 |
-
if ( ! $value ) {
|
64 |
-
return $value;
|
65 |
-
}
|
66 |
-
|
67 |
-
$input_type = RGFormsModel::get_input_type( $field );
|
68 |
-
|
69 |
-
$is_upload_field = in_array( $input_type, array( 'post_image', 'fileupload' ) );
|
70 |
-
$is_multi_input = is_array( rgar( $field, 'inputs' ) );
|
71 |
-
$is_input = intval( $input_id ) != $input_id;
|
72 |
-
|
73 |
-
if ( ! $is_upload_field && ! $is_multi_input ) {
|
74 |
-
return $value;
|
75 |
-
}
|
76 |
-
|
77 |
-
// if is individual input of multi-input field, return just that input value
|
78 |
-
if ( $is_input ) {
|
79 |
-
return $value;
|
80 |
-
}
|
81 |
-
|
82 |
-
$form = RGFormsModel::get_form_meta( $field['formId'] );
|
83 |
-
$lead = self::create_lead( $form );
|
84 |
-
$currency = GFCommon::get_currency();
|
85 |
-
|
86 |
-
if ( is_array( rgar( $field, 'inputs' ) ) ) {
|
87 |
-
$value = RGFormsModel::get_lead_field_value( $lead, $field );
|
88 |
-
|
89 |
-
return GFCommon::get_lead_field_display( $field, $value, $currency );
|
90 |
-
}
|
91 |
-
|
92 |
-
switch ( $input_type ) {
|
93 |
-
case 'fileupload':
|
94 |
-
$value = self::preview_image_value( "input_{$field['id']}", $field, $form, $lead );
|
95 |
-
$value = self::preview_image_display( $field, $form, $value );
|
96 |
-
break;
|
97 |
-
default:
|
98 |
-
$value = self::preview_image_value( "input_{$field['id']}", $field, $form, $lead );
|
99 |
-
$value = GFCommon::get_lead_field_display( $field, $value, $currency );
|
100 |
-
break;
|
101 |
-
}
|
102 |
-
|
103 |
-
return $value;
|
104 |
-
}
|
105 |
-
|
106 |
-
public static function preview_image_value( $input_name, $field, $form, $lead ) {
|
107 |
-
|
108 |
-
$field_id = $field['id'];
|
109 |
-
$file_info = RGFormsModel::get_temp_filename( $form['id'], $input_name );
|
110 |
-
$source = RGFormsModel::get_upload_url( $form['id'] ) . "/tmp/" . $file_info["temp_filename"];
|
111 |
-
|
112 |
-
if ( ! $file_info ) {
|
113 |
-
return '';
|
114 |
-
}
|
115 |
-
|
116 |
-
switch ( RGFormsModel::get_input_type( $field ) ) {
|
117 |
-
|
118 |
-
case "post_image":
|
119 |
-
list( , $image_title, $image_caption, $image_description ) = explode( "|:|", $lead[ $field['id'] ] );
|
120 |
-
$value = ! empty( $source ) ? $source . "|:|" . $image_title . "|:|" . $image_caption . "|:|" . $image_description : "";
|
121 |
-
break;
|
122 |
-
|
123 |
-
case "fileupload" :
|
124 |
-
$value = $source;
|
125 |
-
break;
|
126 |
-
|
127 |
-
}
|
128 |
-
|
129 |
-
return $value;
|
130 |
-
}
|
131 |
-
|
132 |
-
public static function preview_image_display( $field, $form, $value ) {
|
133 |
-
|
134 |
-
// need to get the tmp $file_info to retrieve real uploaded filename, otherwise will display ugly tmp name
|
135 |
-
$input_name = "input_" . str_replace( '.', '_', $field['id'] );
|
136 |
-
$file_info = RGFormsModel::get_temp_filename( $form['id'], $input_name );
|
137 |
-
|
138 |
-
$file_path = $value;
|
139 |
-
if ( ! empty( $file_path ) ) {
|
140 |
-
$file_path = esc_attr( str_replace( " ", "%20", $file_path ) );
|
141 |
-
$value = "<a href='$file_path' target='_blank' title='" . __( "Click to view", "gravityforms" ) . "'>" . $file_info['uploaded_filename'] . "</a>";
|
142 |
-
}
|
143 |
-
|
144 |
-
return $value;
|
145 |
-
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Retrieves $lead object from class if it has already been created; otherwise creates a new $lead object.
|
150 |
-
*/
|
151 |
-
public static function create_lead( $form ) {
|
152 |
-
|
153 |
-
if ( empty( self::$lead ) ) {
|
154 |
-
self::$lead = GFFormsModel::create_lead( $form );
|
155 |
-
self::clear_field_value_cache( $form );
|
156 |
-
}
|
157 |
-
|
158 |
-
return self::$lead;
|
159 |
-
}
|
160 |
-
|
161 |
-
public static function preview_replace_variables( $content, $form ) {
|
162 |
-
|
163 |
-
$lead = self::create_lead( $form );
|
164 |
-
|
165 |
-
// add filter that will handle getting temporary URLs for file uploads and post image fields (removed below)
|
166 |
-
// beware, the RGFormsModel::create_lead() function also triggers the gform_merge_tag_filter at some point and will
|
167 |
-
// result in an infinite loop if not called first above
|
168 |
-
add_filter( 'gform_merge_tag_filter', array( 'GFParsi_PreSubmission', 'preview_special_merge_tags' ), 10, 4 );
|
169 |
-
|
170 |
-
$content = GFCommon::replace_variables( $content, $form, $lead, false, false, false );
|
171 |
-
|
172 |
-
// remove filter so this function is not applied after preview functionality is complete
|
173 |
-
remove_filter( 'gform_merge_tag_filter', array( 'GFParsi_PreSubmission', 'preview_special_merge_tags' ) );
|
174 |
-
|
175 |
-
return $content;
|
176 |
-
}
|
177 |
-
|
178 |
-
public static function clear_field_value_cache( $form ) {
|
179 |
-
|
180 |
-
if ( ! class_exists( 'GFCache' ) ) {
|
181 |
-
return;
|
182 |
-
}
|
183 |
-
|
184 |
-
foreach ( $form['fields'] as &$field ) {
|
185 |
-
if ( GFFormsModel::get_input_type( $field ) == 'total' ) {
|
186 |
-
GFCache::delete( 'GFFormsModel::get_lead_field_value__' . $field['id'] );
|
187 |
-
}
|
188 |
-
}
|
189 |
-
|
190 |
-
}
|
191 |
-
|
192 |
-
}
|
193 |
-
|
194 |
-
GFParsi_PreSubmission::init();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-settings.php
ADDED
@@ -0,0 +1,418 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Settings extends GFAddOn {
|
6 |
+
|
7 |
+
protected $_version = GF_PERSIAN_VERSION;
|
8 |
+
protected $_min_gravityforms_version = '1.9';
|
9 |
+
protected $_path = GF_PERSIAN_DIR . 'index.php';
|
10 |
+
protected $_full_path = __FILE__;
|
11 |
+
protected $_slug = GF_PERSIAN_SLUG;
|
12 |
+
protected $_short_title = 'گرویتی فرم پارسی';
|
13 |
+
protected $_title = 'بسته گرویتی فرم پارسی';
|
14 |
+
|
15 |
+
private static $_instance = null;
|
16 |
+
|
17 |
+
public static function get_instance() {
|
18 |
+
|
19 |
+
if ( self::$_instance == null ) {
|
20 |
+
self::$_instance = new self();
|
21 |
+
}
|
22 |
+
|
23 |
+
return self::$_instance;
|
24 |
+
}
|
25 |
+
|
26 |
+
public function init() {
|
27 |
+
parent::init();
|
28 |
+
}
|
29 |
+
|
30 |
+
public function plugin_settings_fields() {
|
31 |
+
return array(
|
32 |
+
array(
|
33 |
+
'title' => 'تنظیمات گرویتی فرم پارسی',
|
34 |
+
'fields' => array(
|
35 |
+
array(
|
36 |
+
'name' => 'translate',
|
37 |
+
'label' => 'ترجمه گرویتی فرم',
|
38 |
+
'tooltip' => 'با فعالسازی این گزینه در صورتی که زبان سایت به صورت فارسی باشد گرویتی فرم به پارسی ترجمه خواهد شد.',
|
39 |
+
'type' => 'radio',
|
40 |
+
'horizontal' => true,
|
41 |
+
'default_value' => '1',
|
42 |
+
'choices' => array(
|
43 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
44 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
45 |
+
),
|
46 |
+
),
|
47 |
+
array(
|
48 |
+
'name' => 'address',
|
49 |
+
'label' => 'آدرس های ایران',
|
50 |
+
'tooltip' => 'با فعالسازی این گزینه استان ها و شهرهای ایران به فیلد "آدرس" اضافه خواهد شد. باید از تب "عمومی" فیلد آدرس گزینه "نوع آدرس" را بر روی "ایران" قرار دهید و سپس تیک "فعالسازی شهرهای ایران" را انتخاب کنید.',
|
51 |
+
'type' => 'radio',
|
52 |
+
'horizontal' => true,
|
53 |
+
'default_value' => '1',
|
54 |
+
'choices' => array(
|
55 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
56 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
57 |
+
),
|
58 |
+
),
|
59 |
+
array(
|
60 |
+
'name' => 'national_id',
|
61 |
+
'label' => 'فیلد کد ملی',
|
62 |
+
'tooltip' => 'با فعالسازی این فیلد "کد ملی" به فیلدهای پیشرفته گرویتی فرم اضافه خواهد شد. این فیلد قابلیت اعتبار سنجی کد ملی و همچنین نمایش شهر صادر کننده کد ملی را هم دارد.',
|
63 |
+
'type' => 'radio',
|
64 |
+
'horizontal' => true,
|
65 |
+
'default_value' => '1',
|
66 |
+
'choices' => array(
|
67 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
68 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
69 |
+
),
|
70 |
+
),
|
71 |
+
array(
|
72 |
+
'name' => 'jalali',
|
73 |
+
'label' => 'شمسی ساز فیلد تاریخ',
|
74 |
+
'tooltip' => 'با فعالسازی این فیلد گزینه تاریخ جلالی به قابلیت های فیلد تاریخ گرویتی فرم اضافه خواهد شد.',
|
75 |
+
'type' => 'radio',
|
76 |
+
'horizontal' => true,
|
77 |
+
'default_value' => '1',
|
78 |
+
'choices' => array(
|
79 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
80 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
81 |
+
),
|
82 |
+
),
|
83 |
+
array(
|
84 |
+
'name' => 'currencies',
|
85 |
+
'label' => 'واحدهای پول ایران',
|
86 |
+
'tooltip' => 'با فعالسازی این فیلد گزینه واحدهای پول ایران (ریال - تومان - هزار ریال - هزار تومان) به واحدهای پول گرویتی فرم اضافه خواهد شد.<br><br>واحد های "هزار ریال - هزار تومان" با نسخه 2.3 درگاه های پرداخت به بالا سازگارند و برای نسخه های پایین تر درگاه های پرداخت قابل استفاده نیستند.',
|
87 |
+
'type' => 'radio',
|
88 |
+
'horizontal' => true,
|
89 |
+
'default_value' => '1',
|
90 |
+
'choices' => array(
|
91 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
92 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
93 |
+
),
|
94 |
+
),
|
95 |
+
array(
|
96 |
+
'name' => 'rtl_admin',
|
97 |
+
'label' => 'راستچین سازی مدیریت',
|
98 |
+
'tooltip' => 'با فعالسازی این فیلد گزینه بخش هایی از محیط کار با گرویتی فرم در مدیریت که نیاز به راستچین سازی داشته باشند، راستچین خواهند شد.',
|
99 |
+
'type' => 'radio',
|
100 |
+
'horizontal' => true,
|
101 |
+
'default_value' => '1',
|
102 |
+
'choices' => array(
|
103 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
104 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
105 |
+
),
|
106 |
+
),
|
107 |
+
array(
|
108 |
+
'name' => 'font_admin',
|
109 |
+
'label' => 'فونت مدیریت',
|
110 |
+
'tooltip' => 'با توجه به جذاب بودن محیط کار با گرویتی فرم در بخش مدیریت سایت، با اضافه کردن فرم پارسی آن را جذاب تر نمایید.',
|
111 |
+
'type' => 'radio',
|
112 |
+
'horizontal' => true,
|
113 |
+
'default_value' => 'vazir',
|
114 |
+
'choices' => array(
|
115 |
+
array( 'label' => 'بدون فونت', 'value' => '0' ),
|
116 |
+
array( 'label' => 'یکان', 'value' => 'yekan' ),
|
117 |
+
array( 'label' => 'وزیر', 'value' => 'vazir' ),
|
118 |
+
array( 'label' => 'شبنم', 'value' => 'shabnam' ),
|
119 |
+
),
|
120 |
+
),
|
121 |
+
array(
|
122 |
+
'name' => 'payments',
|
123 |
+
'label' => 'سازگاری با درگاه های پرداخت',
|
124 |
+
'tooltip' => 'در صورتی که از درگاه های پرداخت استفاده میکنید حتما باید این گزینه را فعال نمایید تا یک سری امکانات مربوط به درگاه پرداخت ایرانی به گرویتی فرم اضافه شود. (در حال حاضر با توجه به آزمایشی بودن این قسمت، باید فقط فعال باشد.)',
|
125 |
+
'type' => 'radio',
|
126 |
+
'horizontal' => true,
|
127 |
+
'default_value' => '1',
|
128 |
+
'disabled' => 'disabled',
|
129 |
+
'choices' => array(
|
130 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
131 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
132 |
+
),
|
133 |
+
),
|
134 |
+
array(
|
135 |
+
'name' => 'rss_widget',
|
136 |
+
'label' => 'خبرخوان گرویتی فرم پارسی',
|
137 |
+
'tooltip' => 'با فعالسازی این فیلد گزینه ابزارک خبرخوان گرویتی فرم پارسی به داشبورد مدیریت وردپرس اضافه خواهد شد تا آخرین پست های گرویتی فرم پارسی را مشاهده کنید.',
|
138 |
+
'type' => 'radio',
|
139 |
+
'horizontal' => true,
|
140 |
+
'default_value' => '1',
|
141 |
+
'choices' => array(
|
142 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
143 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
144 |
+
),
|
145 |
+
),
|
146 |
+
|
147 |
+
array(
|
148 |
+
'name' => 'br',
|
149 |
+
'label' => '',
|
150 |
+
'type' => 'br',
|
151 |
+
),
|
152 |
+
array(
|
153 |
+
'name' => 'other_tools',
|
154 |
+
'label' => '<strong>سایر تنظیمات اضافه شده</strong>',
|
155 |
+
'tooltip' => 'سایر تنظیمات مربوط به امکانات اضافه شده توسط گرویتی فرم پارسی',
|
156 |
+
'type' => 'hr',
|
157 |
+
'text' => 'گزینه های زیر ارتباطی به بومی سازی برای ایران ندارند و به درخواست کاربران اضافه شده اند.',
|
158 |
+
),
|
159 |
+
array(
|
160 |
+
'name' => 'enable_transaction_id',
|
161 |
+
'label' => 'فعالسازی کد رهگیری',
|
162 |
+
'tooltip' => 'به صورت پیشفرض در گرویتی فرم فقط زمانیکه یک پرداخت انجام شود یک شماره تراکنش ثبت میشود<br> با فعالسازی این گزینه میتوانید حتی برای فرم هایی که به درگاه پرداخت متصل نیستند نیز کد رهگیری اختصاص دهید.',
|
163 |
+
'type' => 'radio',
|
164 |
+
'horizontal' => true,
|
165 |
+
'default_value' => '1',
|
166 |
+
'choices' => array(
|
167 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
168 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
169 |
+
),
|
170 |
+
),
|
171 |
+
array(
|
172 |
+
'name' => 'transaction_id_title',
|
173 |
+
'label' => 'عنوان کد رهگیری',
|
174 |
+
'tooltip' => 'در صورتیکه گزینه بالا را فعال کرده اید، عنوانی که میخواهید برای کد رهگیری نمایش داده شود را وارد کنید.',
|
175 |
+
'type' => 'text',
|
176 |
+
'default_value' => __( 'Transaction Id', 'gravityforms' ),
|
177 |
+
),
|
178 |
+
array(
|
179 |
+
'name' => 'transaction_id_mask',
|
180 |
+
'label' => 'الگوی کد رهگیری (قاب)',
|
181 |
+
'tooltip' => 'با توجه به آشنایی با مفهوم قاب (الگو) در گرویتی فرم، الگوی دلخواه خود برای تولید کد رهگیری را وارد کنید.',
|
182 |
+
'type' => 'text',
|
183 |
+
'default_value' => '9999999999',
|
184 |
+
'style' => 'text-align:left; direction:ltr;',
|
185 |
+
'after_input' => $this->mask_instructions(),
|
186 |
+
),
|
187 |
+
array(
|
188 |
+
'name' => '_',
|
189 |
+
'label' => 'برچسب های ادغام (شورتکد)',
|
190 |
+
'type' => 'hr',
|
191 |
+
'tooltip' => 'برچسب های ادغام (Merge Tags) در واقع همان شورتکد های گرویتی فرم هستند',
|
192 |
+
),
|
193 |
+
array(
|
194 |
+
'name' => 'add_merge_tags',
|
195 |
+
'label' => 'برچسب های ادغام جدید',
|
196 |
+
'tooltip' => 'با فعالسازی این گزینه، شورتکدهای جدیدی به لیست آنها اضافه خواهد شد. شورتکدهایی نظیر اطلاعات پرداخت - وضعیت پرداخت - کد رهگیری و ...',
|
197 |
+
'type' => 'radio',
|
198 |
+
'horizontal' => true,
|
199 |
+
'default_value' => '1',
|
200 |
+
'choices' => array(
|
201 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
202 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
203 |
+
),
|
204 |
+
),
|
205 |
+
array(
|
206 |
+
'name' => 'post_content_merge_tags',
|
207 |
+
'label' => 'برچسب ها در برگه ها',
|
208 |
+
'tooltip' => 'به صورت پیشفرض وقتی نوع تاییدیه ها را روی "برگه" ست میکنید امکان استفاده از "برچسب ها (شورتکد های گرویتی فرم)" در آن برگه ها وجود نخواهد داشت. با فعالسازی این گزینه این امکان فراهم خواهد شد.',
|
209 |
+
'type' => 'radio',
|
210 |
+
'horizontal' => true,
|
211 |
+
'default_value' => '1',
|
212 |
+
'choices' => array(
|
213 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
214 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
215 |
+
),
|
216 |
+
),
|
217 |
+
array(
|
218 |
+
'name' => 'entry_time',
|
219 |
+
'label' => 'ماندگاری برچسب ها در برگه',
|
220 |
+
'tooltip' => 'با فعالسازی گزینه بالا، زمانیکه کاربر به برگه تاییدیه هدایت میشود، آیدی پیام ورودی اش نیز در آدرس بار پاس داده میشود و این سبب میشود که افراد دیگر با دانستن شماره پیام (و یا آزمون و خطا) به اطلاعات آن تاییدیه دسترسی داشته پیدا کنند. برای جلوگیری از این قضیه یک مدت زمان بر حسب دقیقه وارد کنید تا پس از گذشت آن زمان دسترسی به تاییدیه منقضی شود.',
|
221 |
+
'type' => 'text',
|
222 |
+
'class' => 'small',
|
223 |
+
'input_type' => 'number',
|
224 |
+
'default_value' => '0',
|
225 |
+
'style' => 'width:70px;',
|
226 |
+
'after_input' => ' (دقیقه) - در صورتی که این فیلد را خالی و یا برابر 0 قرار دهید، شماره پیام ورودی به صورت "انکریپت شده" پاس داده خواهد شد.',
|
227 |
+
),
|
228 |
+
array(
|
229 |
+
'name' => 'pre_submission_merge_tags',
|
230 |
+
'label' => 'برچسب ها در فیلد HTML',
|
231 |
+
'tooltip' => 'توسط این امکان میتوانید برای فرم های خود یک "پیشفاکتور" بسازید.<br>' . '<a target="_blank" href="http://gravityforms.ir/5690">برای مشاهده راهنما کلیک کنید.</a>',
|
232 |
+
'type' => 'radio',
|
233 |
+
'horizontal' => true,
|
234 |
+
'default_value' => '1',
|
235 |
+
'choices' => array(
|
236 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
237 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
238 |
+
),
|
239 |
+
),
|
240 |
+
array(
|
241 |
+
'name' => '__',
|
242 |
+
'label' => 'تنظیمات سایر ویژگی ها',
|
243 |
+
'type' => 'hr',
|
244 |
+
'tooltip' => 'تنظیمات سایر ویژگی ها',
|
245 |
+
),
|
246 |
+
array(
|
247 |
+
'name' => 'hide_lic',
|
248 |
+
'label' => 'حذف بنر فعال نبودن لایسنس',
|
249 |
+
'tooltip' => 'در برخی نسخه های گرویتی فرم، در صورتی که لایسنس گرویتی فرم شما فعال نباشد یک بنر بالای صفحات گرویتی فرم مبنی بر عدم فعال بودن لایسنس شما ظاهر میشود که با فعالسازی این گزینه میتوانید آن را مخفی نمایید.',
|
250 |
+
'type' => 'radio',
|
251 |
+
'horizontal' => true,
|
252 |
+
'default_value' => '0',
|
253 |
+
'choices' => array(
|
254 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
255 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
256 |
+
),
|
257 |
+
),
|
258 |
+
array(
|
259 |
+
'name' => 'live_preview',
|
260 |
+
'label' => 'پیشنمایش زنده',
|
261 |
+
'tooltip' => 'با فعالسازی این گزینه، منوی پیشنمایش زنده در ویرایشگر فرم اضافه میشود تا فرم را داخل فرانت اند سایت مشاهده نمایید. البته این گزینه ممکن است با برخی قالب ها سازگاری نداشته باشد. چون یک پست تایپ مجازی ایجاد میکند.',
|
262 |
+
'type' => 'radio',
|
263 |
+
'horizontal' => true,
|
264 |
+
'default_value' => '1',
|
265 |
+
'choices' => array(
|
266 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
267 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
268 |
+
),
|
269 |
+
),
|
270 |
+
array(
|
271 |
+
'name' => 'label_visibility',
|
272 |
+
'label' => 'مدیریت لیبل فیلدها',
|
273 |
+
'tooltip' => 'با فعالسازی این گزینه، یک آپشن جدید در تب "نمایش" فیلدها زیر "نگه دارنده متن (Placeholder)" تحت عنوان "نمایش برچسب فیلد" اضافه خواهد شد تا بتوانید "لیبل (Lable)" فیلد ها را مخفی کنید.این گزینه برای زمانی که از "نگه دارنده متن (Placeholder)" استفاده میکنید مفید است.',
|
274 |
+
'type' => 'radio',
|
275 |
+
'horizontal' => true,
|
276 |
+
'default_value' => '1',
|
277 |
+
'choices' => array(
|
278 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
279 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
280 |
+
),
|
281 |
+
),
|
282 |
+
array(
|
283 |
+
'name' => 'newsletter',
|
284 |
+
'label' => 'رویداد خبرنامه در اعلان ها',
|
285 |
+
'tooltip' => 'توسط این امکان میتوانید گرویتی فرم خود را به یک پلاگین خبرنامه تبدیل کنید.<br>' . '<a target="_blank" href="http://gravityforms.ir/3940">برای مشاهده توضیحات کلیک کنید.</a>',
|
286 |
+
'type' => 'radio',
|
287 |
+
'horizontal' => true,
|
288 |
+
'default_value' => '1',
|
289 |
+
'choices' => array(
|
290 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
291 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
292 |
+
),
|
293 |
+
),
|
294 |
+
array(
|
295 |
+
'name' => 'private_post',
|
296 |
+
'label' => 'وضعیت پست خصوصی',
|
297 |
+
'tooltip' => 'به صورت پیشفرض وقتی از "فیلدهای ارسال نوشته" استفاده کنید وضعیت پست "خصوصی" در لیست وضیعت های پست وجود ندارد که با فعالسازی این گزینه اضافه خواهد شد.',
|
298 |
+
'type' => 'radio',
|
299 |
+
'horizontal' => true,
|
300 |
+
'default_value' => '1',
|
301 |
+
'choices' => array(
|
302 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
303 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
304 |
+
),
|
305 |
+
),
|
306 |
+
array(
|
307 |
+
'name' => 'multipage_nav',
|
308 |
+
'label' => 'پیمایش فرم های مرحله ای',
|
309 |
+
'tooltip' => 'با فعالسازی این گزینه در فرم های چند مرحله ای (چند برگه ای) در صورتی که از تب "عمومی" برگه "نشانگر پیشرفت" را روی حالت "مرحله ها" قرار دهید، کاربران بدون استفاده از دکمه های "قبلی" و "بعدی" میتوانند از طریق خود "نشانگر پیشرفت" بین صفحات (مرحله ها) جابجا شوند.',
|
310 |
+
'type' => 'radio',
|
311 |
+
'horizontal' => true,
|
312 |
+
'default_value' => '1',
|
313 |
+
'choices' => array(
|
314 |
+
array( 'label' => 'بله', 'value' => '1' ),
|
315 |
+
array( 'label' => 'خیر', 'value' => '0' ),
|
316 |
+
),
|
317 |
+
),
|
318 |
+
array(
|
319 |
+
'name' => 'multipage_nav_last',
|
320 |
+
'label' => 'شرط پیمایش فرم های مرحله ای',
|
321 |
+
'tooltip' => 'در صورتی که گزینه بالا را فعال کرده اید، میتوانید مشخص کنید که پیمایش بین مرحله ها همواره از ابتدا فعال باشد یا فقط زمانیکه که کاربر مرحله ها را پشت سر گذاشت و به مرحله آخر رسید فعال شود.',
|
322 |
+
'type' => 'radio',
|
323 |
+
'horizontal' => true,
|
324 |
+
'default_value' => '1',
|
325 |
+
'choices' => array(
|
326 |
+
array( 'label' => 'همواره فعال باشد', 'value' => '0' ),
|
327 |
+
array( 'label' => 'فقط زمانیکه تمام مراحل طی شدند و به مرحله آخر رسید فعال شود', 'value' => '1' ),
|
328 |
+
),
|
329 |
+
),
|
330 |
+
)
|
331 |
+
)
|
332 |
+
);
|
333 |
+
}
|
334 |
+
|
335 |
+
|
336 |
+
public function settings_br( $field, $echo = true ) {
|
337 |
+
|
338 |
+
$output = '<br>';
|
339 |
+
|
340 |
+
if ( $echo ) {
|
341 |
+
echo $output;
|
342 |
+
} else {
|
343 |
+
return $output;
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
public function settings_hr( $field, $echo = true ) {
|
348 |
+
|
349 |
+
$output = '';
|
350 |
+
|
351 |
+
if ( ! empty( $field['text'] ) ) {
|
352 |
+
$output .= $field['text'];
|
353 |
+
}
|
354 |
+
|
355 |
+
$output .= '<hr>';
|
356 |
+
|
357 |
+
if ( $echo ) {
|
358 |
+
echo $output;
|
359 |
+
} else {
|
360 |
+
return $output;
|
361 |
+
}
|
362 |
+
}
|
363 |
+
|
364 |
+
private function mask_instructions() {
|
365 |
+
|
366 |
+
ob_start(); ?>
|
367 |
+
|
368 |
+
<div id="custom_mask_instructions" style="display:none;">
|
369 |
+
<div class="custom_mask_instructions">
|
370 |
+
<h4><?php esc_html_e( 'Usage', 'gravityforms' ) ?></h4>
|
371 |
+
<ul class="description-list">
|
372 |
+
<li><?php esc_html_e( "Use a '9' to indicate a numerical character.", 'gravityforms' ) ?></li>
|
373 |
+
<li><?php esc_html_e( "Use a lower case 'a' to indicate an alphabetical character.", 'gravityforms' ) ?></li>
|
374 |
+
<li><?php esc_html_e( "Use an asterisk '*' to indicate any alphanumeric character.", 'gravityforms' ) ?></li>
|
375 |
+
<li><?php esc_html_e( 'All other characters are literal values and will be displayed automatically.', 'gravityforms' ) ?></li>
|
376 |
+
</ul>
|
377 |
+
|
378 |
+
<h4><?php esc_html_e( 'Examples', 'gravityforms' ) ?></h4>
|
379 |
+
<ul class="examples-list">
|
380 |
+
|
381 |
+
<li>
|
382 |
+
<h5><?php esc_html_e( 'Social Security Number', 'gravityforms' ) ?></h5>
|
383 |
+
<span class="label"><?php esc_html_e( 'Mask', 'gravityforms' ) ?></span>
|
384 |
+
<code>999-99-9999</code><br/>
|
385 |
+
<span
|
386 |
+
class="label">نمونه خروجی</span>
|
387 |
+
<code>987-65-4329</code>
|
388 |
+
</li>
|
389 |
+
<li>
|
390 |
+
<h5><?php esc_html_e( 'Course Code', 'gravityforms' ) ?></h5>
|
391 |
+
<span class="label"><?php esc_html_e( 'Mask', 'gravityforms' ) ?></span>
|
392 |
+
<code>aaa 999</code><br/>
|
393 |
+
<span
|
394 |
+
class="label">نمونه خروجی</span>
|
395 |
+
<code>BIO 101</code>
|
396 |
+
</li>
|
397 |
+
<li>
|
398 |
+
<h5><?php esc_html_e( 'License Key', 'gravityforms' ) ?></h5>
|
399 |
+
<span class="label"><?php esc_html_e( 'Mask', 'gravityforms' ) ?></span>
|
400 |
+
<code>***-***-***</code><br/>
|
401 |
+
<span
|
402 |
+
class="label">نمونه خروجی</span>
|
403 |
+
<code>a9a-f0c-28Q</code>
|
404 |
+
</li>
|
405 |
+
</ul>
|
406 |
+
|
407 |
+
</div>
|
408 |
+
</div>
|
409 |
+
(<a href="javascript:void(0);" style="text-decoration: none !important;"
|
410 |
+
onclick="tb_show('<?php echo esc_js( __( 'Custom Mask Instructions', 'gravityforms' ) ); ?>', '#TB_inline?width=350&inlineId=custom_mask_instructions', '');"
|
411 |
+
onkeypress="tb_show('<?php echo esc_js( __( 'Custom Mask Instructions', 'gravityforms' ) ); ?>', '#TB_inline?width=350&inlineId=custom_mask_instructions', '');">
|
412 |
+
راهنمای ایجاد الگو
|
413 |
+
</a>)
|
414 |
+
<?php
|
415 |
+
return ob_get_clean();
|
416 |
+
}
|
417 |
+
|
418 |
+
}
|
includes/class-snippets.php
CHANGED
@@ -1,78 +1,67 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) )
|
2 |
-
|
3 |
-
class GFParsi_PostPermalink {
|
4 |
-
|
5 |
-
function __construct() {
|
6 |
-
add_filter('gform_custom_merge_tags', array($this, 'add_custom_merge_tag'), 10, 4);
|
7 |
-
add_filter('gform_replace_merge_tags', array($this, 'replace_merge_tag'), 10, 3);
|
8 |
-
}
|
9 |
-
|
10 |
-
function add_custom_merge_tag($merge_tags, $form_id, $fields, $element_id) {
|
11 |
-
if(!GFCommon::has_post_field($fields))
|
12 |
-
return $merge_tags;
|
13 |
-
$merge_tags[] = array('label' => __('Post Permalink', 'GF_FA') , 'tag' => '{post_permalink}');
|
14 |
-
return $merge_tags;
|
15 |
-
}
|
16 |
-
|
17 |
-
function replace_merge_tag($text, $form, $entry) {
|
18 |
-
|
19 |
-
$custom_merge_tag = '{post_permalink}';
|
20 |
-
if(strpos($text, $custom_merge_tag) === false || !rgar($entry, 'post_id'))
|
21 |
-
return $text;
|
22 |
-
|
23 |
-
$post_permalink = get_permalink(rgar($entry, 'post_id'));
|
24 |
-
$text = str_replace($custom_merge_tag, $post_permalink, $text);
|
25 |
-
|
26 |
-
return $text;
|
27 |
-
}
|
28 |
-
|
29 |
-
}
|
30 |
-
new GFParsi_PostPermalink();
|
31 |
-
|
32 |
-
|
33 |
-
add_filter('gform_pre_render', 'gfir_prepopluate_merge_tags');
|
34 |
-
function gfir_prepopluate_merge_tags($form) {
|
35 |
-
|
36 |
-
$filter_names = array();
|
37 |
-
|
38 |
-
foreach($form['fields'] as &$field) {
|
39 |
-
|
40 |
-
if(!rgar($field, 'allowsPrepopulate'))
|
41 |
-
continue;
|
42 |
-
|
43 |
-
// complex fields store inputName in the "name" property of the inputs array
|
44 |
-
if(is_array(rgar($field, 'inputs')) && $field['type'] != 'checkbox') {
|
45 |
-
foreach($field['inputs'] as $input) {
|
46 |
-
if(rgar($input, 'name'))
|
47 |
-
$filter_names[] = array('type' => $field['type'], 'name' => rgar($input, 'name'));
|
48 |
-
}
|
49 |
-
} else {
|
50 |
-
$filter_names[] = array('type' => $field['type'], 'name' => rgar($field, 'inputName'));
|
51 |
-
}
|
52 |
-
|
53 |
-
}
|
54 |
-
|
55 |
-
foreach($filter_names as $filter_name) {
|
56 |
-
|
57 |
-
$filtered_name = GFCommon::replace_variables_prepopulate($filter_name['name']);
|
58 |
-
|
59 |
-
if($filter_name['name'] == $filtered_name)
|
60 |
-
continue;
|
61 |
-
|
62 |
-
add_filter("gform_field_value_{$filter_name['name']}", create_function("", "return '$filtered_name';"));
|
63 |
-
}
|
64 |
-
|
65 |
-
return $form;
|
66 |
}
|
67 |
|
|
|
68 |
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
-
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
}
|
4 |
|
5 |
+
class GFPersian_Snippets extends GFPersian_Core {
|
6 |
|
7 |
+
public function __construct() {
|
8 |
+
|
9 |
+
if ( $this->option( 'label_visibility', '1' ) == '1' ) {
|
10 |
+
add_filter( 'gform_enable_field_label_visibility_settings', '__return_true' );
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( $this->option( 'private_post', '1' ) == '1' ) {
|
14 |
+
add_action( 'gform_post_status_options', array( $this, 'add_private_post_status' ) );
|
15 |
+
}
|
16 |
+
|
17 |
+
if ( $this->option( 'newsletter', '1' ) == '1' ) {
|
18 |
+
add_filter( 'gform_notification_events', array( $this, 'add_newsletter_notification_event' ) );
|
19 |
+
add_filter( 'gform_before_resend_notifications', array( $this, 'add_notification_filter' ) );
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
public function add_private_post_status( $post_statuses ) {
|
24 |
+
$post_statuses['private'] = 'خصوصی';
|
25 |
+
|
26 |
+
return $post_statuses;
|
27 |
+
}
|
28 |
+
|
29 |
+
/*---------------------------------------------------------------------------------------------*/
|
30 |
+
/*----------Start of NewsLetter----------------------------------------------------------------*/
|
31 |
+
/*---------------------------------------------------------------------------------------------*/
|
32 |
+
public function add_newsletter_notification_event( $events ) {
|
33 |
+
$events['newsletter'] = 'خبرنامه';
|
34 |
+
|
35 |
+
return $events;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function add_notification_filter( $form ) {
|
39 |
+
add_filter( 'gform_notification', array( $this, 'evaluate_notification_conditional_logic' ), 10, 3 );
|
40 |
|
41 |
+
return $form;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function evaluate_notification_conditional_logic( $notification, $form, $entry ) {
|
45 |
+
|
46 |
+
// if it fails conditional logic, suppress it
|
47 |
+
if ( $notification['event'] == 'newsletter' && ! GFCommon::evaluate_conditional_logic( rgar( $notification, 'conditionalLogic' ), $form, $entry ) ) {
|
48 |
+
add_filter( 'gform_pre_send_email', array( $this, 'abort_next_notification' ) );
|
49 |
+
}
|
50 |
+
|
51 |
+
return $notification;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function abort_next_notification( $args ) {
|
55 |
+
remove_filter( 'gform_pre_send_email', array( $this, 'abort_next_notification' ) );
|
56 |
+
$args['abort_email'] = true;
|
57 |
+
|
58 |
+
return $args;
|
59 |
+
}
|
60 |
+
/*---------------------------------------------------------------------------------------------*/
|
61 |
+
/*----------End of NewsLetter------------------------------------------------------------------*/
|
62 |
+
/*---------------------------------------------------------------------------------------------*/
|
63 |
+
|
64 |
+
|
65 |
+
}
|
66 |
|
67 |
+
new GFPersian_Snippets;
|
includes/class-subtotal-calc.php
DELETED
@@ -1,245 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit;
|
2 |
-
|
3 |
-
class GFParsi_CalcSubtotal {
|
4 |
-
|
5 |
-
public static $merge_tag = '{subtotal}';
|
6 |
-
|
7 |
-
function __construct() {
|
8 |
-
|
9 |
-
// front-end
|
10 |
-
add_filter( 'gform_pre_render', array( $this, 'maybe_replace_subtotal_merge_tag' ) );
|
11 |
-
add_filter( 'gform_pre_validation', array( $this, 'maybe_replace_subtotal_merge_tag_submission' ) );
|
12 |
-
|
13 |
-
// back-end
|
14 |
-
add_filter( 'gform_admin_pre_render', array( $this, 'add_merge_tags' ) );
|
15 |
-
|
16 |
-
}
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Look for {subtotal} merge tag in form fields 'calculationFormula' property. If found, replace with the
|
20 |
-
* aggregated subtotal merge tag string.
|
21 |
-
*
|
22 |
-
* @param mixed $form
|
23 |
-
*/
|
24 |
-
function maybe_replace_subtotal_merge_tag( $form, $filter_tags = false ) {
|
25 |
-
|
26 |
-
foreach( $form['fields'] as &$field ) {
|
27 |
-
|
28 |
-
if( current_filter() == 'gform_pre_render' && rgar( $field, 'origCalculationFormula' ) )
|
29 |
-
$field['calculationFormula'] = $field['origCalculationFormula'];
|
30 |
-
|
31 |
-
if( ! self::has_subtotal_merge_tag( $field ) )
|
32 |
-
continue;
|
33 |
-
|
34 |
-
$subtotal_merge_tags = self::get_subtotal_merge_tag_string( $form, $field, $filter_tags );
|
35 |
-
$field['origCalculationFormula'] = $field['calculationFormula'];
|
36 |
-
$field['calculationFormula'] = str_replace( self::$merge_tag, $subtotal_merge_tags, $field['calculationFormula'] );
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
return $form;
|
41 |
-
}
|
42 |
-
|
43 |
-
function maybe_replace_subtotal_merge_tag_submission( $form ) {
|
44 |
-
return $this->maybe_replace_subtotal_merge_tag( $form, true );
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Get all the pricing fields on the form, get their corresponding merge tags and aggregate them into a formula that
|
49 |
-
* will yeild the form's subtotal.
|
50 |
-
*
|
51 |
-
* @param mixed $form
|
52 |
-
*/
|
53 |
-
static function get_subtotal_merge_tag_string( $form, $current_field, $filter_tags = false ) {
|
54 |
-
|
55 |
-
$pricing_fields = self::get_pricing_fields( $form );
|
56 |
-
$product_tag_groups = array();
|
57 |
-
|
58 |
-
foreach( $pricing_fields['products'] as $product ) {
|
59 |
-
|
60 |
-
$product_field = rgar( $product, 'product' );
|
61 |
-
$option_fields = rgar( $product, 'options' );
|
62 |
-
$quantity_field = rgar( $product, 'quantity' );
|
63 |
-
|
64 |
-
// do not include current field in subtotal
|
65 |
-
if( $product_field['id'] == $current_field['id'] )
|
66 |
-
continue;
|
67 |
-
|
68 |
-
$product_tags = GFCommon::get_field_merge_tags( $product_field );
|
69 |
-
$quantity_tag = 1;
|
70 |
-
|
71 |
-
// if a single product type, only get the "price" merge tag
|
72 |
-
if( in_array( GFFormsModel::get_input_type( $product_field ), array( 'singleproduct', 'calculation', 'hiddenproduct' ) ) ) {
|
73 |
-
|
74 |
-
// single products provide quantity merge tag
|
75 |
-
if( empty( $quantity_field ) && ! rgar( $product_field, 'disableQuantity' ) )
|
76 |
-
$quantity_tag = $product_tags[2]['tag'];
|
77 |
-
|
78 |
-
$product_tags = array( $product_tags[1] );
|
79 |
-
}
|
80 |
-
|
81 |
-
// if quantity field is provided for product, get merge tag
|
82 |
-
if( ! empty( $quantity_field ) ) {
|
83 |
-
$quantity_tag = GFCommon::get_field_merge_tags( $quantity_field );
|
84 |
-
$quantity_tag = $quantity_tag[0]['tag'];
|
85 |
-
}
|
86 |
-
|
87 |
-
if( $filter_tags && ! self::has_valid_quantity( $quantity_tag ) )
|
88 |
-
continue;
|
89 |
-
|
90 |
-
$product_tags = wp_list_pluck( $product_tags, 'tag' );
|
91 |
-
$option_tags = array();
|
92 |
-
|
93 |
-
foreach( $option_fields as $option_field ) {
|
94 |
-
|
95 |
-
if( is_array( $option_field['inputs'] ) ) {
|
96 |
-
|
97 |
-
$choice_number = 1;
|
98 |
-
|
99 |
-
$inputs = $option_field['inputs'];
|
100 |
-
|
101 |
-
foreach( $inputs as &$input ) {
|
102 |
-
|
103 |
-
//hack to skip numbers ending in 0. so that 5.1 doesn't conflict with 5.10
|
104 |
-
if( $choice_number % 10 == 0 )
|
105 |
-
$choice_number++;
|
106 |
-
|
107 |
-
$input['id'] = $option_field['id'] . '.' . $choice_number++;
|
108 |
-
|
109 |
-
}
|
110 |
-
}
|
111 |
-
|
112 |
-
$new_options_tags = GFCommon::get_field_merge_tags( $option_field );
|
113 |
-
if( ! is_array( $new_options_tags ) )
|
114 |
-
continue;
|
115 |
-
|
116 |
-
if( GFFormsModel::get_input_type( $option_field ) == 'checkbox' )
|
117 |
-
array_shift( $new_options_tags );
|
118 |
-
|
119 |
-
$option_tags = array_merge( $option_tags, $new_options_tags );
|
120 |
-
}
|
121 |
-
|
122 |
-
$option_tags = wp_list_pluck( $option_tags, 'tag' );
|
123 |
-
|
124 |
-
$product_tag_groups[] = '( ( ' . implode( ' + ', array_merge( $product_tags, $option_tags ) ) . ' ) * ' . $quantity_tag . ' )';
|
125 |
-
|
126 |
-
}
|
127 |
-
|
128 |
-
$shipping_tag = 0;
|
129 |
-
/* Shipping should not be included in subtotal, correct?
|
130 |
-
if( rgar( $pricing_fields, 'shipping' ) ) {
|
131 |
-
$shipping_tag = GFCommon::get_field_merge_tags( rgars( $pricing_fields, 'shipping/0' ) );
|
132 |
-
$shipping_tag = $shipping_tag[0]['tag'];
|
133 |
-
}*/
|
134 |
-
|
135 |
-
$pricing_tag_string = '( ( ' . implode( ' + ', $product_tag_groups ) . ' ) + ' . $shipping_tag . ' )';
|
136 |
-
|
137 |
-
return $pricing_tag_string;
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* Get all pricing fields from a given form object grouped by product and shipping with options nested under their
|
142 |
-
* respective products.
|
143 |
-
*
|
144 |
-
* @param mixed $form
|
145 |
-
*/
|
146 |
-
static function get_pricing_fields( $form ) {
|
147 |
-
|
148 |
-
$product_fields = array();
|
149 |
-
|
150 |
-
foreach( $form["fields"] as $field ) {
|
151 |
-
|
152 |
-
if( $field["type"] != 'product' )
|
153 |
-
continue;
|
154 |
-
|
155 |
-
$option_fields = GFCommon::get_product_fields_by_type($form, array("option"), $field['id'] );
|
156 |
-
|
157 |
-
// can only have 1 quantity field
|
158 |
-
$quantity_field = GFCommon::get_product_fields_by_type( $form, array("quantity"), $field['id'] );
|
159 |
-
$quantity_field = rgar( $quantity_field, 0 );
|
160 |
-
|
161 |
-
$product_fields[] = array(
|
162 |
-
'product' => $field,
|
163 |
-
'options' => $option_fields,
|
164 |
-
'quantity' => $quantity_field
|
165 |
-
);
|
166 |
-
|
167 |
-
}
|
168 |
-
|
169 |
-
$shipping_field = GFCommon::get_fields_by_type($form, array("shipping"));
|
170 |
-
|
171 |
-
return array( "products" => $product_fields, "shipping" => $shipping_field );
|
172 |
-
}
|
173 |
-
|
174 |
-
static function has_valid_quantity( $quantity_tag ) {
|
175 |
-
|
176 |
-
if( is_numeric( $quantity_tag ) ) {
|
177 |
-
|
178 |
-
$qty_value = $quantity_tag;
|
179 |
-
|
180 |
-
} else {
|
181 |
-
|
182 |
-
// extract qty input ID from the merge tag
|
183 |
-
preg_match_all( '/{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/mi', $quantity_tag, $matches, PREG_SET_ORDER );
|
184 |
-
$qty_input_id = rgars( $matches, '0/1' );
|
185 |
-
$qty_value = rgpost( 'input_' . str_replace( '.', '_', $qty_input_id ) );
|
186 |
-
|
187 |
-
}
|
188 |
-
|
189 |
-
return floatval( $qty_value ) > 0;
|
190 |
-
}
|
191 |
-
|
192 |
-
function add_merge_tags( $form ) {
|
193 |
-
|
194 |
-
$label = __('Subtotal', 'GF_FA');
|
195 |
-
|
196 |
-
?>
|
197 |
-
|
198 |
-
<script type="text/javascript">
|
199 |
-
|
200 |
-
// for the future (not yet supported for calc field)
|
201 |
-
gform.addFilter("gform_merge_tags", "gfircs_add_merge_tags");
|
202 |
-
function gfircs_add_merge_tags( mergeTags, elementId, hideAllFields, excludeFieldTypes, isPrepop, option ) {
|
203 |
-
mergeTags["pricing"].tags.push({ tag: '<?php echo self::$merge_tag; ?>', label: '<?php echo $label; ?>' });
|
204 |
-
return mergeTags;
|
205 |
-
}
|
206 |
-
|
207 |
-
// hacky, but only temporary
|
208 |
-
jQuery(document).ready(function($){
|
209 |
-
|
210 |
-
var calcMergeTagSelect = $('#field_calculation_formula_variable_select');
|
211 |
-
calcMergeTagSelect.find('optgroup').eq(0).append( '<option value="<?php echo self::$merge_tag; ?>"><?php echo $label; ?></option>' );
|
212 |
-
|
213 |
-
});
|
214 |
-
|
215 |
-
</script>
|
216 |
-
|
217 |
-
<?php
|
218 |
-
//return the form object from the php hook
|
219 |
-
return $form;
|
220 |
-
}
|
221 |
-
|
222 |
-
static function has_subtotal_merge_tag( $field ) {
|
223 |
-
|
224 |
-
// check if form is passed
|
225 |
-
if( isset( $field['fields'] ) ) {
|
226 |
-
|
227 |
-
$form = $field;
|
228 |
-
foreach( $form['fields'] as $field ) {
|
229 |
-
if( self::has_subtotal_merge_tag( $field ) )
|
230 |
-
return true;
|
231 |
-
}
|
232 |
-
|
233 |
-
} else {
|
234 |
-
|
235 |
-
if( isset( $field['calculationFormula'] ) && strpos( $field['calculationFormula'], self::$merge_tag ) !== false )
|
236 |
-
return true;
|
237 |
-
|
238 |
-
}
|
239 |
-
|
240 |
-
return false;
|
241 |
-
}
|
242 |
-
|
243 |
-
}
|
244 |
-
|
245 |
-
new GFParsi_CalcSubtotal();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/class-transaction-id.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
}
|
4 |
+
|
5 |
+
class GFPersian_Transaction_ID extends GFPersian_Core {
|
6 |
+
|
7 |
+
private $transaction_id_title;
|
8 |
+
|
9 |
+
public function __construct() {
|
10 |
+
|
11 |
+
if ( $this->option( 'enable_transaction_id', '1' ) != '1' ) {
|
12 |
+
return;
|
13 |
+
}
|
14 |
+
|
15 |
+
$this->transaction_id_title = $this->option( 'transaction_id_title', __( 'Transaction Id', 'gravityforms' ) );
|
16 |
+
|
17 |
+
add_filter( 'gettext', array( $this, 'change_transaction_id_title' ), 999, 3 );
|
18 |
+
add_filter( 'ngettext', array( $this, 'change_transaction_id_title' ), 999, 3 );
|
19 |
+
add_action( 'gform_entry_created', array( $this, 'create_transaction_id' ), 10, 2 );
|
20 |
+
}
|
21 |
+
|
22 |
+
public function create_transaction_id( $entry, $form ) {
|
23 |
+
|
24 |
+
$default_mask = '9999999999';
|
25 |
+
$masked_input = $this->option( 'transaction_id_mask', $default_mask );
|
26 |
+
$masked_input = apply_filters( 'gform_transaction_id', $masked_input, $entry, $form );
|
27 |
+
$masked_input = ! empty( $masked_input ) ? $masked_input : $default_mask;
|
28 |
+
|
29 |
+
$transaction_id = '';
|
30 |
+
foreach ( str_split( $masked_input ) as $string ) {
|
31 |
+
if ( in_array( $string, array( '*', 'a' ) ) ) {
|
32 |
+
$rand = $string == '*' ? array_map( 'strval', range( 0, 9 ) ) : array();
|
33 |
+
$rand = array_merge( $rand, range( 'A', 'Z' ), range( 'a', 'z' ) );
|
34 |
+
shuffle( $rand );
|
35 |
+
$transaction_id .= $rand[ rand( 0, count( $rand ) - 1 ) ];
|
36 |
+
} elseif ( $string == '9' ) {
|
37 |
+
$transaction_id .= rand( 0, 9 );
|
38 |
+
} else {
|
39 |
+
$transaction_id .= $string;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
GFAPI::update_entry_property( $entry['id'], 'transaction_id', $transaction_id );
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
public function change_transaction_id_title( $translated_text, $untranslated_text, $domain ) {
|
48 |
+
if ( $domain == 'gravityforms' && strtolower( $untranslated_text ) == 'transaction id' ) {
|
49 |
+
|
50 |
+
return $this->transaction_id_title;
|
51 |
+
}
|
52 |
+
|
53 |
+
return $translated_text;
|
54 |
+
}
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
new GFPersian_Transaction_ID;
|
includes/class-wpp-gravity-forms.php
DELETED
@@ -1,116 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Makes GravityForms compatible with wp-parsidate plugin
|
4 |
-
*
|
5 |
-
* @package Persian-Gravity-Forms
|
6 |
-
* @author HANNANStd
|
7 |
-
*/
|
8 |
-
class WPP_GravityForms {
|
9 |
-
|
10 |
-
public static $instance = null;
|
11 |
-
|
12 |
-
public $font = 'yekan';
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Returns an instance of class
|
16 |
-
*
|
17 |
-
* @return WPP_GravityForms
|
18 |
-
*/
|
19 |
-
public static function getInstance() {
|
20 |
-
if ( self::$instance == null )
|
21 |
-
self::$instance = new WPP_GravityForms();
|
22 |
-
|
23 |
-
return self::$instance;
|
24 |
-
}
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Hooks required tags
|
28 |
-
*/
|
29 |
-
public function __construct() {
|
30 |
-
|
31 |
-
if ( ! class_exists('GFCommon') ) {
|
32 |
-
return;
|
33 |
-
}
|
34 |
-
|
35 |
-
global $wpp_settings;
|
36 |
-
|
37 |
-
if ( !empty($wpp_settings) && $wpp_settings ) {
|
38 |
-
|
39 |
-
if ( ! isset( $wpp_settings[ 'droidsans_admin' ] ) || $wpp_settings[ 'droidsans_admin' ] != 'disable' ) {
|
40 |
-
|
41 |
-
add_filter( 'wpp_plugins_compability_settings', array( $this, 'add_settings' ) );
|
42 |
-
|
43 |
-
if ( ! isset( $wpp_settings['gravityforms_droidsans_admin'] ) || $wpp_settings['gravityforms_droidsans_admin'] != 'disable' ) {
|
44 |
-
$this->font = 'droidsans';
|
45 |
-
}
|
46 |
-
}
|
47 |
-
|
48 |
-
|
49 |
-
}
|
50 |
-
|
51 |
-
add_action('admin_enqueue_scripts', array( $this, 'admin_script' ));
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Adds desired fonts
|
56 |
-
*/
|
57 |
-
public function admin_script() {
|
58 |
-
|
59 |
-
if ( is_rtl() && $this->is_gravity_page() ) {
|
60 |
-
wp_register_style( 'gravity-forms-admin-' . $this->font , GF_PARSI_URL . 'assets/css/font.' . $this->font . '.css' );
|
61 |
-
wp_enqueue_style( 'gravity-forms-admin-' . $this->font );
|
62 |
-
}
|
63 |
-
}
|
64 |
-
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Checks is gravityforms page
|
68 |
-
*
|
69 |
-
*/
|
70 |
-
public function is_gravity_page() {
|
71 |
-
|
72 |
-
if ( !class_exists('RGForms') )
|
73 |
-
return false;
|
74 |
-
|
75 |
-
$current_page = trim(strtolower(RGForms::get("page")));
|
76 |
-
return ( substr( $current_page , 0 , 2) == 'gf' || stripos( $current_page, 'gravity' ) !== false );
|
77 |
-
}
|
78 |
-
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Adds settings for toggle fixing
|
82 |
-
*
|
83 |
-
* @param array $old_settings Old settings
|
84 |
-
* @return array New settings
|
85 |
-
*/
|
86 |
-
public function add_settings( $old_settings ) {
|
87 |
-
|
88 |
-
$options = array(
|
89 |
-
'enable' => __( 'Enable', 'wp-parsidate' ),
|
90 |
-
'disable' => __( 'Disable', 'wp-parsidate' )
|
91 |
-
);
|
92 |
-
|
93 |
-
$settings = array(
|
94 |
-
'gravityforms' => array(
|
95 |
-
'id' => 'gravityforms',
|
96 |
-
'name' => __( 'GravityForms', 'GF_FA' ),
|
97 |
-
'type' => 'header'
|
98 |
-
),
|
99 |
-
'gravityforms_droidsans_admin' => array(
|
100 |
-
'id' => 'gravityforms_droidsans_admin',
|
101 |
-
'name' => __( 'Use Droid Sans font for GravityForms Admin', 'GF_FA' ),
|
102 |
-
'type' => 'radio',
|
103 |
-
'options' => $options,
|
104 |
-
'std' => 'enable',
|
105 |
-
'desc' => __( 'By GravityForms.ir', 'GF_FA' )
|
106 |
-
),
|
107 |
-
);
|
108 |
-
|
109 |
-
return array_merge( $old_settings, $settings );
|
110 |
-
}
|
111 |
-
}
|
112 |
-
|
113 |
-
add_action('plugins_loaded', 'wpp_gravity_forms', 0);
|
114 |
-
function wpp_gravity_forms() {
|
115 |
-
WPP_GravityForms::getInstance();
|
116 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
includes/lib/jalali.php
ADDED
@@ -0,0 +1,755 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/* In The Name Of Allah */
|
3 |
+
/** Software Hijri_Shamsi , Solar(Jalali) Date and Time
|
4 |
+
* Copyright(C)2011, Reza Gholampanahi , http://jdf.scr.ir
|
5 |
+
* version 2.55 :: 1391/08/24 = 1433/12/18 = 2012/11/15
|
6 |
+
/* [ jdf.php ] version 2.55 ?> Download new version from [ http://jdf.scr.ir ] */
|
7 |
+
/*--- EDITED BY HANNANStd ---*/
|
8 |
+
|
9 |
+
/**/
|
10 |
+
/* F */
|
11 |
+
function GF_jdate( $format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa' ) {
|
12 |
+
|
13 |
+
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
14 |
+
|
15 |
+
if ( $time_zone != 'local' ) {
|
16 |
+
date_default_timezone_set( ( $time_zone == '' ) ? 'Asia/Tehran' : $time_zone );
|
17 |
+
}
|
18 |
+
|
19 |
+
$ts = $T_sec + ( ( $timestamp == '' or $timestamp == 'now' ) ? time() : GF_tr_num( $timestamp ) );
|
20 |
+
$date = explode( '_', date( 'H_i_j_n_O_P_s_w_Y', $ts ) );
|
21 |
+
list( $j_y, $j_m, $j_d ) = GF_gregorian_to_jalali( $date[8], $date[3], $date[2] );
|
22 |
+
$doy = ( $j_m < 7 ) ? ( ( $j_m - 1 ) * 31 ) + $j_d - 1 : ( ( $j_m - 7 ) * 30 ) + $j_d + 185;
|
23 |
+
$kab = ( $j_y % 33 % 4 - 1 == (int) ( $j_y % 33 * .05 ) ) ? 1 : 0;
|
24 |
+
$sl = strlen( $format );
|
25 |
+
$out = '';
|
26 |
+
|
27 |
+
for ( $i = 0; $i < $sl; $i ++ ) {
|
28 |
+
$sub = substr( $format, $i, 1 );
|
29 |
+
if ( $sub == '\\' ) {
|
30 |
+
$out .= substr( $format, ++ $i, 1 );
|
31 |
+
continue;
|
32 |
+
}
|
33 |
+
|
34 |
+
switch ( $sub ) {
|
35 |
+
case'E':
|
36 |
+
case'R':
|
37 |
+
case'x':
|
38 |
+
case'X':
|
39 |
+
$out .= 'http://jdf.scr.ir';
|
40 |
+
break;
|
41 |
+
|
42 |
+
case'B':
|
43 |
+
case'e':
|
44 |
+
case'g':
|
45 |
+
case'G':
|
46 |
+
case'h':
|
47 |
+
case'I':
|
48 |
+
case'T':
|
49 |
+
case'u':
|
50 |
+
case'Z':
|
51 |
+
$out .= date( $sub, $ts );
|
52 |
+
break;
|
53 |
+
|
54 |
+
case'a':
|
55 |
+
$out .= ( $date[0] < 12 ) ? 'ق.ظ' : 'ب.ظ';
|
56 |
+
break;
|
57 |
+
|
58 |
+
case'A':
|
59 |
+
$out .= ( $date[0] < 12 ) ? 'قبل از ظهر' : 'بعد از ظهر';
|
60 |
+
break;
|
61 |
+
|
62 |
+
case'b':
|
63 |
+
$out .= (int) ( $j_m / 3.1 ) + 1;
|
64 |
+
break;
|
65 |
+
|
66 |
+
case'c':
|
67 |
+
$out .= $j_y . '/' . $j_m . '/' . $j_d . ' ،' . $date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[5];
|
68 |
+
break;
|
69 |
+
|
70 |
+
case'C':
|
71 |
+
$out .= (int) ( ( $j_y + 99 ) / 100 );
|
72 |
+
break;
|
73 |
+
|
74 |
+
case'd':
|
75 |
+
$out .= ( $j_d < 10 ) ? '0' . $j_d : $j_d;
|
76 |
+
break;
|
77 |
+
|
78 |
+
case'D':
|
79 |
+
$out .= GF_jdate_words( array( 'kh' => $date[7] ), ' ' );
|
80 |
+
break;
|
81 |
+
|
82 |
+
case'f':
|
83 |
+
$out .= GF_jdate_words( array( 'ff' => $j_m ), ' ' );
|
84 |
+
break;
|
85 |
+
|
86 |
+
case'F':
|
87 |
+
$out .= GF_jdate_words( array( 'mm' => $j_m ), ' ' );
|
88 |
+
break;
|
89 |
+
|
90 |
+
case'H':
|
91 |
+
$out .= $date[0];
|
92 |
+
break;
|
93 |
+
|
94 |
+
case'i':
|
95 |
+
$out .= $date[1];
|
96 |
+
break;
|
97 |
+
|
98 |
+
case'j':
|
99 |
+
$out .= $j_d;
|
100 |
+
break;
|
101 |
+
|
102 |
+
case'J':
|
103 |
+
$out .= GF_jdate_words( array( 'rr' => $j_d ), ' ' );
|
104 |
+
break;
|
105 |
+
|
106 |
+
case'k';
|
107 |
+
$out .= GF_tr_num( 100 - (int) ( $doy / ( $kab + 365 ) * 1000 ) / 10, $tr_num );
|
108 |
+
break;
|
109 |
+
|
110 |
+
case'K':
|
111 |
+
$out .= GF_tr_num( (int) ( $doy / ( $kab + 365 ) * 1000 ) / 10, $tr_num );
|
112 |
+
break;
|
113 |
+
|
114 |
+
case'l':
|
115 |
+
$out .= GF_jdate_words( array( 'rh' => $date[7] ), ' ' );
|
116 |
+
break;
|
117 |
+
|
118 |
+
case'L':
|
119 |
+
$out .= $kab;
|
120 |
+
break;
|
121 |
+
|
122 |
+
case'm':
|
123 |
+
$out .= ( $j_m > 9 ) ? $j_m : '0' . $j_m;
|
124 |
+
break;
|
125 |
+
|
126 |
+
case'M':
|
127 |
+
$out .= GF_jdate_words( array( 'km' => $j_m ), ' ' );
|
128 |
+
break;
|
129 |
+
|
130 |
+
case'n':
|
131 |
+
$out .= $j_m;
|
132 |
+
break;
|
133 |
+
|
134 |
+
case'N':
|
135 |
+
$out .= $date[7] + 1;
|
136 |
+
break;
|
137 |
+
|
138 |
+
case'o':
|
139 |
+
$jdw = ( $date[7] == 6 ) ? 0 : $date[7] + 1;
|
140 |
+
$dny = 364 + $kab - $doy;
|
141 |
+
$out .= ( $jdw > ( $doy + 3 ) and $doy < 3 ) ? $j_y - 1 : ( ( ( 3 - $dny ) > $jdw and $dny < 3 ) ? $j_y + 1 : $j_y );
|
142 |
+
break;
|
143 |
+
|
144 |
+
case'O':
|
145 |
+
$out .= $date[4];
|
146 |
+
break;
|
147 |
+
|
148 |
+
case'p':
|
149 |
+
$out .= GF_jdate_words( array( 'mb' => $j_m ), ' ' );
|
150 |
+
break;
|
151 |
+
|
152 |
+
case'P':
|
153 |
+
$out .= $date[5];
|
154 |
+
break;
|
155 |
+
|
156 |
+
case'q':
|
157 |
+
$out .= GF_jdate_words( array( 'sh' => $j_y ), ' ' );
|
158 |
+
break;
|
159 |
+
|
160 |
+
case'Q':
|
161 |
+
$out .= $kab + 364 - $doy;
|
162 |
+
break;
|
163 |
+
|
164 |
+
case'r':
|
165 |
+
$key = GF_jdate_words( array( 'rh' => $date[7], 'mm' => $j_m ) );
|
166 |
+
$out .= $date[0] . ':' . $date[1] . ':' . $date[6] . ' ' . $date[4] . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
|
167 |
+
break;
|
168 |
+
|
169 |
+
case's':
|
170 |
+
$out .= $date[6];
|
171 |
+
break;
|
172 |
+
|
173 |
+
case'S':
|
174 |
+
$out .= 'ام';
|
175 |
+
break;
|
176 |
+
|
177 |
+
case't':
|
178 |
+
$out .= ( $j_m != 12 ) ? ( 31 - (int) ( $j_m / 6.5 ) ) : ( $kab + 29 );
|
179 |
+
break;
|
180 |
+
|
181 |
+
case'U':
|
182 |
+
$out .= $ts;
|
183 |
+
break;
|
184 |
+
|
185 |
+
case'v':
|
186 |
+
$out .= GF_jdate_words( array( 'ss' => substr( $j_y, 2, 2 ) ), ' ' );
|
187 |
+
break;
|
188 |
+
|
189 |
+
case'V':
|
190 |
+
$out .= GF_jdate_words( array( 'ss' => $j_y ), ' ' );
|
191 |
+
break;
|
192 |
+
|
193 |
+
case'w':
|
194 |
+
$out .= ( $date[7] == 6 ) ? 0 : $date[7] + 1;
|
195 |
+
break;
|
196 |
+
|
197 |
+
case'W':
|
198 |
+
$avs = ( ( $date[7] == 6 ) ? 0 : $date[7] + 1 ) - ( $doy % 7 );
|
199 |
+
if ( $avs < 0 ) {
|
200 |
+
$avs += 7;
|
201 |
+
}
|
202 |
+
$num = (int) ( ( $doy + $avs ) / 7 );
|
203 |
+
if ( $avs < 4 ) {
|
204 |
+
$num ++;
|
205 |
+
} elseif ( $num < 1 ) {
|
206 |
+
$num = ( $avs == 4 or $avs == ( ( $j_y % 33 % 4 - 2 == (int) ( $j_y % 33 * .05 ) ) ? 5 : 4 ) ) ? 53 : 52;
|
207 |
+
}
|
208 |
+
$aks = $avs + $kab;
|
209 |
+
if ( $aks == 7 ) {
|
210 |
+
$aks = 0;
|
211 |
+
}
|
212 |
+
$out .= ( ( $kab + 363 - $doy ) < $aks and $aks < 3 ) ? '01' : ( ( $num < 10 ) ? '0' . $num : $num );
|
213 |
+
break;
|
214 |
+
|
215 |
+
case'y':
|
216 |
+
$out .= substr( $j_y, 2, 2 );
|
217 |
+
break;
|
218 |
+
|
219 |
+
case'Y':
|
220 |
+
$out .= $j_y;
|
221 |
+
break;
|
222 |
+
|
223 |
+
case'z':
|
224 |
+
$out .= $doy;
|
225 |
+
break;
|
226 |
+
|
227 |
+
default:
|
228 |
+
$out .= $sub;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
|
232 |
+
return ( $tr_num != 'en' ) ? GF_tr_num( $out, 'fa', '.' ) : $out;
|
233 |
+
}
|
234 |
+
|
235 |
+
/* F */
|
236 |
+
function GF_jstrftime( $format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa' ) {
|
237 |
+
|
238 |
+
$T_sec = 0;/* <= رفع خطاي زمان سرور ، با اعداد '+' و '-' بر حسب ثانيه */
|
239 |
+
if ( $time_zone != 'local' ) {
|
240 |
+
date_default_timezone_set( ( $time_zone == '' ) ? 'Asia/Tehran' : $time_zone );
|
241 |
+
}
|
242 |
+
|
243 |
+
$ts = $T_sec + ( ( $timestamp == '' or $timestamp == 'now' ) ? time() : GF_tr_num( $timestamp ) );
|
244 |
+
$date = explode( '_', date( 'h_H_i_j_n_s_w_Y', $ts ) );
|
245 |
+
list( $j_y, $j_m, $j_d ) = GF_gregorian_to_jalali( $date[7], $date[4], $date[3] );
|
246 |
+
$doy = ( $j_m < 7 ) ? ( ( $j_m - 1 ) * 31 ) + $j_d - 1 : ( ( $j_m - 7 ) * 30 ) + $j_d + 185;
|
247 |
+
|
248 |
+
$kab = ( $j_y % 33 % 4 - 1 == (int) ( $j_y % 33 * .05 ) ) ? 1 : 0;
|
249 |
+
$sl = strlen( $format );
|
250 |
+
$out = '';
|
251 |
+
for ( $i = 0; $i < $sl; $i ++ ) {
|
252 |
+
|
253 |
+
$sub = substr( $format, $i, 1 );
|
254 |
+
|
255 |
+
if ( $sub == '%' ) {
|
256 |
+
$sub = substr( $format, ++ $i, 1 );
|
257 |
+
} else {
|
258 |
+
$out .= $sub;
|
259 |
+
continue;
|
260 |
+
}
|
261 |
+
|
262 |
+
switch ( $sub ) {
|
263 |
+
|
264 |
+
/* Day */
|
265 |
+
case'a':
|
266 |
+
$out .= GF_jdate_words( array( 'kh' => $date[6] ), ' ' );
|
267 |
+
break;
|
268 |
+
|
269 |
+
case'A':
|
270 |
+
$out .= GF_jdate_words( array( 'rh' => $date[6] ), ' ' );
|
271 |
+
break;
|
272 |
+
|
273 |
+
case'd':
|
274 |
+
$out .= ( $j_d < 10 ) ? '0' . $j_d : $j_d;
|
275 |
+
break;
|
276 |
+
|
277 |
+
case'e':
|
278 |
+
$out .= ( $j_d < 10 ) ? ' ' . $j_d : $j_d;
|
279 |
+
break;
|
280 |
+
|
281 |
+
case'j':
|
282 |
+
$out .= str_pad( $doy + 1, 3, 0, STR_PAD_LEFT );
|
283 |
+
break;
|
284 |
+
|
285 |
+
case'u':
|
286 |
+
$out .= $date[6] + 1;
|
287 |
+
break;
|
288 |
+
|
289 |
+
case'w':
|
290 |
+
$out .= ( $date[6] == 6 ) ? 0 : $date[6] + 1;
|
291 |
+
break;
|
292 |
+
|
293 |
+
/* Week */
|
294 |
+
case'U':
|
295 |
+
$avs = ( ( $date[6] < 5 ) ? $date[6] + 2 : $date[6] - 5 ) - ( $doy % 7 );
|
296 |
+
if ( $avs < 0 ) {
|
297 |
+
$avs += 7;
|
298 |
+
}
|
299 |
+
$num = (int) ( ( $doy + $avs ) / 7 ) + 1;
|
300 |
+
if ( $avs > 3 or $avs == 1 ) {
|
301 |
+
$num --;
|
302 |
+
}
|
303 |
+
$out .= ( $num < 10 ) ? '0' . $num : $num;
|
304 |
+
break;
|
305 |
+
|
306 |
+
case'V':
|
307 |
+
$avs = ( ( $date[6] == 6 ) ? 0 : $date[6] + 1 ) - ( $doy % 7 );
|
308 |
+
|
309 |
+
if ( $avs < 0 ) {
|
310 |
+
$avs += 7;
|
311 |
+
}
|
312 |
+
$num = (int) ( ( $doy + $avs ) / 7 );
|
313 |
+
|
314 |
+
if ( $avs < 4 ) {
|
315 |
+
$num ++;
|
316 |
+
} elseif ( $num < 1 ) {
|
317 |
+
$num = ( $avs == 4 or $avs == ( ( $j_y % 33 % 4 - 2 == (int) ( $j_y % 33 * .05 ) ) ? 5 : 4 ) ) ? 53 : 52;
|
318 |
+
}
|
319 |
+
|
320 |
+
$aks = $avs + $kab;
|
321 |
+
if ( $aks == 7 ) {
|
322 |
+
$aks = 0;
|
323 |
+
}
|
324 |
+
$out .= ( ( $kab + 363 - $doy ) < $aks and $aks < 3 ) ? '01' : ( ( $num < 10 ) ? '0' . $num : $num );
|
325 |
+
break;
|
326 |
+
|
327 |
+
case'W':
|
328 |
+
$avs = ( ( $date[6] == 6 ) ? 0 : $date[6] + 1 ) - ( $doy % 7 );
|
329 |
+
if ( $avs < 0 ) {
|
330 |
+
$avs += 7;
|
331 |
+
}
|
332 |
+
$num = (int) ( ( $doy + $avs ) / 7 ) + 1;
|
333 |
+
if ( $avs > 3 ) {
|
334 |
+
$num --;
|
335 |
+
}
|
336 |
+
$out .= ( $num < 10 ) ? '0' . $num : $num;
|
337 |
+
break;
|
338 |
+
|
339 |
+
/* Month */
|
340 |
+
case'b':
|
341 |
+
case'h':
|
342 |
+
$out .= GF_jdate_words( array( 'km' => $j_m ), ' ' );
|
343 |
+
break;
|
344 |
+
|
345 |
+
case'B':
|
346 |
+
$out .= GF_jdate_words( array( 'mm' => $j_m ), ' ' );
|
347 |
+
break;
|
348 |
+
|
349 |
+
case'm':
|
350 |
+
$out .= ( $j_m > 9 ) ? $j_m : '0' . $j_m;
|
351 |
+
break;
|
352 |
+
|
353 |
+
/* Year */
|
354 |
+
case'C':
|
355 |
+
$out .= substr( $j_y, 0, 2 );
|
356 |
+
break;
|
357 |
+
|
358 |
+
case'g':
|
359 |
+
$jdw = ( $date[6] == 6 ) ? 0 : $date[6] + 1;
|
360 |
+
$dny = 364 + $kab - $doy;
|
361 |
+
$out .= substr( ( $jdw > ( $doy + 3 ) and $doy < 3 ) ? $j_y - 1 : ( ( ( 3 - $dny ) > $jdw and $dny < 3 ) ? $j_y + 1 : $j_y ), 2, 2 );
|
362 |
+
break;
|
363 |
+
|
364 |
+
case'G':
|
365 |
+
$jdw = ( $date[6] == 6 ) ? 0 : $date[6] + 1;
|
366 |
+
$dny = 364 + $kab - $doy;
|
367 |
+
$out .= ( $jdw > ( $doy + 3 ) and $doy < 3 ) ? $j_y - 1 : ( ( ( 3 - $dny ) > $jdw and $dny < 3 ) ? $j_y + 1 : $j_y );
|
368 |
+
break;
|
369 |
+
|
370 |
+
case'y':
|
371 |
+
$out .= substr( $j_y, 2, 2 );
|
372 |
+
break;
|
373 |
+
|
374 |
+
case'Y':
|
375 |
+
$out .= $j_y;
|
376 |
+
break;
|
377 |
+
|
378 |
+
/* Time */
|
379 |
+
case'H':
|
380 |
+
$out .= $date[1];
|
381 |
+
break;
|
382 |
+
|
383 |
+
case'I':
|
384 |
+
$out .= $date[0];
|
385 |
+
break;
|
386 |
+
|
387 |
+
case'l':
|
388 |
+
$out .= ( $date[0] > 9 ) ? $date[0] : ' ' . (int) $date[0];
|
389 |
+
break;
|
390 |
+
|
391 |
+
case'M':
|
392 |
+
$out .= $date[2];
|
393 |
+
break;
|
394 |
+
|
395 |
+
case'p':
|
396 |
+
$out .= ( $date[1] < 12 ) ? 'قبل از ظهر' : 'بعد از ظهر';
|
397 |
+
break;
|
398 |
+
|
399 |
+
case'P':
|
400 |
+
$out .= ( $date[1] < 12 ) ? 'ق.ظ' : 'ب.ظ';
|
401 |
+
break;
|
402 |
+
|
403 |
+
case'r':
|
404 |
+
$out .= $date[0] . ':' . $date[2] . ':' . $date[5] . ' ' . ( ( $date[1] < 12 ) ? 'قبل از ظهر' : 'بعد از ظهر' );
|
405 |
+
break;
|
406 |
+
|
407 |
+
case'R':
|
408 |
+
$out .= $date[1] . ':' . $date[2];
|
409 |
+
break;
|
410 |
+
|
411 |
+
case'S':
|
412 |
+
$out .= $date[5];
|
413 |
+
break;
|
414 |
+
|
415 |
+
case'T':
|
416 |
+
$out .= $date[1] . ':' . $date[2] . ':' . $date[5];
|
417 |
+
break;
|
418 |
+
|
419 |
+
case'X':
|
420 |
+
$out .= $date[0] . ':' . $date[2] . ':' . $date[5];
|
421 |
+
break;
|
422 |
+
|
423 |
+
case'z':
|
424 |
+
$out .= date( 'O', $ts );
|
425 |
+
break;
|
426 |
+
|
427 |
+
case'Z':
|
428 |
+
$out .= date( 'T', $ts );
|
429 |
+
break;
|
430 |
+
|
431 |
+
/* Time and Date Stamps */
|
432 |
+
case'c':
|
433 |
+
$key = GF_jdate_words( array( 'rh' => $date[6], 'mm' => $j_m ) );
|
434 |
+
$out .= $date[1] . ':' . $date[2] . ':' . $date[5] . ' ' . date( 'P', $ts ) . ' ' . $key['rh'] . '، ' . $j_d . ' ' . $key['mm'] . ' ' . $j_y;
|
435 |
+
break;
|
436 |
+
|
437 |
+
case'D':
|
438 |
+
$out .= substr( $j_y, 2, 2 ) . '/' . ( ( $j_m > 9 ) ? $j_m : '0' . $j_m ) . '/' . ( ( $j_d < 10 ) ? '0' . $j_d : $j_d );
|
439 |
+
break;
|
440 |
+
|
441 |
+
case'F':
|
442 |
+
$out .= $j_y . '-' . ( ( $j_m > 9 ) ? $j_m : '0' . $j_m ) . '-' . ( ( $j_d < 10 ) ? '0' . $j_d : $j_d );
|
443 |
+
break;
|
444 |
+
|
445 |
+
case's':
|
446 |
+
$out .= $ts;
|
447 |
+
break;
|
448 |
+
|
449 |
+
case'x':
|
450 |
+
$out .= substr( $j_y, 2, 2 ) . '/' . ( ( $j_m > 9 ) ? $j_m : '0' . $j_m ) . '/' . ( ( $j_d < 10 ) ? '0' . $j_d : $j_d );
|
451 |
+
break;
|
452 |
+
|
453 |
+
/* Miscellaneous */
|
454 |
+
case'n':
|
455 |
+
$out .= "\n";
|
456 |
+
break;
|
457 |
+
|
458 |
+
case't':
|
459 |
+
$out .= "\t";
|
460 |
+
break;
|
461 |
+
|
462 |
+
case'%':
|
463 |
+
$out .= '%';
|
464 |
+
break;
|
465 |
+
|
466 |
+
default:
|
467 |
+
$out .= $sub;
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
return ( $tr_num != 'en' ) ? GF_tr_num( $out, 'fa', '.' ) : $out;
|
472 |
+
}
|
473 |
+
|
474 |
+
/* F */
|
475 |
+
function GF_jmktime( $h = '', $m = '', $s = '', $jm = '', $jd = '', $jy = '', $is_dst = - 1 ) {
|
476 |
+
$h = GF_tr_num( $h );
|
477 |
+
$m = GF_tr_num( $m );
|
478 |
+
$s = GF_tr_num( $s );
|
479 |
+
$jm = GF_tr_num( $jm );
|
480 |
+
$jd = GF_tr_num( $jd );
|
481 |
+
$jy = GF_tr_num( $jy );
|
482 |
+
if ( $h == '' and $m == '' and $s == '' and $jm == '' and $jd == '' and $jy == '' ) {
|
483 |
+
return mktime();
|
484 |
+
} else {
|
485 |
+
list( $year, $month, $day ) = GF_jalali_to_gregorian( $jy, $jm, $jd );
|
486 |
+
|
487 |
+
return mktime( $h, $m, $s, $month, $day, $year, $is_dst );
|
488 |
+
}
|
489 |
+
}
|
490 |
+
|
491 |
+
|
492 |
+
/* F */
|
493 |
+
function GF_jgetdate( $timestamp = '', $none = '', $tz = 'Asia/Tehran', $tn = 'en' ) {
|
494 |
+
$ts = ( $timestamp == '' ) ? time() : GF_tr_num( $timestamp );
|
495 |
+
$jdate = explode( '_', GF_jdate( 'F_G_i_j_l_n_s_w_Y_z', $ts, '', $tz, $tn ) );
|
496 |
+
|
497 |
+
return array(
|
498 |
+
'seconds' => GF_tr_num( (int) GF_tr_num( $jdate[6] ), $tn ),
|
499 |
+
'minutes' => GF_tr_num( (int) GF_tr_num( $jdate[2] ), $tn ),
|
500 |
+
'hours' => $jdate[1],
|
501 |
+
'mday' => $jdate[3],
|
502 |
+
'wday' => $jdate[7],
|
503 |
+
'mon' => $jdate[5],
|
504 |
+
'year' => $jdate[8],
|
505 |
+
'yday' => $jdate[9],
|
506 |
+
'weekday' => $jdate[4],
|
507 |
+
'month' => $jdate[0],
|
508 |
+
0 => GF_tr_num( $ts, $tn )
|
509 |
+
);
|
510 |
+
}
|
511 |
+
|
512 |
+
/* F */
|
513 |
+
function GF_jcheckdate( $jm, $jd, $jy ) {
|
514 |
+
$jm = GF_tr_num( $jm );
|
515 |
+
$jd = GF_tr_num( $jd );
|
516 |
+
$jy = GF_tr_num( $jy );
|
517 |
+
$l_d = ( $jm == 12 ) ? ( ( $jy % 33 % 4 - 1 == (int) ( $jy % 33 * .05 ) ) ? 30 : 29 ) : 31 - (int) ( $jm / 6.5 );
|
518 |
+
|
519 |
+
return ( $jm > 0 and $jd > 0 and $jy > 0 and $jm < 13 and $jd <= $l_d ) ? true : false;
|
520 |
+
}
|
521 |
+
|
522 |
+
/* F */
|
523 |
+
function GF_tr_num( $str, $mod = 'en', $mf = '٫' ) {
|
524 |
+
$num_a = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' );
|
525 |
+
$key_a = array( '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', $mf );
|
526 |
+
|
527 |
+
return ( $mod == 'fa' ) ? str_replace( $num_a, $key_a, $str ) : str_replace( $key_a, $num_a, $str );
|
528 |
+
}
|
529 |
+
|
530 |
+
/* F */
|
531 |
+
function GF_jdate_words( $array, $mod = '' ) {
|
532 |
+
foreach ( $array as $type => $num ) {
|
533 |
+
$num = (int) GF_tr_num( $num );
|
534 |
+
switch ( $type ) {
|
535 |
+
case'ss':
|
536 |
+
$sl = strlen( $num );
|
537 |
+
$xy3 = substr( $num, 2 - $sl, 1 );
|
538 |
+
$h3 = $h34 = $h4 = '';
|
539 |
+
if ( $xy3 == 1 ) {
|
540 |
+
$p34 = '';
|
541 |
+
$k34 = array(
|
542 |
+
'ده',
|
543 |
+
'یازده',
|
544 |
+
'دوازده',
|
545 |
+
'سیزده',
|
546 |
+
'چهارده',
|
547 |
+
'پانزده',
|
548 |
+
'شانزده',
|
549 |
+
'هفده',
|
550 |
+
'هجده',
|
551 |
+
'نوزده'
|
552 |
+
);
|
553 |
+
$h34 = $k34[ substr( $num, 2 - $sl, 2 ) - 10 ];
|
554 |
+
} else {
|
555 |
+
$xy4 = substr( $num, 3 - $sl, 1 );
|
556 |
+
$p34 = ( $xy3 == 0 or $xy4 == 0 ) ? '' : ' و ';
|
557 |
+
$k3 = array( '', '', 'بیست', 'سی', 'چهل', 'پنجاه', 'شصت', 'هفتاد', 'هشتاد', 'نود' );
|
558 |
+
$h3 = $k3[ $xy3 ];
|
559 |
+
$k4 = array( '', 'یک', 'دو', 'سه', 'چهار', 'پنج', 'شش', 'هفت', 'هشت', 'نه' );
|
560 |
+
$h4 = $k4[ $xy4 ];
|
561 |
+
}
|
562 |
+
$array[ $type ] = ( ( $num > 99 ) ? str_ireplace( array( '12', '13', '14', '19', '20' ),
|
563 |
+
array( 'هزار و دویست', 'هزار و سیصد', 'هزار و چهارصد', 'هزار و نهصد', 'دوهزار' ),
|
564 |
+
substr( $num, 0, 2 ) ) . ( ( substr( $num, 2, 2 ) == '00' ) ? '' : ' و ' ) : '' ) . $h3 . $p34 . $h34 . $h4;
|
565 |
+
break;
|
566 |
+
|
567 |
+
case'mm':
|
568 |
+
$key = array(
|
569 |
+
'فروردین',
|
570 |
+
'اردیبهشت',
|
571 |
+
'خرداد',
|
572 |
+
'تیر',
|
573 |
+
'مرداد',
|
574 |
+
'شهریور',
|
575 |
+
'مهر',
|
576 |
+
'آبان',
|
577 |
+
'آذر',
|
578 |
+
'دی',
|
579 |
+
'بهمن',
|
580 |
+
'اسفند'
|
581 |
+
);
|
582 |
+
$array[ $type ] = $key[ $num - 1 ];
|
583 |
+
break;
|
584 |
+
|
585 |
+
case'rr':
|
586 |
+
$key = array(
|
587 |
+
'یک',
|
588 |
+
'دو',
|
589 |
+
'سه',
|
590 |
+
'چهار',
|
591 |
+
'پنج',
|
592 |
+
'شش',
|
593 |
+
'هفت',
|
594 |
+
'هشت',
|
595 |
+
'نه',
|
596 |
+
'ده',
|
597 |
+
'یازده',
|
598 |
+
'دوازده',
|
599 |
+
'سیزده',
|
600 |
+
'چهارده',
|
601 |
+
'پانزده',
|
602 |
+
'شانزده',
|
603 |
+
'هفده',
|
604 |
+
'هجده',
|
605 |
+
'نوزده',
|
606 |
+
'بیست',
|
607 |
+
'بیست و یک',
|
608 |
+
'بیست و دو',
|
609 |
+
'بیست و سه',
|
610 |
+
'بیست و چهار',
|
611 |
+
'بیست و پنج',
|
612 |
+
'بیست و شش',
|
613 |
+
'بیست و هفت',
|
614 |
+
'بیست و هشت',
|
615 |
+
'بیست و نه',
|
616 |
+
'سی',
|
617 |
+
'سی و یک'
|
618 |
+
);
|
619 |
+
$array[ $type ] = $key[ $num - 1 ];
|
620 |
+
break;
|
621 |
+
|
622 |
+
case'rh':
|
623 |
+
$key = array( 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه' );
|
624 |
+
$array[ $type ] = $key[ $num ];
|
625 |
+
break;
|
626 |
+
|
627 |
+
case'sh':
|
628 |
+
$key = array(
|
629 |
+
'مار',
|
630 |
+
'اسب',
|
631 |
+
'گوسفند',
|
632 |
+
'میمون',
|
633 |
+
'مرغ',
|
634 |
+
'سگ',
|
635 |
+
'خوک',
|
636 |
+
'موش',
|
637 |
+
'گاو',
|
638 |
+
'پلنگ',
|
639 |
+
'خرگوش',
|
640 |
+
'نهنگ'
|
641 |
+
);
|
642 |
+
$array[ $type ] = $key[ $num % 12 ];
|
643 |
+
break;
|
644 |
+
|
645 |
+
case'mb':
|
646 |
+
$key = array(
|
647 |
+
'حمل',
|
648 |
+
'ثور',
|
649 |
+
'جوزا',
|
650 |
+
'سرطان',
|
651 |
+
'اسد',
|
652 |
+
'سنبله',
|
653 |
+
'میزان',
|
654 |
+
'عقرب',
|
655 |
+
'قوس',
|
656 |
+
'جدی',
|
657 |
+
'دلو',
|
658 |
+
'حوت'
|
659 |
+
);
|
660 |
+
$array[ $type ] = $key[ $num - 1 ];
|
661 |
+
break;
|
662 |
+
|
663 |
+
case'ff':
|
664 |
+
$key = array( 'بهار', 'تابستان', 'پاییز', 'زمستان' );
|
665 |
+
$array[ $type ] = $key[ (int) ( $num / 3.1 ) ];
|
666 |
+
break;
|
667 |
+
|
668 |
+
case'km':
|
669 |
+
$key = array( 'فر', 'ار', 'خر', 'تی', 'مر', 'شه', 'مه', 'آب', 'آذ', 'دی', 'به', 'اس' );
|
670 |
+
$array[ $type ] = $key[ $num - 1 ];
|
671 |
+
break;
|
672 |
+
|
673 |
+
case'kh':
|
674 |
+
$key = array( 'ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش' );
|
675 |
+
$array[ $type ] = $key[ $num ];
|
676 |
+
break;
|
677 |
+
|
678 |
+
default:
|
679 |
+
$array[ $type ] = $num;
|
680 |
+
}
|
681 |
+
}
|
682 |
+
|
683 |
+
return ( $mod == '' ) ? $array : implode( $mod, $array );
|
684 |
+
}
|
685 |
+
|
686 |
+
/** Convertor from and to Gregorian and Jalali (Hijri_Shamsi,Solar) Functions
|
687 |
+
* Copyright(C)2011, Reza Gholampanahi [ http://jdf.scr.ir/jdf ] version 2.50 */
|
688 |
+
|
689 |
+
/* F */
|
690 |
+
function GF_gregorian_to_jalali( $g_y, $g_m, $g_d, $mod = '' ) {
|
691 |
+
$g_y = GF_tr_num( $g_y );
|
692 |
+
$g_m = GF_tr_num( $g_m );
|
693 |
+
$g_d = GF_tr_num( $g_d );/* <= :اين سطر ، جزء تابع اصلي نيست */
|
694 |
+
$d_4 = $g_y % 4;
|
695 |
+
$g_a = array( 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 );
|
696 |
+
$doy_g = $g_a[ (int) $g_m ] + $g_d;
|
697 |
+
if ( $d_4 == 0 and $g_m > 2 ) {
|
698 |
+
$doy_g ++;
|
699 |
+
}
|
700 |
+
$d_33 = (int) ( ( ( $g_y - 16 ) % 132 ) * .0305 );
|
701 |
+
$a = ( $d_33 == 3 or $d_33 < ( $d_4 - 1 ) or $d_4 == 0 ) ? 286 : 287;
|
702 |
+
$b = ( ( $d_33 == 1 or $d_33 == 2 ) and ( $d_33 == $d_4 or $d_4 == 1 ) ) ? 78 : ( ( $d_33 == 3 and $d_4 == 0 ) ? 80 : 79 );
|
703 |
+
if ( (int) ( ( $g_y - 10 ) / 63 ) == 30 ) {
|
704 |
+
$a --;
|
705 |
+
$b ++;
|
706 |
+
}
|
707 |
+
if ( $doy_g > $b ) {
|
708 |
+
$jy = $g_y - 621;
|
709 |
+
$doy_j = $doy_g - $b;
|
710 |
+
} else {
|
711 |
+
$jy = $g_y - 622;
|
712 |
+
$doy_j = $doy_g + $a;
|
713 |
+
}
|
714 |
+
if ( $doy_j < 187 ) {
|
715 |
+
$jm = (int) ( ( $doy_j - 1 ) / 31 );
|
716 |
+
$jd = $doy_j - ( 31 * $jm ++ );
|
717 |
+
} else {
|
718 |
+
$jm = (int) ( ( $doy_j - 187 ) / 30 );
|
719 |
+
$jd = $doy_j - 186 - ( $jm * 30 );
|
720 |
+
$jm += 7;
|
721 |
+
}
|
722 |
+
|
723 |
+
return ( $mod == '' ) ? array( $jy, $jm, $jd ) : $jy . $mod . $jm . $mod . $jd;
|
724 |
+
}
|
725 |
+
|
726 |
+
/* F */
|
727 |
+
function GF_jalali_to_gregorian( $j_y, $j_m, $j_d, $mod = '' ) {
|
728 |
+
$j_y = GF_tr_num( $j_y );
|
729 |
+
$j_m = GF_tr_num( $j_m );
|
730 |
+
$j_d = GF_tr_num( $j_d );/* <= :اين سطر ، جزء تابع اصلي نيست */
|
731 |
+
$d_4 = ( $j_y + 1 ) % 4;
|
732 |
+
$doy_j = ( $j_m < 7 ) ? ( ( $j_m - 1 ) * 31 ) + $j_d : ( ( $j_m - 7 ) * 30 ) + $j_d + 186;
|
733 |
+
$d_33 = (int) ( ( ( $j_y - 55 ) % 132 ) * .0305 );
|
734 |
+
$a = ( $d_33 != 3 and $d_4 <= $d_33 ) ? 287 : 286;
|
735 |
+
$b = ( ( $d_33 == 1 or $d_33 == 2 ) and ( $d_33 == $d_4 or $d_4 == 1 ) ) ? 78 : ( ( $d_33 == 3 and $d_4 == 0 ) ? 80 : 79 );
|
736 |
+
if ( (int) ( ( $j_y - 19 ) / 63 ) == 20 ) {
|
737 |
+
$a --;
|
738 |
+
$b ++;
|
739 |
+
}
|
740 |
+
if ( $doy_j <= $a ) {
|
741 |
+
$gy = $j_y + 621;
|
742 |
+
$gd = $doy_j + $b;
|
743 |
+
} else {
|
744 |
+
$gy = $j_y + 622;
|
745 |
+
$gd = $doy_j - $a;
|
746 |
+
}
|
747 |
+
foreach ( array( 0, 31, ( $gy % 4 == 0 ) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ) as $gm => $v ) {
|
748 |
+
if ( $gd <= $v ) {
|
749 |
+
break;
|
750 |
+
}
|
751 |
+
$gd -= $v;
|
752 |
+
}
|
753 |
+
|
754 |
+
return ( $mod == '' ) ? array( $gy, $gm, $gd ) : $gy . $mod . $gm . $mod . $gd;
|
755 |
+
}
|
includes/lib/nusoap-php5.3.php
ADDED
@@ -0,0 +1,8484 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
$Id: nusoap.php,v 1.123 2010/04/26 20:15:08 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 Help forum on the project home page.
|
27 |
+
|
28 |
+
If you have any questions or comments, please email:
|
29 |
+
|
30 |
+
Dietrich Ayala
|
31 |
+
dietrich@ganx4.com
|
32 |
+
http://dietrich.ganx4.com/nusoap
|
33 |
+
|
34 |
+
NuSphere Corporation
|
35 |
+
http://www.nusphere.com
|
36 |
+
|
37 |
+
*/
|
38 |
+
|
39 |
+
/*
|
40 |
+
* Some of the standards implmented in whole or part by NuSOAP:
|
41 |
+
*
|
42 |
+
* SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
|
43 |
+
* WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
|
44 |
+
* SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
|
45 |
+
* XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
|
46 |
+
* Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
|
47 |
+
* XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
|
48 |
+
* RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
|
49 |
+
* RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
|
50 |
+
* RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
|
51 |
+
*/
|
52 |
+
|
53 |
+
/* load classes
|
54 |
+
|
55 |
+
// necessary classes
|
56 |
+
require_once('class.soapclient.php');
|
57 |
+
require_once('class.soap_val.php');
|
58 |
+
require_once('class.soap_parser.php');
|
59 |
+
require_once('class.soap_fault.php');
|
60 |
+
|
61 |
+
// transport classes
|
62 |
+
require_once('class.soap_transport_http.php');
|
63 |
+
|
64 |
+
// optional add-on classes
|
65 |
+
require_once('class.xmlschema.php');
|
66 |
+
require_once('class.wsdl.php');
|
67 |
+
|
68 |
+
// server class
|
69 |
+
require_once('class.soap_server.php');*/
|
70 |
+
|
71 |
+
// class variable emulation
|
72 |
+
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
|
73 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
|
74 |
+
|
75 |
+
/**
|
76 |
+
*
|
77 |
+
* nusoap_base
|
78 |
+
*
|
79 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
80 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
81 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
82 |
+
* @access public
|
83 |
+
*/
|
84 |
+
//error_reporting( '0' );
|
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.9.5';
|
101 |
+
/**
|
102 |
+
* CVS revision for HTTP headers.
|
103 |
+
*
|
104 |
+
* @var string
|
105 |
+
* @access private
|
106 |
+
*/
|
107 |
+
var $revision = '$Revision: 1.123 $';
|
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',
|
188 |
+
'boolean' => 'boolean',
|
189 |
+
'float' => 'double',
|
190 |
+
'double' => 'double',
|
191 |
+
'decimal' => 'double',
|
192 |
+
'duration' => '',
|
193 |
+
'dateTime' => 'string',
|
194 |
+
'time' => 'string',
|
195 |
+
'date' => 'string',
|
196 |
+
'gYearMonth' => '',
|
197 |
+
'gYear' => '',
|
198 |
+
'gMonthDay' => '',
|
199 |
+
'gDay' => '',
|
200 |
+
'gMonth' => '',
|
201 |
+
'hexBinary' => 'string',
|
202 |
+
'base64Binary' => 'string',
|
203 |
+
// abstract "any" types
|
204 |
+
'anyType' => 'string',
|
205 |
+
'anySimpleType' => 'string',
|
206 |
+
// derived datatypes
|
207 |
+
'normalizedString' => 'string',
|
208 |
+
'token' => 'string',
|
209 |
+
'language' => '',
|
210 |
+
'NMTOKEN' => '',
|
211 |
+
'NMTOKENS' => '',
|
212 |
+
'Name' => '',
|
213 |
+
'NCName' => '',
|
214 |
+
'ID' => '',
|
215 |
+
'IDREF' => '',
|
216 |
+
'IDREFS' => '',
|
217 |
+
'ENTITY' => '',
|
218 |
+
'ENTITIES' => '',
|
219 |
+
'integer' => 'integer',
|
220 |
+
'nonPositiveInteger' => 'integer',
|
221 |
+
'negativeInteger' => 'integer',
|
222 |
+
'long' => 'integer',
|
223 |
+
'int' => 'integer',
|
224 |
+
'short' => 'integer',
|
225 |
+
'byte' => 'integer',
|
226 |
+
'nonNegativeInteger' => 'integer',
|
227 |
+
'unsignedLong' => '',
|
228 |
+
'unsignedInt' => '',
|
229 |
+
'unsignedShort' => '',
|
230 |
+
'unsignedByte' => '',
|
231 |
+
'positiveInteger' => ''
|
232 |
+
),
|
233 |
+
'http://www.w3.org/2000/10/XMLSchema' => array(
|
234 |
+
'i4' => '',
|
235 |
+
'int' => 'integer',
|
236 |
+
'boolean' => 'boolean',
|
237 |
+
'string' => 'string',
|
238 |
+
'double' => 'double',
|
239 |
+
'float' => 'double',
|
240 |
+
'dateTime' => 'string',
|
241 |
+
'timeInstant' => 'string',
|
242 |
+
'base64Binary' => 'string',
|
243 |
+
'base64' => 'string',
|
244 |
+
'ur-type' => 'array'
|
245 |
+
),
|
246 |
+
'http://www.w3.org/1999/XMLSchema' => array(
|
247 |
+
'i4' => '',
|
248 |
+
'int' => 'integer',
|
249 |
+
'boolean' => 'boolean',
|
250 |
+
'string' => 'string',
|
251 |
+
'double' => 'double',
|
252 |
+
'float' => 'double',
|
253 |
+
'dateTime' => 'string',
|
254 |
+
'timeInstant' => 'string',
|
255 |
+
'base64Binary' => 'string',
|
256 |
+
'base64' => 'string',
|
257 |
+
'ur-type' => 'array'
|
258 |
+
),
|
259 |
+
'http://soapinterop.org/xsd' => array( 'SOAPStruct' => 'struct' ),
|
260 |
+
'http://schemas.xmlsoap.org/soap/encoding/' => array(
|
261 |
+
'base64' => 'string',
|
262 |
+
'array' => 'array',
|
263 |
+
'Array' => 'array'
|
264 |
+
),
|
265 |
+
'http://xml.apache.org/xml-soap' => array( 'Map' )
|
266 |
+
);
|
267 |
+
|
268 |
+
/**
|
269 |
+
* XML entities to convert
|
270 |
+
*
|
271 |
+
* @var array
|
272 |
+
* @access public
|
273 |
+
* @deprecated
|
274 |
+
* @see expandEntities
|
275 |
+
*/
|
276 |
+
var $xmlEntities = array(
|
277 |
+
'quot' => '"',
|
278 |
+
'amp' => '&',
|
279 |
+
'lt' => '<',
|
280 |
+
'gt' => '>',
|
281 |
+
'apos' => "'"
|
282 |
+
);
|
283 |
+
|
284 |
+
/**
|
285 |
+
* constructor
|
286 |
+
*
|
287 |
+
* @access public
|
288 |
+
*/
|
289 |
+
function nusoap_base() {
|
290 |
+
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* gets the global debug level, which applies to future instances
|
295 |
+
*
|
296 |
+
* @return integer Debug level 0-9, where 0 turns off
|
297 |
+
* @access public
|
298 |
+
*/
|
299 |
+
function getGlobalDebugLevel() {
|
300 |
+
return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
301 |
+
}
|
302 |
+
|
303 |
+
/**
|
304 |
+
* sets the global debug level, which applies to future instances
|
305 |
+
*
|
306 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
307 |
+
*
|
308 |
+
* @access public
|
309 |
+
*/
|
310 |
+
function setGlobalDebugLevel( $level ) {
|
311 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
|
312 |
+
}
|
313 |
+
|
314 |
+
/**
|
315 |
+
* gets the debug level for this instance
|
316 |
+
*
|
317 |
+
* @return int Debug level 0-9, where 0 turns off
|
318 |
+
* @access public
|
319 |
+
*/
|
320 |
+
function getDebugLevel() {
|
321 |
+
return $this->debugLevel;
|
322 |
+
}
|
323 |
+
|
324 |
+
/**
|
325 |
+
* sets the debug level for this instance
|
326 |
+
*
|
327 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
328 |
+
*
|
329 |
+
* @access public
|
330 |
+
*/
|
331 |
+
function setDebugLevel( $level ) {
|
332 |
+
$this->debugLevel = $level;
|
333 |
+
}
|
334 |
+
|
335 |
+
/**
|
336 |
+
* adds debug data to the instance debug string with formatting
|
337 |
+
*
|
338 |
+
* @param string $string debug data
|
339 |
+
*
|
340 |
+
* @access private
|
341 |
+
*/
|
342 |
+
function debug( $string ) {
|
343 |
+
if ( $this->debugLevel > 0 ) {
|
344 |
+
$this->appendDebug( $this->getmicrotime() . ' ' . get_class( $this ) . ": $string\n" );
|
345 |
+
}
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* adds debug data to the instance debug string without formatting
|
350 |
+
*
|
351 |
+
* @param string $string debug data
|
352 |
+
*
|
353 |
+
* @access public
|
354 |
+
*/
|
355 |
+
function appendDebug( $string ) {
|
356 |
+
if ( $this->debugLevel > 0 ) {
|
357 |
+
// it would be nice to use a memory stream here to use
|
358 |
+
// memory more efficiently
|
359 |
+
$this->debug_str .= $string;
|
360 |
+
}
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* clears the current debug data for this instance
|
365 |
+
*
|
366 |
+
* @access public
|
367 |
+
*/
|
368 |
+
function clearDebug() {
|
369 |
+
// it would be nice to use a memory stream here to use
|
370 |
+
// memory more efficiently
|
371 |
+
$this->debug_str = '';
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* gets the current debug data for this instance
|
376 |
+
*
|
377 |
+
* @return debug data
|
378 |
+
* @access public
|
379 |
+
*/
|
380 |
+
function &getDebug() {
|
381 |
+
// it would be nice to use a memory stream here to use
|
382 |
+
// memory more efficiently
|
383 |
+
return $this->debug_str;
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* gets the current debug data for this instance as an XML comment
|
388 |
+
* this may change the contents of the debug data
|
389 |
+
*
|
390 |
+
* @return debug data as an XML comment
|
391 |
+
* @access public
|
392 |
+
*/
|
393 |
+
function &getDebugAsXMLComment() {
|
394 |
+
// it would be nice to use a memory stream here to use
|
395 |
+
// memory more efficiently
|
396 |
+
while ( strpos( $this->debug_str, '--' ) ) {
|
397 |
+
$this->debug_str = str_replace( '--', '- -', $this->debug_str );
|
398 |
+
}
|
399 |
+
$ret = "<!--\n" . $this->debug_str . "\n-->";
|
400 |
+
|
401 |
+
return $ret;
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* expands entities, e.g. changes '<' to '<'.
|
406 |
+
*
|
407 |
+
* @param string $val The string in which to expand entities.
|
408 |
+
*
|
409 |
+
* @access private
|
410 |
+
*/
|
411 |
+
function expandEntities( $val ) {
|
412 |
+
if ( $this->charencoding ) {
|
413 |
+
$val = str_replace( '&', '&', $val );
|
414 |
+
$val = str_replace( "'", ''', $val );
|
415 |
+
$val = str_replace( '"', '"', $val );
|
416 |
+
$val = str_replace( '<', '<', $val );
|
417 |
+
$val = str_replace( '>', '>', $val );
|
418 |
+
}
|
419 |
+
|
420 |
+
return $val;
|
421 |
+
}
|
422 |
+
|
423 |
+
/**
|
424 |
+
* returns error string if present
|
425 |
+
*
|
426 |
+
* @return mixed error string or false
|
427 |
+
* @access public
|
428 |
+
*/
|
429 |
+
function getError() {
|
430 |
+
if ( $this->error_str != '' ) {
|
431 |
+
return $this->error_str;
|
432 |
+
}
|
433 |
+
|
434 |
+
return false;
|
435 |
+
}
|
436 |
+
|
437 |
+
/**
|
438 |
+
* sets error string
|
439 |
+
*
|
440 |
+
* @return boolean $string error string
|
441 |
+
* @access private
|
442 |
+
*/
|
443 |
+
function setError( $str ) {
|
444 |
+
$this->error_str = $str;
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* detect if array is a simple array or a struct (associative array)
|
449 |
+
*
|
450 |
+
* @param mixed $val The PHP array
|
451 |
+
*
|
452 |
+
* @return string (arraySimple|arrayStruct)
|
453 |
+
* @access private
|
454 |
+
*/
|
455 |
+
function isArraySimpleOrStruct( $val ) {
|
456 |
+
$keyList = array_keys( $val );
|
457 |
+
foreach ( $keyList as $keyListValue ) {
|
458 |
+
if ( ! is_int( $keyListValue ) ) {
|
459 |
+
return 'arrayStruct';
|
460 |
+
}
|
461 |
+
}
|
462 |
+
|
463 |
+
return 'arraySimple';
|
464 |
+
}
|
465 |
+
|
466 |
+
/**
|
467 |
+
* serializes PHP values in accordance w/ section 5. Type information is
|
468 |
+
* not serialized if $use == 'literal'.
|
469 |
+
*
|
470 |
+
* @param mixed $val The value to serialize
|
471 |
+
* @param string $name The name (local part) of the XML element
|
472 |
+
* @param string $type The XML schema type (local part) for the element
|
473 |
+
* @param string $name_ns The namespace for the name of the XML element
|
474 |
+
* @param string $type_ns The namespace for the type of the element
|
475 |
+
* @param array $attributes The attributes to serialize as name=>value pairs
|
476 |
+
* @param string $use The WSDL "use" (encoded|literal)
|
477 |
+
* @param boolean $soapval Whether this is called from soapval.
|
478 |
+
*
|
479 |
+
* @return string The serialized element, possibly with child elements
|
480 |
+
* @access public
|
481 |
+
*/
|
482 |
+
function serialize_val( $val, $name = false, $type = false, $name_ns = false, $type_ns = false, $attributes = false, $use = 'encoded', $soapval = false ) {
|
483 |
+
$this->debug( "in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval" );
|
484 |
+
$this->appendDebug( 'value=' . $this->varDump( $val ) );
|
485 |
+
$this->appendDebug( 'attributes=' . $this->varDump( $attributes ) );
|
486 |
+
|
487 |
+
if ( is_object( $val ) && get_class( $val ) == 'soapval' && ( ! $soapval ) ) {
|
488 |
+
$this->debug( "serialize_val: serialize soapval" );
|
489 |
+
$xml = $val->serialize( $use );
|
490 |
+
$this->appendDebug( $val->getDebug() );
|
491 |
+
$val->clearDebug();
|
492 |
+
$this->debug( "serialize_val of soapval returning $xml" );
|
493 |
+
|
494 |
+
return $xml;
|
495 |
+
}
|
496 |
+
// force valid name if necessary
|
497 |
+
if ( is_numeric( $name ) ) {
|
498 |
+
$name = '__numeric_' . $name;
|
499 |
+
} elseif ( ! $name ) {
|
500 |
+
$name = 'noname';
|
501 |
+
}
|
502 |
+
// if name has ns, add ns prefix to name
|
503 |
+
$xmlns = '';
|
504 |
+
if ( $name_ns ) {
|
505 |
+
$prefix = 'nu' . rand( 1000, 9999 );
|
506 |
+
$name = $prefix . ':' . $name;
|
507 |
+
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
|
508 |
+
}
|
509 |
+
// if type is prefixed, create type prefix
|
510 |
+
if ( $type_ns != '' && $type_ns == $this->namespaces['xsd'] ) {
|
511 |
+
// need to fix this. shouldn't default to xsd if no ns specified
|
512 |
+
// w/o checking against typemap
|
513 |
+
$type_prefix = 'xsd';
|
514 |
+
} elseif ( $type_ns ) {
|
515 |
+
$type_prefix = 'ns' . rand( 1000, 9999 );
|
516 |
+
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
|
517 |
+
}
|
518 |
+
// serialize attributes if present
|
519 |
+
$atts = '';
|
520 |
+
if ( $attributes ) {
|
521 |
+
foreach ( $attributes as $k => $v ) {
|
522 |
+
$atts .= " $k=\"" . $this->expandEntities( $v ) . '"';
|
523 |
+
}
|
524 |
+
}
|
525 |
+
// serialize null value
|
526 |
+
if ( is_null( $val ) ) {
|
527 |
+
$this->debug( "serialize_val: serialize null" );
|
528 |
+
if ( $use == 'literal' ) {
|
529 |
+
// TODO: depends on minOccurs
|
530 |
+
$xml = "<$name$xmlns$atts/>";
|
531 |
+
$this->debug( "serialize_val returning $xml" );
|
532 |
+
|
533 |
+
return $xml;
|
534 |
+
} else {
|
535 |
+
if ( isset( $type ) && isset( $type_prefix ) ) {
|
536 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
537 |
+
} else {
|
538 |
+
$type_str = '';
|
539 |
+
}
|
540 |
+
$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
|
541 |
+
$this->debug( "serialize_val returning $xml" );
|
542 |
+
|
543 |
+
return $xml;
|
544 |
+
}
|
545 |
+
}
|
546 |
+
// serialize if an xsd built-in primitive type
|
547 |
+
if ( $type != '' && isset( $this->typemap[ $this->XMLSchemaVersion ][ $type ] ) ) {
|
548 |
+
$this->debug( "serialize_val: serialize xsd built-in primitive type" );
|
549 |
+
if ( is_bool( $val ) ) {
|
550 |
+
if ( $type == 'boolean' ) {
|
551 |
+
$val = $val ? 'true' : 'false';
|
552 |
+
} elseif ( ! $val ) {
|
553 |
+
$val = 0;
|
554 |
+
}
|
555 |
+
} else if ( is_string( $val ) ) {
|
556 |
+
$val = $this->expandEntities( $val );
|
557 |
+
}
|
558 |
+
if ( $use == 'literal' ) {
|
559 |
+
$xml = "<$name$xmlns$atts>$val</$name>";
|
560 |
+
$this->debug( "serialize_val returning $xml" );
|
561 |
+
|
562 |
+
return $xml;
|
563 |
+
} else {
|
564 |
+
$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
|
565 |
+
$this->debug( "serialize_val returning $xml" );
|
566 |
+
|
567 |
+
return $xml;
|
568 |
+
}
|
569 |
+
}
|
570 |
+
// detect type and serialize
|
571 |
+
$xml = '';
|
572 |
+
switch ( true ) {
|
573 |
+
case ( is_bool( $val ) || $type == 'boolean' ):
|
574 |
+
$this->debug( "serialize_val: serialize boolean" );
|
575 |
+
if ( $type == 'boolean' ) {
|
576 |
+
$val = $val ? 'true' : 'false';
|
577 |
+
} elseif ( ! $val ) {
|
578 |
+
$val = 0;
|
579 |
+
}
|
580 |
+
if ( $use == 'literal' ) {
|
581 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
582 |
+
} else {
|
583 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
|
584 |
+
}
|
585 |
+
break;
|
586 |
+
case ( is_int( $val ) || is_long( $val ) || $type == 'int' ):
|
587 |
+
$this->debug( "serialize_val: serialize int" );
|
588 |
+
if ( $use == 'literal' ) {
|
589 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
590 |
+
} else {
|
591 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
|
592 |
+
}
|
593 |
+
break;
|
594 |
+
case ( is_float( $val ) || is_double( $val ) || $type == 'float' ):
|
595 |
+
$this->debug( "serialize_val: serialize float" );
|
596 |
+
if ( $use == 'literal' ) {
|
597 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
598 |
+
} else {
|
599 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
|
600 |
+
}
|
601 |
+
break;
|
602 |
+
case ( is_string( $val ) || $type == 'string' ):
|
603 |
+
$this->debug( "serialize_val: serialize string" );
|
604 |
+
$val = $this->expandEntities( $val );
|
605 |
+
if ( $use == 'literal' ) {
|
606 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
607 |
+
} else {
|
608 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
|
609 |
+
}
|
610 |
+
break;
|
611 |
+
case is_object( $val ):
|
612 |
+
$this->debug( "serialize_val: serialize object" );
|
613 |
+
if ( get_class( $val ) == 'soapval' ) {
|
614 |
+
$this->debug( "serialize_val: serialize soapval object" );
|
615 |
+
$pXml = $val->serialize( $use );
|
616 |
+
$this->appendDebug( $val->getDebug() );
|
617 |
+
$val->clearDebug();
|
618 |
+
} else {
|
619 |
+
if ( ! $name ) {
|
620 |
+
$name = get_class( $val );
|
621 |
+
$this->debug( "In serialize_val, used class name $name as element name" );
|
622 |
+
} else {
|
623 |
+
$this->debug( "In serialize_val, do not override name $name for element name for class " . get_class( $val ) );
|
624 |
+
}
|
625 |
+
foreach ( get_object_vars( $val ) as $k => $v ) {
|
626 |
+
$pXml = isset( $pXml ) ? $pXml . $this->serialize_val( $v, $k, false, false, false, false, $use ) : $this->serialize_val( $v, $k, false, false, false, false, $use );
|
627 |
+
}
|
628 |
+
}
|
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>$pXml</$name>";
|
636 |
+
} else {
|
637 |
+
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
|
638 |
+
}
|
639 |
+
break;
|
640 |
+
break;
|
641 |
+
case ( is_array( $val ) || $type ):
|
642 |
+
// detect if struct or array
|
643 |
+
$valueType = $this->isArraySimpleOrStruct( $val );
|
644 |
+
if ( $valueType == 'arraySimple' || preg_match( '/^ArrayOf/', $type ) ) {
|
645 |
+
$this->debug( "serialize_val: serialize array" );
|
646 |
+
$i = 0;
|
647 |
+
if ( is_array( $val ) && count( $val ) > 0 ) {
|
648 |
+
foreach ( $val as $v ) {
|
649 |
+
if ( is_object( $v ) && get_class( $v ) == 'soapval' ) {
|
650 |
+
$tt_ns = $v->type_ns;
|
651 |
+
$tt = $v->type;
|
652 |
+
} elseif ( is_array( $v ) ) {
|
653 |
+
$tt = $this->isArraySimpleOrStruct( $v );
|
654 |
+
} else {
|
655 |
+
$tt = gettype( $v );
|
656 |
+
}
|
657 |
+
$array_types[ $tt ] = 1;
|
658 |
+
// TODO: for literal, the name should be $name
|
659 |
+
$xml .= $this->serialize_val( $v, 'item', false, false, false, false, $use );
|
660 |
+
++ $i;
|
661 |
+
}
|
662 |
+
if ( count( $array_types ) > 1 ) {
|
663 |
+
$array_typename = 'xsd:anyType';
|
664 |
+
} elseif ( isset( $tt ) && isset( $this->typemap[ $this->XMLSchemaVersion ][ $tt ] ) ) {
|
665 |
+
if ( $tt == 'integer' ) {
|
666 |
+
$tt = 'int';
|
667 |
+
}
|
668 |
+
$array_typename = 'xsd:' . $tt;
|
669 |
+
} elseif ( isset( $tt ) && $tt == 'arraySimple' ) {
|
670 |
+
$array_typename = 'SOAP-ENC:Array';
|
671 |
+
} elseif ( isset( $tt ) && $tt == 'arrayStruct' ) {
|
672 |
+
$array_typename = 'unnamed_struct_use_soapval';
|
673 |
+
} else {
|
674 |
+
// if type is prefixed, create type prefix
|
675 |
+
if ( $tt_ns != '' && $tt_ns == $this->namespaces['xsd'] ) {
|
676 |
+
$array_typename = 'xsd:' . $tt;
|
677 |
+
} elseif ( $tt_ns ) {
|
678 |
+
$tt_prefix = 'ns' . rand( 1000, 9999 );
|
679 |
+
$array_typename = "$tt_prefix:$tt";
|
680 |
+
$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
|
681 |
+
} else {
|
682 |
+
$array_typename = $tt;
|
683 |
+
}
|
684 |
+
}
|
685 |
+
$array_type = $i;
|
686 |
+
if ( $use == 'literal' ) {
|
687 |
+
$type_str = '';
|
688 |
+
} else if ( isset( $type ) && isset( $type_prefix ) ) {
|
689 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
690 |
+
} else {
|
691 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
|
692 |
+
}
|
693 |
+
// empty array
|
694 |
+
} else {
|
695 |
+
if ( $use == 'literal' ) {
|
696 |
+
$type_str = '';
|
697 |
+
} else if ( isset( $type ) && isset( $type_prefix ) ) {
|
698 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
699 |
+
} else {
|
700 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
|
701 |
+
}
|
702 |
+
}
|
703 |
+
// TODO: for array in literal, there is no wrapper here
|
704 |
+
$xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
|
705 |
+
} else {
|
706 |
+
// got a struct
|
707 |
+
$this->debug( "serialize_val: serialize struct" );
|
708 |
+
if ( isset( $type ) && isset( $type_prefix ) ) {
|
709 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
710 |
+
} else {
|
711 |
+
$type_str = '';
|
712 |
+
}
|
713 |
+
if ( $use == 'literal' ) {
|
714 |
+
$xml .= "<$name$xmlns$atts>";
|
715 |
+
} else {
|
716 |
+
$xml .= "<$name$xmlns$type_str$atts>";
|
717 |
+
}
|
718 |
+
foreach ( $val as $k => $v ) {
|
719 |
+
// Apache Map
|
720 |
+
if ( $type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap' ) {
|
721 |
+
$xml .= '<item>';
|
722 |
+
$xml .= $this->serialize_val( $k, 'key', false, false, false, false, $use );
|
723 |
+
$xml .= $this->serialize_val( $v, 'value', false, false, false, false, $use );
|
724 |
+
$xml .= '</item>';
|
725 |
+
} else {
|
726 |
+
$xml .= $this->serialize_val( $v, $k, false, false, false, false, $use );
|
727 |
+
}
|
728 |
+
}
|
729 |
+
$xml .= "</$name>";
|
730 |
+
}
|
731 |
+
break;
|
732 |
+
default:
|
733 |
+
$this->debug( "serialize_val: serialize unknown" );
|
734 |
+
$xml .= 'not detected, got ' . gettype( $val ) . ' for ' . $val;
|
735 |
+
break;
|
736 |
+
}
|
737 |
+
$this->debug( "serialize_val returning $xml" );
|
738 |
+
|
739 |
+
return $xml;
|
740 |
+
}
|
741 |
+
|
742 |
+
/**
|
743 |
+
* serializes a message
|
744 |
+
*
|
745 |
+
* @param string $body the XML of the SOAP body
|
746 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
747 |
+
* @param array $namespaces optional the namespaces used in generating the body and headers
|
748 |
+
* @param string $style optional (rpc|document)
|
749 |
+
* @param string $use optional (encoded|literal)
|
750 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
751 |
+
*
|
752 |
+
* @return string the message
|
753 |
+
* @access public
|
754 |
+
*/
|
755 |
+
function serializeEnvelope( $body, $headers = false, $namespaces = array(), $style = 'rpc', $use = 'encoded', $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/' ) {
|
756 |
+
// TODO: add an option to automatically run utf8_encode on $body and $headers
|
757 |
+
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
|
758 |
+
// one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
|
759 |
+
|
760 |
+
$this->debug( "In serializeEnvelope length=" . strlen( $body ) . " body (max 1000 characters)=" . substr( $body, 0, 1000 ) . " style=$style use=$use encodingStyle=$encodingStyle" );
|
761 |
+
$this->debug( "headers:" );
|
762 |
+
$this->appendDebug( $this->varDump( $headers ) );
|
763 |
+
$this->debug( "namespaces:" );
|
764 |
+
$this->appendDebug( $this->varDump( $namespaces ) );
|
765 |
+
|
766 |
+
// serialize namespaces
|
767 |
+
$ns_string = '';
|
768 |
+
foreach ( array_merge( $this->namespaces, $namespaces ) as $k => $v ) {
|
769 |
+
$ns_string .= " xmlns:$k=\"$v\"";
|
770 |
+
}
|
771 |
+
if ( $encodingStyle ) {
|
772 |
+
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
|
773 |
+
}
|
774 |
+
|
775 |
+
// serialize headers
|
776 |
+
if ( $headers ) {
|
777 |
+
if ( is_array( $headers ) ) {
|
778 |
+
$xml = '';
|
779 |
+
foreach ( $headers as $k => $v ) {
|
780 |
+
if ( is_object( $v ) && get_class( $v ) == 'soapval' ) {
|
781 |
+
$xml .= $this->serialize_val( $v, false, false, false, false, false, $use );
|
782 |
+
} else {
|
783 |
+
$xml .= $this->serialize_val( $v, $k, false, false, false, false, $use );
|
784 |
+
}
|
785 |
+
}
|
786 |
+
$headers = $xml;
|
787 |
+
$this->debug( "In serializeEnvelope, serialized array of headers to $headers" );
|
788 |
+
}
|
789 |
+
$headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
|
790 |
+
}
|
791 |
+
|
792 |
+
// serialize envelope
|
793 |
+
return
|
794 |
+
'<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
|
795 |
+
'<SOAP-ENV:Envelope' . $ns_string . ">" .
|
796 |
+
$headers .
|
797 |
+
"<SOAP-ENV:Body>" .
|
798 |
+
$body .
|
799 |
+
"</SOAP-ENV:Body>" .
|
800 |
+
"</SOAP-ENV:Envelope>";
|
801 |
+
}
|
802 |
+
|
803 |
+
/**
|
804 |
+
* formats a string to be inserted into an HTML stream
|
805 |
+
*
|
806 |
+
* @param string $str The string to format
|
807 |
+
*
|
808 |
+
* @return string The formatted string
|
809 |
+
* @access public
|
810 |
+
* @deprecated
|
811 |
+
*/
|
812 |
+
function formatDump( $str ) {
|
813 |
+
$str = htmlspecialchars( $str );
|
814 |
+
|
815 |
+
return nl2br( $str );
|
816 |
+
}
|
817 |
+
|
818 |
+
/**
|
819 |
+
* contracts (changes namespace to prefix) a qualified name
|
820 |
+
*
|
821 |
+
* @param string $qname qname
|
822 |
+
*
|
823 |
+
* @return string contracted qname
|
824 |
+
* @access private
|
825 |
+
*/
|
826 |
+
function contractQname( $qname ) {
|
827 |
+
// get element namespace
|
828 |
+
//$this->xdebug("Contract $qname");
|
829 |
+
if ( strrpos( $qname, ':' ) ) {
|
830 |
+
// get unqualified name
|
831 |
+
$name = substr( $qname, strrpos( $qname, ':' ) + 1 );
|
832 |
+
// get ns
|
833 |
+
$ns = substr( $qname, 0, strrpos( $qname, ':' ) );
|
834 |
+
$p = $this->getPrefixFromNamespace( $ns );
|
835 |
+
if ( $p ) {
|
836 |
+
return $p . ':' . $name;
|
837 |
+
}
|
838 |
+
|
839 |
+
return $qname;
|
840 |
+
} else {
|
841 |
+
return $qname;
|
842 |
+
}
|
843 |
+
}
|
844 |
+
|
845 |
+
/**
|
846 |
+
* expands (changes prefix to namespace) a qualified name
|
847 |
+
*
|
848 |
+
* @param string $qname qname
|
849 |
+
*
|
850 |
+
* @return string expanded qname
|
851 |
+
* @access private
|
852 |
+
*/
|
853 |
+
function expandQname( $qname ) {
|
854 |
+
// get element prefix
|
855 |
+
if ( strpos( $qname, ':' ) && ! preg_match( '/^http:\/\//', $qname ) ) {
|
856 |
+
// get unqualified name
|
857 |
+
$name = substr( strstr( $qname, ':' ), 1 );
|
858 |
+
// get ns prefix
|
859 |
+
$prefix = substr( $qname, 0, strpos( $qname, ':' ) );
|
860 |
+
if ( isset( $this->namespaces[ $prefix ] ) ) {
|
861 |
+
return $this->namespaces[ $prefix ] . ':' . $name;
|
862 |
+
} else {
|
863 |
+
return $qname;
|
864 |
+
}
|
865 |
+
} else {
|
866 |
+
return $qname;
|
867 |
+
}
|
868 |
+
}
|
869 |
+
|
870 |
+
/**
|
871 |
+
* returns the local part of a prefixed string
|
872 |
+
* returns the original string, if not prefixed
|
873 |
+
*
|
874 |
+
* @param string $str The prefixed string
|
875 |
+
*
|
876 |
+
* @return string The local part
|
877 |
+
* @access public
|
878 |
+
*/
|
879 |
+
function getLocalPart( $str ) {
|
880 |
+
if ( $sstr = strrchr( $str, ':' ) ) {
|
881 |
+
// get unqualified name
|
882 |
+
return substr( $sstr, 1 );
|
883 |
+
} else {
|
884 |
+
return $str;
|
885 |
+
}
|
886 |
+
}
|
887 |
+
|
888 |
+
/**
|
889 |
+
* returns the prefix part of a prefixed string
|
890 |
+
* returns false, if not prefixed
|
891 |
+
*
|
892 |
+
* @param string $str The prefixed string
|
893 |
+
*
|
894 |
+
* @return mixed The prefix or false if there is no prefix
|
895 |
+
* @access public
|
896 |
+
*/
|
897 |
+
function getPrefix( $str ) {
|
898 |
+
if ( $pos = strrpos( $str, ':' ) ) {
|
899 |
+
// get prefix
|
900 |
+
return substr( $str, 0, $pos );
|
901 |
+
}
|
902 |
+
|
903 |
+
return false;
|
904 |
+
}
|
905 |
+
|
906 |
+
/**
|
907 |
+
* pass it a prefix, it returns a namespace
|
908 |
+
*
|
909 |
+
* @param string $prefix The prefix
|
910 |
+
*
|
911 |
+
* @return mixed The namespace, false if no namespace has the specified prefix
|
912 |
+
* @access public
|
913 |
+
*/
|
914 |
+
function getNamespaceFromPrefix( $prefix ) {
|
915 |
+
if ( isset( $this->namespaces[ $prefix ] ) ) {
|
916 |
+
return $this->namespaces[ $prefix ];
|
917 |
+
}
|
918 |
+
|
919 |
+
//$this->setError("No namespace registered for prefix '$prefix'");
|
920 |
+
return false;
|
921 |
+
}
|
922 |
+
|
923 |
+
/**
|
924 |
+
* returns the prefix for a given namespace (or prefix)
|
925 |
+
* or false if no prefixes registered for the given namespace
|
926 |
+
*
|
927 |
+
* @param string $ns The namespace
|
928 |
+
*
|
929 |
+
* @return mixed The prefix, false if the namespace has no prefixes
|
930 |
+
* @access public
|
931 |
+
*/
|
932 |
+
function getPrefixFromNamespace( $ns ) {
|
933 |
+
foreach ( $this->namespaces as $p => $n ) {
|
934 |
+
if ( $ns == $n || $ns == $p ) {
|
935 |
+
$this->usedNamespaces[ $p ] = $n;
|
936 |
+
|
937 |
+
return $p;
|
938 |
+
}
|
939 |
+
}
|
940 |
+
|
941 |
+
return false;
|
942 |
+
}
|
943 |
+
|
944 |
+
/**
|
945 |
+
* returns the time in ODBC canonical form with microseconds
|
946 |
+
*
|
947 |
+
* @return string The time in ODBC canonical form with microseconds
|
948 |
+
* @access public
|
949 |
+
*/
|
950 |
+
function getmicrotime() {
|
951 |
+
if ( function_exists( 'gettimeofday' ) ) {
|
952 |
+
$tod = gettimeofday();
|
953 |
+
$sec = $tod['sec'];
|
954 |
+
$usec = $tod['usec'];
|
955 |
+
} else {
|
956 |
+
$sec = time();
|
957 |
+
$usec = 0;
|
958 |
+
}
|
959 |
+
|
960 |
+
return strftime( '%Y-%m-%d %H:%M:%S', $sec ) . '.' . sprintf( '%06d', $usec );
|
961 |
+
}
|
962 |
+
|
963 |
+
/**
|
964 |
+
* Returns a string with the output of var_dump
|
965 |
+
*
|
966 |
+
* @param mixed $data The variable to var_dump
|
967 |
+
*
|
968 |
+
* @return string The output of var_dump
|
969 |
+
* @access public
|
970 |
+
*/
|
971 |
+
function varDump( $data ) {
|
972 |
+
ob_start();
|
973 |
+
var_dump( $data );
|
974 |
+
$ret_val = ob_get_contents();
|
975 |
+
ob_end_clean();
|
976 |
+
|
977 |
+
return $ret_val;
|
978 |
+
}
|
979 |
+
|
980 |
+
/**
|
981 |
+
* represents the object as a string
|
982 |
+
*
|
983 |
+
* @return string
|
984 |
+
* @access public
|
985 |
+
*/
|
986 |
+
function __toString() {
|
987 |
+
return $this->varDump( $this );
|
988 |
+
}
|
989 |
+
}
|
990 |
+
|
991 |
+
// XML Schema Datatype Helper Functions
|
992 |
+
|
993 |
+
//xsd:dateTime helpers
|
994 |
+
|
995 |
+
/**
|
996 |
+
* convert unix timestamp to ISO 8601 compliant date string
|
997 |
+
*
|
998 |
+
* @param int $timestamp Unix time stamp
|
999 |
+
* @param boolean $utc Whether the time stamp is UTC or local
|
1000 |
+
*
|
1001 |
+
* @return mixed ISO 8601 date string or false
|
1002 |
+
* @access public
|
1003 |
+
*/
|
1004 |
+
function timestamp_to_iso8601( $timestamp, $utc = true ) {
|
1005 |
+
$datestr = date( 'Y-m-d\TH:i:sO', $timestamp );
|
1006 |
+
$pos = strrpos( $datestr, "+" );
|
1007 |
+
if ( $pos === false ) {
|
1008 |
+
$pos = strrpos( $datestr, "-" );
|
1009 |
+
}
|
1010 |
+
if ( $pos !== false ) {
|
1011 |
+
if ( strlen( $datestr ) == $pos + 5 ) {
|
1012 |
+
$datestr = substr( $datestr, 0, $pos + 3 ) . ':' . substr( $datestr, - 2 );
|
1013 |
+
}
|
1014 |
+
}
|
1015 |
+
if ( $utc ) {
|
1016 |
+
$pattern = '/' .
|
1017 |
+
'([0-9]{4})-' . // centuries & years CCYY-
|
1018 |
+
'([0-9]{2})-' . // months MM-
|
1019 |
+
'([0-9]{2})' . // days DD
|
1020 |
+
'T' . // separator T
|
1021 |
+
'([0-9]{2}):' . // hours hh:
|
1022 |
+
'([0-9]{2}):' . // minutes mm:
|
1023 |
+
'([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
|
1024 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
1025 |
+
'/';
|
1026 |
+
|
1027 |
+
if ( preg_match( $pattern, $datestr, $regs ) ) {
|
1028 |
+
return sprintf( '%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6] );
|
1029 |
+
}
|
1030 |
+
|
1031 |
+
return false;
|
1032 |
+
} else {
|
1033 |
+
return $datestr;
|
1034 |
+
}
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
/**
|
1038 |
+
* convert ISO 8601 compliant date string to unix timestamp
|
1039 |
+
*
|
1040 |
+
* @param string $datestr ISO 8601 compliant date string
|
1041 |
+
*
|
1042 |
+
* @return mixed Unix timestamp (int) or false
|
1043 |
+
* @access public
|
1044 |
+
*/
|
1045 |
+
function iso8601_to_timestamp( $datestr ) {
|
1046 |
+
$pattern = '/' .
|
1047 |
+
'([0-9]{4})-' . // centuries & years CCYY-
|
1048 |
+
'([0-9]{2})-' . // months MM-
|
1049 |
+
'([0-9]{2})' . // days DD
|
1050 |
+
'T' . // separator T
|
1051 |
+
'([0-9]{2}):' . // hours hh:
|
1052 |
+
'([0-9]{2}):' . // minutes mm:
|
1053 |
+
'([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
|
1054 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
1055 |
+
'/';
|
1056 |
+
if ( preg_match( $pattern, $datestr, $regs ) ) {
|
1057 |
+
// not utc
|
1058 |
+
if ( $regs[8] != 'Z' ) {
|
1059 |
+
$op = substr( $regs[8], 0, 1 );
|
1060 |
+
$h = substr( $regs[8], 1, 2 );
|
1061 |
+
$m = substr( $regs[8], strlen( $regs[8] ) - 2, 2 );
|
1062 |
+
if ( $op == '-' ) {
|
1063 |
+
$regs[4] = $regs[4] + $h;
|
1064 |
+
$regs[5] = $regs[5] + $m;
|
1065 |
+
} elseif ( $op == '+' ) {
|
1066 |
+
$regs[4] = $regs[4] - $h;
|
1067 |
+
$regs[5] = $regs[5] - $m;
|
1068 |
+
}
|
1069 |
+
}
|
1070 |
+
|
1071 |
+
return gmmktime( $regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1] );
|
1072 |
+
// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
|
1073 |
+
} else {
|
1074 |
+
return false;
|
1075 |
+
}
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
/**
|
1079 |
+
* sleeps some number of microseconds
|
1080 |
+
*
|
1081 |
+
* @param string $usec the number of microseconds to sleep
|
1082 |
+
*
|
1083 |
+
* @access public
|
1084 |
+
* @deprecated
|
1085 |
+
*/
|
1086 |
+
function usleepWindows( $usec ) {
|
1087 |
+
$start = gettimeofday();
|
1088 |
+
|
1089 |
+
do {
|
1090 |
+
$stop = gettimeofday();
|
1091 |
+
$timePassed = 1000000 * ( $stop['sec'] - $start['sec'] )
|
1092 |
+
+ $stop['usec'] - $start['usec'];
|
1093 |
+
} while ( $timePassed < $usec );
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
?><?php
|
1097 |
+
|
1098 |
+
|
1099 |
+
/**
|
1100 |
+
* Contains information for a SOAP fault.
|
1101 |
+
* Mainly used for returning faults from deployed functions
|
1102 |
+
* in a server instance.
|
1103 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1104 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1105 |
+
* @access public
|
1106 |
+
*/
|
1107 |
+
class nusoap_fault extends nusoap_base {
|
1108 |
+
/**
|
1109 |
+
* The fault code (client|server)
|
1110 |
+
* @var string
|
1111 |
+
* @access private
|
1112 |
+
*/
|
1113 |
+
var $faultcode;
|
1114 |
+
/**
|
1115 |
+
* The fault actor
|
1116 |
+
* @var string
|
1117 |
+
* @access private
|
1118 |
+
*/
|
1119 |
+
var $faultactor;
|
1120 |
+
/**
|
1121 |
+
* The fault string, a description of the fault
|
1122 |
+
* @var string
|
1123 |
+
* @access private
|
1124 |
+
*/
|
1125 |
+
var $faultstring;
|
1126 |
+
/**
|
1127 |
+
* The fault detail, typically a string or array of string
|
1128 |
+
* @var mixed
|
1129 |
+
* @access private
|
1130 |
+
*/
|
1131 |
+
var $faultdetail;
|
1132 |
+
|
1133 |
+
/**
|
1134 |
+
* constructor
|
1135 |
+
*
|
1136 |
+
* @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
|
1137 |
+
* @param string $faultactor only used when msg routed between multiple actors
|
1138 |
+
* @param string $faultstring human readable error message
|
1139 |
+
* @param mixed $faultdetail detail, typically a string or array of string
|
1140 |
+
*/
|
1141 |
+
function nusoap_fault( $faultcode, $faultactor = '', $faultstring = '', $faultdetail = '' ) {
|
1142 |
+
parent::nusoap_base();
|
1143 |
+
$this->faultcode = $faultcode;
|
1144 |
+
$this->faultactor = $faultactor;
|
1145 |
+
$this->faultstring = $faultstring;
|
1146 |
+
$this->faultdetail = $faultdetail;
|
1147 |
+
}
|
1148 |
+
|
1149 |
+
/**
|
1150 |
+
* serialize a fault
|
1151 |
+
*
|
1152 |
+
* @return string The serialization of the fault instance.
|
1153 |
+
* @access public
|
1154 |
+
*/
|
1155 |
+
function serialize() {
|
1156 |
+
$ns_string = '';
|
1157 |
+
foreach ( $this->namespaces as $k => $v ) {
|
1158 |
+
$ns_string .= "\n xmlns:$k=\"$v\"";
|
1159 |
+
}
|
1160 |
+
$return_msg =
|
1161 |
+
'<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
|
1162 |
+
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
|
1163 |
+
'<SOAP-ENV:Body>' .
|
1164 |
+
'<SOAP-ENV:Fault>' .
|
1165 |
+
$this->serialize_val( $this->faultcode, 'faultcode' ) .
|
1166 |
+
$this->serialize_val( $this->faultactor, 'faultactor' ) .
|
1167 |
+
$this->serialize_val( $this->faultstring, 'faultstring' ) .
|
1168 |
+
$this->serialize_val( $this->faultdetail, 'detail' ) .
|
1169 |
+
'</SOAP-ENV:Fault>' .
|
1170 |
+
'</SOAP-ENV:Body>' .
|
1171 |
+
'</SOAP-ENV:Envelope>';
|
1172 |
+
|
1173 |
+
return $return_msg;
|
1174 |
+
}
|
1175 |
+
}
|
1176 |
+
|
1177 |
+
/**
|
1178 |
+
* Backward compatibility
|
1179 |
+
*/
|
1180 |
+
class soap_fault extends nusoap_fault {
|
1181 |
+
}
|
1182 |
+
|
1183 |
+
?><?php
|
1184 |
+
|
1185 |
+
|
1186 |
+
/**
|
1187 |
+
* parses an XML Schema, allows access to it's data, other utility methods.
|
1188 |
+
* imperfect, no validation... yet, but quite functional.
|
1189 |
+
*
|
1190 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1191 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
1192 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1193 |
+
* @access public
|
1194 |
+
*/
|
1195 |
+
class nusoap_xmlschema extends nusoap_base {
|
1196 |
+
|
1197 |
+
// files
|
1198 |
+
var $schema = '';
|
1199 |
+
var $xml = '';
|
1200 |
+
// namespaces
|
1201 |
+
var $enclosingNamespaces;
|
1202 |
+
// schema info
|
1203 |
+
var $schemaInfo = array();
|
1204 |
+
var $schemaTargetNamespace = '';
|
1205 |
+
// types, elements, attributes defined by the schema
|
1206 |
+
var $attributes = array();
|
1207 |
+
var $complexTypes = array();
|
1208 |
+
var $complexTypeStack = array();
|
1209 |
+
var $currentComplexType = null;
|
1210 |
+
var $elements = array();
|
1211 |
+
var $elementStack = array();
|
1212 |
+
var $currentElement = null;
|
1213 |
+
var $simpleTypes = array();
|
1214 |
+
var $simpleTypeStack = array();
|
1215 |
+
var $currentSimpleType = null;
|
1216 |
+
// imports
|
1217 |
+
var $imports = array();
|
1218 |
+
// parser vars
|
1219 |
+
var $parser;
|
1220 |
+
var $position = 0;
|
1221 |
+
var $depth = 0;
|
1222 |
+
var $depth_array = array();
|
1223 |
+
var $message = array();
|
1224 |
+
var $defaultNamespace = array();
|
1225 |
+
|
1226 |
+
/**
|
1227 |
+
* constructor
|
1228 |
+
*
|
1229 |
+
* @param string $schema schema document URI
|
1230 |
+
* @param string $xml xml document URI
|
1231 |
+
* @param string $namespaces namespaces defined in enclosing XML
|
1232 |
+
*
|
1233 |
+
* @access public
|
1234 |
+
*/
|
1235 |
+
function nusoap_xmlschema( $schema = '', $xml = '', $namespaces = array() ) {
|
1236 |
+
parent::nusoap_base();
|
1237 |
+
$this->debug( 'nusoap_xmlschema class instantiated, inside constructor' );
|
1238 |
+
// files
|
1239 |
+
$this->schema = $schema;
|
1240 |
+
$this->xml = $xml;
|
1241 |
+
|
1242 |
+
// namespaces
|
1243 |
+
$this->enclosingNamespaces = $namespaces;
|
1244 |
+
$this->namespaces = array_merge( $this->namespaces, $namespaces );
|
1245 |
+
|
1246 |
+
// parse schema file
|
1247 |
+
if ( $schema != '' ) {
|
1248 |
+
$this->debug( 'initial schema file: ' . $schema );
|
1249 |
+
$this->parseFile( $schema, 'schema' );
|
1250 |
+
}
|
1251 |
+
|
1252 |
+
// parse xml file
|
1253 |
+
if ( $xml != '' ) {
|
1254 |
+
$this->debug( 'initial xml file: ' . $xml );
|
1255 |
+
$this->parseFile( $xml, 'xml' );
|
1256 |
+
}
|
1257 |
+
|
1258 |
+
}
|
1259 |
+
|
1260 |
+
/**
|
1261 |
+
* parse an XML file
|
1262 |
+
*
|
1263 |
+
* @param string $xml path/URL to XML file
|
1264 |
+
* @param string $type (schema | xml)
|
1265 |
+
*
|
1266 |
+
* @return boolean
|
1267 |
+
* @access public
|
1268 |
+
*/
|
1269 |
+
function parseFile( $xml, $type ) {
|
1270 |
+
// parse xml file
|
1271 |
+
if ( $xml != "" ) {
|
1272 |
+
$xmlStr = @join( "", @file( $xml ) );
|
1273 |
+
if ( $xmlStr == "" ) {
|
1274 |
+
$msg = 'Error reading XML from ' . $xml;
|
1275 |
+
$this->setError( $msg );
|
1276 |
+
$this->debug( $msg );
|
1277 |
+
|
1278 |
+
return false;
|
1279 |
+
} else {
|
1280 |
+
$this->debug( "parsing $xml" );
|
1281 |
+
$this->parseString( $xmlStr, $type );
|
1282 |
+
$this->debug( "done parsing $xml" );
|
1283 |
+
|
1284 |
+
return true;
|
1285 |
+
}
|
1286 |
+
}
|
1287 |
+
|
1288 |
+
return false;
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
/**
|
1292 |
+
* parse an XML string
|
1293 |
+
*
|
1294 |
+
* @param string $xml path or URL
|
1295 |
+
* @param string $type (schema|xml)
|
1296 |
+
*
|
1297 |
+
* @access private
|
1298 |
+
*/
|
1299 |
+
function parseString( $xml, $type ) {
|
1300 |
+
// parse xml string
|
1301 |
+
if ( $xml != "" ) {
|
1302 |
+
|
1303 |
+
// Create an XML parser.
|
1304 |
+
$this->parser = xml_parser_create();
|
1305 |
+
// Set the options for parsing the XML data.
|
1306 |
+
xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, 0 );
|
1307 |
+
|
1308 |
+
// Set the object for the parser.
|
1309 |
+
xml_set_object( $this->parser, $this );
|
1310 |
+
|
1311 |
+
// Set the element handlers for the parser.
|
1312 |
+
if ( $type == "schema" ) {
|
1313 |
+
xml_set_element_handler( $this->parser, 'schemaStartElement', 'schemaEndElement' );
|
1314 |
+
xml_set_character_data_handler( $this->parser, 'schemaCharacterData' );
|
1315 |
+
} elseif ( $type == "xml" ) {
|
1316 |
+
xml_set_element_handler( $this->parser, 'xmlStartElement', 'xmlEndElement' );
|
1317 |
+
xml_set_character_data_handler( $this->parser, 'xmlCharacterData' );
|
1318 |
+
}
|
1319 |
+
|
1320 |
+
// Parse the XML file.
|
1321 |
+
if ( ! xml_parse( $this->parser, $xml, true ) ) {
|
1322 |
+
// Display an error message.
|
1323 |
+
$errstr = sprintf( 'XML error parsing XML schema on line %d: %s',
|
1324 |
+
xml_get_current_line_number( $this->parser ),
|
1325 |
+
xml_error_string( xml_get_error_code( $this->parser ) )
|
1326 |
+
);
|
1327 |
+
$this->debug( $errstr );
|
1328 |
+
$this->debug( "XML payload:\n" . $xml );
|
1329 |
+
$this->setError( $errstr );
|
1330 |
+
}
|
1331 |
+
|
1332 |
+
xml_parser_free( $this->parser );
|
1333 |
+
} else {
|
1334 |
+
$this->debug( 'no xml passed to parseString()!!' );
|
1335 |
+
$this->setError( 'no xml passed to parseString()!!' );
|
1336 |
+
}
|
1337 |
+
}
|
1338 |
+
|
1339 |
+
/**
|
1340 |
+
* gets a type name for an unnamed type
|
1341 |
+
*
|
1342 |
+
* @param string Element name
|
1343 |
+
*
|
1344 |
+
* @return string A type name for an unnamed type
|
1345 |
+
* @access private
|
1346 |
+
*/
|
1347 |
+
function CreateTypeName( $ename ) {
|
1348 |
+
$scope = '';
|
1349 |
+
for ( $i = 0; $i < count( $this->complexTypeStack ); $i ++ ) {
|
1350 |
+
$scope .= $this->complexTypeStack[ $i ] . '_';
|
1351 |
+
}
|
1352 |
+
|
1353 |
+
return $scope . $ename . '_ContainedType';
|
1354 |
+
}
|
1355 |
+
|
1356 |
+
/**
|
1357 |
+
* start-element handler
|
1358 |
+
*
|
1359 |
+
* @param string $parser XML parser object
|
1360 |
+
* @param string $name element name
|
1361 |
+
* @param string $attrs associative array of attributes
|
1362 |
+
*
|
1363 |
+
* @access private
|
1364 |
+
*/
|
1365 |
+
function schemaStartElement( $parser, $name, $attrs ) {
|
1366 |
+
|
1367 |
+
// position in the total number of elements, starting from 0
|
1368 |
+
$pos = $this->position ++;
|
1369 |
+
$depth = $this->depth ++;
|
1370 |
+
// set self as current value for this depth
|
1371 |
+
$this->depth_array[ $depth ] = $pos;
|
1372 |
+
$this->message[ $pos ] = array( 'cdata' => '' );
|
1373 |
+
if ( $depth > 0 ) {
|
1374 |
+
$this->defaultNamespace[ $pos ] = $this->defaultNamespace[ $this->depth_array[ $depth - 1 ] ];
|
1375 |
+
} else {
|
1376 |
+
$this->defaultNamespace[ $pos ] = false;
|
1377 |
+
}
|
1378 |
+
|
1379 |
+
// get element prefix
|
1380 |
+
if ( $prefix = $this->getPrefix( $name ) ) {
|
1381 |
+
// get unqualified name
|
1382 |
+
$name = $this->getLocalPart( $name );
|
1383 |
+
} else {
|
1384 |
+
$prefix = '';
|
1385 |
+
}
|
1386 |
+
|
1387 |
+
// loop thru attributes, expanding, and registering namespace declarations
|
1388 |
+
if ( count( $attrs ) > 0 ) {
|
1389 |
+
foreach ( $attrs as $k => $v ) {
|
1390 |
+
// if ns declarations, add to class level array of valid namespaces
|
1391 |
+
if ( preg_match( '/^xmlns/', $k ) ) {
|
1392 |
+
//$this->xdebug("$k: $v");
|
1393 |
+
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
|
1394 |
+
if ( $ns_prefix = substr( strrchr( $k, ':' ), 1 ) ) {
|
1395 |
+
//$this->xdebug("Add namespace[$ns_prefix] = $v");
|
1396 |
+
$this->namespaces[ $ns_prefix ] = $v;
|
1397 |
+
} else {
|
1398 |
+
$this->defaultNamespace[ $pos ] = $v;
|
1399 |
+
if ( ! $this->getPrefixFromNamespace( $v ) ) {
|
1400 |
+
$this->namespaces[ 'ns' . ( count( $this->namespaces ) + 1 ) ] = $v;
|
1401 |
+
}
|
1402 |
+
}
|
1403 |
+
if ( $v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema' ) {
|
1404 |
+
$this->XMLSchemaVersion = $v;
|
1405 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
1406 |
+
}
|
1407 |
+
}
|
1408 |
+
}
|
1409 |
+
foreach ( $attrs as $k => $v ) {
|
1410 |
+
// expand each attribute
|
1411 |
+
$k = strpos( $k, ':' ) ? $this->expandQname( $k ) : $k;
|
1412 |
+
$v = strpos( $v, ':' ) ? $this->expandQname( $v ) : $v;
|
1413 |
+
$eAttrs[ $k ] = $v;
|
1414 |
+
}
|
1415 |
+
$attrs = $eAttrs;
|
1416 |
+
} else {
|
1417 |
+
$attrs = array();
|
1418 |
+
}
|
1419 |
+
// find status, register data
|
1420 |
+
switch ( $name ) {
|
1421 |
+
case 'all': // (optional) compositor content for a complexType
|
1422 |
+
case 'choice':
|
1423 |
+
case 'group':
|
1424 |
+
case 'sequence':
|
1425 |
+
//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
|
1426 |
+
$this->complexTypes[ $this->currentComplexType ]['compositor'] = $name;
|
1427 |
+
//if($name == 'all' || $name == 'sequence'){
|
1428 |
+
// $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1429 |
+
//}
|
1430 |
+
break;
|
1431 |
+
case 'attribute': // complexType attribute
|
1432 |
+
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
|
1433 |
+
$this->xdebug( "parsing attribute:" );
|
1434 |
+
$this->appendDebug( $this->varDump( $attrs ) );
|
1435 |
+
if ( ! isset( $attrs['form'] ) ) {
|
1436 |
+
// TODO: handle globals
|
1437 |
+
$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
|
1438 |
+
}
|
1439 |
+
if ( isset( $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] ) ) {
|
1440 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1441 |
+
if ( ! strpos( $v, ':' ) ) {
|
1442 |
+
// no namespace in arrayType attribute value...
|
1443 |
+
if ( $this->defaultNamespace[ $pos ] ) {
|
1444 |
+
// ...so use the default
|
1445 |
+
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[ $pos ] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1446 |
+
}
|
1447 |
+
}
|
1448 |
+
}
|
1449 |
+
if ( isset( $attrs['name'] ) ) {
|
1450 |
+
$this->attributes[ $attrs['name'] ] = $attrs;
|
1451 |
+
$aname = $attrs['name'];
|
1452 |
+
} elseif ( isset( $attrs['ref'] ) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType' ) {
|
1453 |
+
if ( isset( $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] ) ) {
|
1454 |
+
$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1455 |
+
} else {
|
1456 |
+
$aname = '';
|
1457 |
+
}
|
1458 |
+
} elseif ( isset( $attrs['ref'] ) ) {
|
1459 |
+
$aname = $attrs['ref'];
|
1460 |
+
$this->attributes[ $attrs['ref'] ] = $attrs;
|
1461 |
+
}
|
1462 |
+
|
1463 |
+
if ( $this->currentComplexType ) { // This should *always* be
|
1464 |
+
$this->complexTypes[ $this->currentComplexType ]['attrs'][ $aname ] = $attrs;
|
1465 |
+
}
|
1466 |
+
// arrayType attribute
|
1467 |
+
if ( isset( $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] ) || $this->getLocalPart( $aname ) == 'arrayType' ) {
|
1468 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'array';
|
1469 |
+
$prefix = $this->getPrefix( $aname );
|
1470 |
+
if ( isset( $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] ) ) {
|
1471 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1472 |
+
} else {
|
1473 |
+
$v = '';
|
1474 |
+
}
|
1475 |
+
if ( strpos( $v, '[,]' ) ) {
|
1476 |
+
$this->complexTypes[ $this->currentComplexType ]['multidimensional'] = true;
|
1477 |
+
}
|
1478 |
+
$v = substr( $v, 0, strpos( $v, '[' ) ); // clip the []
|
1479 |
+
if ( ! strpos( $v, ':' ) && isset( $this->typemap[ $this->XMLSchemaVersion ][ $v ] ) ) {
|
1480 |
+
$v = $this->XMLSchemaVersion . ':' . $v;
|
1481 |
+
}
|
1482 |
+
$this->complexTypes[ $this->currentComplexType ]['arrayType'] = $v;
|
1483 |
+
}
|
1484 |
+
break;
|
1485 |
+
case 'complexContent': // (optional) content for a complexType
|
1486 |
+
$this->xdebug( "do nothing for element $name" );
|
1487 |
+
break;
|
1488 |
+
case 'complexType':
|
1489 |
+
array_push( $this->complexTypeStack, $this->currentComplexType );
|
1490 |
+
if ( isset( $attrs['name'] ) ) {
|
1491 |
+
// TODO: what is the scope of named complexTypes that appear
|
1492 |
+
// nested within other c complexTypes?
|
1493 |
+
$this->xdebug( 'processing named complexType ' . $attrs['name'] );
|
1494 |
+
//$this->currentElement = false;
|
1495 |
+
$this->currentComplexType = $attrs['name'];
|
1496 |
+
$this->complexTypes[ $this->currentComplexType ] = $attrs;
|
1497 |
+
$this->complexTypes[ $this->currentComplexType ]['typeClass'] = 'complexType';
|
1498 |
+
// This is for constructs like
|
1499 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1500 |
+
// <sequence>
|
1501 |
+
// <element name="string" type="xsd:string"
|
1502 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1503 |
+
// </sequence>
|
1504 |
+
// </complexType>
|
1505 |
+
if ( isset( $attrs['base'] ) && preg_match( '/:Array$/', $attrs['base'] ) ) {
|
1506 |
+
$this->xdebug( 'complexType is unusual array' );
|
1507 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'array';
|
1508 |
+
} else {
|
1509 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'struct';
|
1510 |
+
}
|
1511 |
+
} else {
|
1512 |
+
$name = $this->CreateTypeName( $this->currentElement );
|
1513 |
+
$this->xdebug( 'processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name );
|
1514 |
+
$this->currentComplexType = $name;
|
1515 |
+
//$this->currentElement = false;
|
1516 |
+
$this->complexTypes[ $this->currentComplexType ] = $attrs;
|
1517 |
+
$this->complexTypes[ $this->currentComplexType ]['typeClass'] = 'complexType';
|
1518 |
+
// This is for constructs like
|
1519 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1520 |
+
// <sequence>
|
1521 |
+
// <element name="string" type="xsd:string"
|
1522 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1523 |
+
// </sequence>
|
1524 |
+
// </complexType>
|
1525 |
+
if ( isset( $attrs['base'] ) && preg_match( '/:Array$/', $attrs['base'] ) ) {
|
1526 |
+
$this->xdebug( 'complexType is unusual array' );
|
1527 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'array';
|
1528 |
+
} else {
|
1529 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'struct';
|
1530 |
+
}
|
1531 |
+
}
|
1532 |
+
$this->complexTypes[ $this->currentComplexType ]['simpleContent'] = 'false';
|
1533 |
+
break;
|
1534 |
+
case 'element':
|
1535 |
+
array_push( $this->elementStack, $this->currentElement );
|
1536 |
+
if ( ! isset( $attrs['form'] ) ) {
|
1537 |
+
if ( $this->currentComplexType ) {
|
1538 |
+
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
|
1539 |
+
} else {
|
1540 |
+
// global
|
1541 |
+
$attrs['form'] = 'qualified';
|
1542 |
+
}
|
1543 |
+
}
|
1544 |
+
if ( isset( $attrs['type'] ) ) {
|
1545 |
+
$this->xdebug( "processing typed element " . $attrs['name'] . " of type " . $attrs['type'] );
|
1546 |
+
if ( ! $this->getPrefix( $attrs['type'] ) ) {
|
1547 |
+
if ( $this->defaultNamespace[ $pos ] ) {
|
1548 |
+
$attrs['type'] = $this->defaultNamespace[ $pos ] . ':' . $attrs['type'];
|
1549 |
+
$this->xdebug( 'used default namespace to make type ' . $attrs['type'] );
|
1550 |
+
}
|
1551 |
+
}
|
1552 |
+
// This is for constructs like
|
1553 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1554 |
+
// <sequence>
|
1555 |
+
// <element name="string" type="xsd:string"
|
1556 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1557 |
+
// </sequence>
|
1558 |
+
// </complexType>
|
1559 |
+
if ( $this->currentComplexType && $this->complexTypes[ $this->currentComplexType ]['phpType'] == 'array' ) {
|
1560 |
+
$this->xdebug( 'arrayType for unusual array is ' . $attrs['type'] );
|
1561 |
+
$this->complexTypes[ $this->currentComplexType ]['arrayType'] = $attrs['type'];
|
1562 |
+
}
|
1563 |
+
$this->currentElement = $attrs['name'];
|
1564 |
+
$ename = $attrs['name'];
|
1565 |
+
} elseif ( isset( $attrs['ref'] ) ) {
|
1566 |
+
$this->xdebug( "processing element as ref to " . $attrs['ref'] );
|
1567 |
+
$this->currentElement = "ref to " . $attrs['ref'];
|
1568 |
+
$ename = $this->getLocalPart( $attrs['ref'] );
|
1569 |
+
} else {
|
1570 |
+
$type = $this->CreateTypeName( $this->currentComplexType . '_' . $attrs['name'] );
|
1571 |
+
$this->xdebug( "processing untyped element " . $attrs['name'] . ' type ' . $type );
|
1572 |
+
$this->currentElement = $attrs['name'];
|
1573 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
|
1574 |
+
$ename = $attrs['name'];
|
1575 |
+
}
|
1576 |
+
if ( isset( $ename ) && $this->currentComplexType ) {
|
1577 |
+
$this->xdebug( "add element $ename to complexType $this->currentComplexType" );
|
1578 |
+
$this->complexTypes[ $this->currentComplexType ]['elements'][ $ename ] = $attrs;
|
1579 |
+
} elseif ( ! isset( $attrs['ref'] ) ) {
|
1580 |
+
$this->xdebug( "add element $ename to elements array" );
|
1581 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
1582 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
1583 |
+
}
|
1584 |
+
break;
|
1585 |
+
case 'enumeration': // restriction value list member
|
1586 |
+
$this->xdebug( 'enumeration ' . $attrs['value'] );
|
1587 |
+
if ( $this->currentSimpleType ) {
|
1588 |
+
$this->simpleTypes[ $this->currentSimpleType ]['enumeration'][] = $attrs['value'];
|
1589 |
+
} elseif ( $this->currentComplexType ) {
|
1590 |
+
$this->complexTypes[ $this->currentComplexType ]['enumeration'][] = $attrs['value'];
|
1591 |
+
}
|
1592 |
+
break;
|
1593 |
+
case 'extension': // simpleContent or complexContent type extension
|
1594 |
+
$this->xdebug( 'extension ' . $attrs['base'] );
|
1595 |
+
if ( $this->currentComplexType ) {
|
1596 |
+
$ns = $this->getPrefix( $attrs['base'] );
|
1597 |
+
if ( $ns == '' ) {
|
1598 |
+
$this->complexTypes[ $this->currentComplexType ]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
|
1599 |
+
} else {
|
1600 |
+
$this->complexTypes[ $this->currentComplexType ]['extensionBase'] = $attrs['base'];
|
1601 |
+
}
|
1602 |
+
} else {
|
1603 |
+
$this->xdebug( 'no current complexType to set extensionBase' );
|
1604 |
+
}
|
1605 |
+
break;
|
1606 |
+
case 'import':
|
1607 |
+
if ( isset( $attrs['schemaLocation'] ) ) {
|
1608 |
+
$this->xdebug( 'import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation'] );
|
1609 |
+
$this->imports[ $attrs['namespace'] ][] = array(
|
1610 |
+
'location' => $attrs['schemaLocation'],
|
1611 |
+
'loaded' => false
|
1612 |
+
);
|
1613 |
+
} else {
|
1614 |
+
$this->xdebug( 'import namespace ' . $attrs['namespace'] );
|
1615 |
+
$this->imports[ $attrs['namespace'] ][] = array( 'location' => '', 'loaded' => true );
|
1616 |
+
if ( ! $this->getPrefixFromNamespace( $attrs['namespace'] ) ) {
|
1617 |
+
$this->namespaces[ 'ns' . ( count( $this->namespaces ) + 1 ) ] = $attrs['namespace'];
|
1618 |
+
}
|
1619 |
+
}
|
1620 |
+
break;
|
1621 |
+
case 'include':
|
1622 |
+
if ( isset( $attrs['schemaLocation'] ) ) {
|
1623 |
+
$this->xdebug( 'include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation'] );
|
1624 |
+
$this->imports[ $this->schemaTargetNamespace ][] = array(
|
1625 |
+
'location' => $attrs['schemaLocation'],
|
1626 |
+
'loaded' => false
|
1627 |
+
);
|
1628 |
+
} else {
|
1629 |
+
$this->xdebug( 'ignoring invalid XML Schema construct: include without schemaLocation attribute' );
|
1630 |
+
}
|
1631 |
+
break;
|
1632 |
+
case 'list': // simpleType value list
|
1633 |
+
$this->xdebug( "do nothing for element $name" );
|
1634 |
+
break;
|
1635 |
+
case 'restriction': // simpleType, simpleContent or complexContent value restriction
|
1636 |
+
$this->xdebug( 'restriction ' . $attrs['base'] );
|
1637 |
+
if ( $this->currentSimpleType ) {
|
1638 |
+
$this->simpleTypes[ $this->currentSimpleType ]['type'] = $attrs['base'];
|
1639 |
+
} elseif ( $this->currentComplexType ) {
|
1640 |
+
$this->complexTypes[ $this->currentComplexType ]['restrictionBase'] = $attrs['base'];
|
1641 |
+
if ( strstr( $attrs['base'], ':' ) == ':Array' ) {
|
1642 |
+
$this->complexTypes[ $this->currentComplexType ]['phpType'] = 'array';
|
1643 |
+
}
|
1644 |
+
}
|
1645 |
+
break;
|
1646 |
+
case 'schema':
|
1647 |
+
$this->schemaInfo = $attrs;
|
1648 |
+
$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix( $prefix );
|
1649 |
+
if ( isset( $attrs['targetNamespace'] ) ) {
|
1650 |
+
$this->schemaTargetNamespace = $attrs['targetNamespace'];
|
1651 |
+
}
|
1652 |
+
if ( ! isset( $attrs['elementFormDefault'] ) ) {
|
1653 |
+
$this->schemaInfo['elementFormDefault'] = 'unqualified';
|
1654 |
+
}
|
1655 |
+
if ( ! isset( $attrs['attributeFormDefault'] ) ) {
|
1656 |
+
$this->schemaInfo['attributeFormDefault'] = 'unqualified';
|
1657 |
+
}
|
1658 |
+
break;
|
1659 |
+
case 'simpleContent': // (optional) content for a complexType
|
1660 |
+
if ( $this->currentComplexType ) { // This should *always* be
|
1661 |
+
$this->complexTypes[ $this->currentComplexType ]['simpleContent'] = 'true';
|
1662 |
+
} else {
|
1663 |
+
$this->xdebug( "do nothing for element $name because there is no current complexType" );
|
1664 |
+
}
|
1665 |
+
break;
|
1666 |
+
case 'simpleType':
|
1667 |
+
array_push( $this->simpleTypeStack, $this->currentSimpleType );
|
1668 |
+
if ( isset( $attrs['name'] ) ) {
|
1669 |
+
$this->xdebug( "processing simpleType for name " . $attrs['name'] );
|
1670 |
+
$this->currentSimpleType = $attrs['name'];
|
1671 |
+
$this->simpleTypes[ $attrs['name'] ] = $attrs;
|
1672 |
+
$this->simpleTypes[ $attrs['name'] ]['typeClass'] = 'simpleType';
|
1673 |
+
$this->simpleTypes[ $attrs['name'] ]['phpType'] = 'scalar';
|
1674 |
+
} else {
|
1675 |
+
$name = $this->CreateTypeName( $this->currentComplexType . '_' . $this->currentElement );
|
1676 |
+
$this->xdebug( 'processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name );
|
1677 |
+
$this->currentSimpleType = $name;
|
1678 |
+
//$this->currentElement = false;
|
1679 |
+
$this->simpleTypes[ $this->currentSimpleType ] = $attrs;
|
1680 |
+
$this->simpleTypes[ $this->currentSimpleType ]['phpType'] = 'scalar';
|
1681 |
+
}
|
1682 |
+
break;
|
1683 |
+
case 'union': // simpleType type list
|
1684 |
+
$this->xdebug( "do nothing for element $name" );
|
1685 |
+
break;
|
1686 |
+
default:
|
1687 |
+
$this->xdebug( "do not have any logic to process element $name" );
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
|
1691 |
+
/**
|
1692 |
+
* end-element handler
|
1693 |
+
*
|
1694 |
+
* @param string $parser XML parser object
|
1695 |
+
* @param string $name element name
|
1696 |
+
*
|
1697 |
+
* @access private
|
1698 |
+
*/
|
1699 |
+
function schemaEndElement( $parser, $name ) {
|
1700 |
+
// bring depth down a notch
|
1701 |
+
$this->depth --;
|
1702 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
1703 |
+
if ( isset( $this->depth_array[ $this->depth ] ) ) {
|
1704 |
+
$pos = $this->depth_array[ $this->depth ];
|
1705 |
+
}
|
1706 |
+
// get element prefix
|
1707 |
+
if ( $prefix = $this->getPrefix( $name ) ) {
|
1708 |
+
// get unqualified name
|
1709 |
+
$name = $this->getLocalPart( $name );
|
1710 |
+
} else {
|
1711 |
+
$prefix = '';
|
1712 |
+
}
|
1713 |
+
// move on...
|
1714 |
+
if ( $name == 'complexType' ) {
|
1715 |
+
$this->xdebug( 'done processing complexType ' . ( $this->currentComplexType ? $this->currentComplexType : '(unknown)' ) );
|
1716 |
+
$this->xdebug( $this->varDump( $this->complexTypes[ $this->currentComplexType ] ) );
|
1717 |
+
$this->currentComplexType = array_pop( $this->complexTypeStack );
|
1718 |
+
//$this->currentElement = false;
|
1719 |
+
}
|
1720 |
+
if ( $name == 'element' ) {
|
1721 |
+
$this->xdebug( 'done processing element ' . ( $this->currentElement ? $this->currentElement : '(unknown)' ) );
|
1722 |
+
$this->currentElement = array_pop( $this->elementStack );
|
1723 |
+
}
|
1724 |
+
if ( $name == 'simpleType' ) {
|
1725 |
+
$this->xdebug( 'done processing simpleType ' . ( $this->currentSimpleType ? $this->currentSimpleType : '(unknown)' ) );
|
1726 |
+
$this->xdebug( $this->varDump( $this->simpleTypes[ $this->currentSimpleType ] ) );
|
1727 |
+
$this->currentSimpleType = array_pop( $this->simpleTypeStack );
|
1728 |
+
}
|
1729 |
+
}
|
1730 |
+
|
1731 |
+
/**
|
1732 |
+
* element content handler
|
1733 |
+
*
|
1734 |
+
* @param string $parser XML parser object
|
1735 |
+
* @param string $data element content
|
1736 |
+
*
|
1737 |
+
* @access private
|
1738 |
+
*/
|
1739 |
+
function schemaCharacterData( $parser, $data ) {
|
1740 |
+
$pos = $this->depth_array[ $this->depth - 1 ];
|
1741 |
+
$this->message[ $pos ]['cdata'] .= $data;
|
1742 |
+
}
|
1743 |
+
|
1744 |
+
/**
|
1745 |
+
* serialize the schema
|
1746 |
+
*
|
1747 |
+
* @access public
|
1748 |
+
*/
|
1749 |
+
function serializeSchema() {
|
1750 |
+
|
1751 |
+
$schemaPrefix = $this->getPrefixFromNamespace( $this->XMLSchemaVersion );
|
1752 |
+
$xml = '';
|
1753 |
+
// imports
|
1754 |
+
if ( sizeof( $this->imports ) > 0 ) {
|
1755 |
+
foreach ( $this->imports as $ns => $list ) {
|
1756 |
+
foreach ( $list as $ii ) {
|
1757 |
+
if ( $ii['location'] != '' ) {
|
1758 |
+
$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
|
1759 |
+
} else {
|
1760 |
+
$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
|
1761 |
+
}
|
1762 |
+
}
|
1763 |
+
}
|
1764 |
+
}
|
1765 |
+
// complex types
|
1766 |
+
foreach ( $this->complexTypes as $typeName => $attrs ) {
|
1767 |
+
$contentStr = '';
|
1768 |
+
// serialize child elements
|
1769 |
+
if ( isset( $attrs['elements'] ) && ( count( $attrs['elements'] ) > 0 ) ) {
|
1770 |
+
foreach ( $attrs['elements'] as $element => $eParts ) {
|
1771 |
+
if ( isset( $eParts['ref'] ) ) {
|
1772 |
+
$contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
|
1773 |
+
} else {
|
1774 |
+
$contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName( $eParts['type'] ) . "\"";
|
1775 |
+
foreach ( $eParts as $aName => $aValue ) {
|
1776 |
+
// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
|
1777 |
+
if ( $aName != 'name' && $aName != 'type' ) {
|
1778 |
+
$contentStr .= " $aName=\"$aValue\"";
|
1779 |
+
}
|
1780 |
+
}
|
1781 |
+
$contentStr .= "/>\n";
|
1782 |
+
}
|
1783 |
+
}
|
1784 |
+
// compositor wraps elements
|
1785 |
+
if ( isset( $attrs['compositor'] ) && ( $attrs['compositor'] != '' ) ) {
|
1786 |
+
$contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
|
1787 |
+
}
|
1788 |
+
}
|
1789 |
+
// attributes
|
1790 |
+
if ( isset( $attrs['attrs'] ) && ( count( $attrs['attrs'] ) >= 1 ) ) {
|
1791 |
+
foreach ( $attrs['attrs'] as $attr => $aParts ) {
|
1792 |
+
$contentStr .= " <$schemaPrefix:attribute";
|
1793 |
+
foreach ( $aParts as $a => $v ) {
|
1794 |
+
if ( $a == 'ref' || $a == 'type' ) {
|
1795 |
+
$contentStr .= " $a=\"" . $this->contractQName( $v ) . '"';
|
1796 |
+
} elseif ( $a == 'http://schemas.xmlsoap.org/wsdl/:arrayType' ) {
|
1797 |
+
$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
|
1798 |
+
$contentStr .= ' wsdl:arrayType="' . $this->contractQName( $v ) . '"';
|
1799 |
+
} else {
|
1800 |
+
$contentStr .= " $a=\"$v\"";
|
1801 |
+
}
|
1802 |
+
}
|
1803 |
+
$contentStr .= "/>\n";
|
1804 |
+
}
|
1805 |
+
}
|
1806 |
+
// if restriction
|
1807 |
+
if ( isset( $attrs['restrictionBase'] ) && $attrs['restrictionBase'] != '' ) {
|
1808 |
+
$contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName( $attrs['restrictionBase'] ) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
|
1809 |
+
// complex or simple content
|
1810 |
+
if ( ( isset( $attrs['elements'] ) && count( $attrs['elements'] ) > 0 ) || ( isset( $attrs['attrs'] ) && count( $attrs['attrs'] ) > 0 ) ) {
|
1811 |
+
$contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
|
1812 |
+
}
|
1813 |
+
}
|
1814 |
+
// finalize complex type
|
1815 |
+
if ( $contentStr != '' ) {
|
1816 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
|
1817 |
+
} else {
|
1818 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
|
1819 |
+
}
|
1820 |
+
$xml .= $contentStr;
|
1821 |
+
}
|
1822 |
+
// simple types
|
1823 |
+
if ( isset( $this->simpleTypes ) && count( $this->simpleTypes ) > 0 ) {
|
1824 |
+
foreach ( $this->simpleTypes as $typeName => $eParts ) {
|
1825 |
+
$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName( $eParts['type'] ) . "\">\n";
|
1826 |
+
if ( isset( $eParts['enumeration'] ) ) {
|
1827 |
+
foreach ( $eParts['enumeration'] as $e ) {
|
1828 |
+
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
|
1829 |
+
}
|
1830 |
+
}
|
1831 |
+
$xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
|
1832 |
+
}
|
1833 |
+
}
|
1834 |
+
// elements
|
1835 |
+
if ( isset( $this->elements ) && count( $this->elements ) > 0 ) {
|
1836 |
+
foreach ( $this->elements as $element => $eParts ) {
|
1837 |
+
$xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName( $eParts['type'] ) . "\"/>\n";
|
1838 |
+
}
|
1839 |
+
}
|
1840 |
+
// attributes
|
1841 |
+
if ( isset( $this->attributes ) && count( $this->attributes ) > 0 ) {
|
1842 |
+
foreach ( $this->attributes as $attr => $aParts ) {
|
1843 |
+
$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName( $aParts['type'] ) . "\"\n/>";
|
1844 |
+
}
|
1845 |
+
}
|
1846 |
+
// finish 'er up
|
1847 |
+
$attr = '';
|
1848 |
+
foreach ( $this->schemaInfo as $k => $v ) {
|
1849 |
+
if ( $k == 'elementFormDefault' || $k == 'attributeFormDefault' ) {
|
1850 |
+
$attr .= " $k=\"$v\"";
|
1851 |
+
}
|
1852 |
+
}
|
1853 |
+
$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
|
1854 |
+
foreach ( array_diff( $this->usedNamespaces, $this->enclosingNamespaces ) as $nsp => $ns ) {
|
1855 |
+
$el .= " xmlns:$nsp=\"$ns\"";
|
1856 |
+
}
|
1857 |
+
$xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
|
1858 |
+
|
1859 |
+
return $xml;
|
1860 |
+
}
|
1861 |
+
|
1862 |
+
/**
|
1863 |
+
* adds debug data to the clas level debug string
|
1864 |
+
*
|
1865 |
+
* @param string $string debug data
|
1866 |
+
*
|
1867 |
+
* @access private
|
1868 |
+
*/
|
1869 |
+
function xdebug( $string ) {
|
1870 |
+
$this->debug( '<' . $this->schemaTargetNamespace . '> ' . $string );
|
1871 |
+
}
|
1872 |
+
|
1873 |
+
/**
|
1874 |
+
* get the PHP type of a user defined type in the schema
|
1875 |
+
* PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
|
1876 |
+
* returns false if no type exists, or not w/ the given namespace
|
1877 |
+
* else returns a string that is either a native php type, or 'struct'
|
1878 |
+
*
|
1879 |
+
* @param string $type name of defined type
|
1880 |
+
* @param string $ns namespace of type
|
1881 |
+
*
|
1882 |
+
* @return mixed
|
1883 |
+
* @access public
|
1884 |
+
* @deprecated
|
1885 |
+
*/
|
1886 |
+
function getPHPType( $type, $ns ) {
|
1887 |
+
if ( isset( $this->typemap[ $ns ][ $type ] ) ) {
|
1888 |
+
//print "found type '$type' and ns $ns in typemap<br>";
|
1889 |
+
return $this->typemap[ $ns ][ $type ];
|
1890 |
+
} elseif ( isset( $this->complexTypes[ $type ] ) ) {
|
1891 |
+
//print "getting type '$type' and ns $ns from complexTypes array<br>";
|
1892 |
+
return $this->complexTypes[ $type ]['phpType'];
|
1893 |
+
}
|
1894 |
+
|
1895 |
+
return false;
|
1896 |
+
}
|
1897 |
+
|
1898 |
+
/**
|
1899 |
+
* returns an associative array of information about a given type
|
1900 |
+
* returns false if no type exists by the given name
|
1901 |
+
*
|
1902 |
+
* For a complexType typeDef = array(
|
1903 |
+
* 'restrictionBase' => '',
|
1904 |
+
* 'phpType' => '',
|
1905 |
+
* 'compositor' => '(sequence|all)',
|
1906 |
+
* 'elements' => array(), // refs to elements array
|
1907 |
+
* 'attrs' => array() // refs to attributes array
|
1908 |
+
* ... and so on (see addComplexType)
|
1909 |
+
* )
|
1910 |
+
*
|
1911 |
+
* For simpleType or element, the array has different keys.
|
1912 |
+
*
|
1913 |
+
* @param string $type
|
1914 |
+
*
|
1915 |
+
* @return mixed
|
1916 |
+
* @access public
|
1917 |
+
* @see addComplexType
|
1918 |
+
* @see addSimpleType
|
1919 |
+
* @see addElement
|
1920 |
+
*/
|
1921 |
+
function getTypeDef( $type ) {
|
1922 |
+
//$this->debug("in getTypeDef for type $type");
|
1923 |
+
if ( substr( $type, - 1 ) == '^' ) {
|
1924 |
+
$is_element = 1;
|
1925 |
+
$type = substr( $type, 0, - 1 );
|
1926 |
+
} else {
|
1927 |
+
$is_element = 0;
|
1928 |
+
}
|
1929 |
+
|
1930 |
+
if ( ( ! $is_element ) && isset( $this->complexTypes[ $type ] ) ) {
|
1931 |
+
$this->xdebug( "in getTypeDef, found complexType $type" );
|
1932 |
+
|
1933 |
+
return $this->complexTypes[ $type ];
|
1934 |
+
} elseif ( ( ! $is_element ) && isset( $this->simpleTypes[ $type ] ) ) {
|
1935 |
+
$this->xdebug( "in getTypeDef, found simpleType $type" );
|
1936 |
+
if ( ! isset( $this->simpleTypes[ $type ]['phpType'] ) ) {
|
1937 |
+
// get info for type to tack onto the simple type
|
1938 |
+
// TODO: can this ever really apply (i.e. what is a simpleType really?)
|
1939 |
+
$uqType = substr( $this->simpleTypes[ $type ]['type'], strrpos( $this->simpleTypes[ $type ]['type'], ':' ) + 1 );
|
1940 |
+
$ns = substr( $this->simpleTypes[ $type ]['type'], 0, strrpos( $this->simpleTypes[ $type ]['type'], ':' ) );
|
1941 |
+
$etype = $this->getTypeDef( $uqType );
|
1942 |
+
if ( $etype ) {
|
1943 |
+
$this->xdebug( "in getTypeDef, found type for simpleType $type:" );
|
1944 |
+
$this->xdebug( $this->varDump( $etype ) );
|
1945 |
+
if ( isset( $etype['phpType'] ) ) {
|
1946 |
+
$this->simpleTypes[ $type ]['phpType'] = $etype['phpType'];
|
1947 |
+
}
|
1948 |
+
if ( isset( $etype['elements'] ) ) {
|
1949 |
+
$this->simpleTypes[ $type ]['elements'] = $etype['elements'];
|
1950 |
+
}
|
1951 |
+
}
|
1952 |
+
}
|
1953 |
+
|
1954 |
+
return $this->simpleTypes[ $type ];
|
1955 |
+
} elseif ( isset( $this->elements[ $type ] ) ) {
|
1956 |
+
$this->xdebug( "in getTypeDef, found element $type" );
|
1957 |
+
if ( ! isset( $this->elements[ $type ]['phpType'] ) ) {
|
1958 |
+
// get info for type to tack onto the element
|
1959 |
+
$uqType = substr( $this->elements[ $type ]['type'], strrpos( $this->elements[ $type ]['type'], ':' ) + 1 );
|
1960 |
+
$ns = substr( $this->elements[ $type ]['type'], 0, strrpos( $this->elements[ $type ]['type'], ':' ) );
|
1961 |
+
$etype = $this->getTypeDef( $uqType );
|
1962 |
+
if ( $etype ) {
|
1963 |
+
$this->xdebug( "in getTypeDef, found type for element $type:" );
|
1964 |
+
$this->xdebug( $this->varDump( $etype ) );
|
1965 |
+
if ( isset( $etype['phpType'] ) ) {
|
1966 |
+
$this->elements[ $type ]['phpType'] = $etype['phpType'];
|
1967 |
+
}
|
1968 |
+
if ( isset( $etype['elements'] ) ) {
|
1969 |
+
$this->elements[ $type ]['elements'] = $etype['elements'];
|
1970 |
+
}
|
1971 |
+
if ( isset( $etype['extensionBase'] ) ) {
|
1972 |
+
$this->elements[ $type ]['extensionBase'] = $etype['extensionBase'];
|
1973 |
+
}
|
1974 |
+
} elseif ( $ns == 'http://www.w3.org/2001/XMLSchema' ) {
|
1975 |
+
$this->xdebug( "in getTypeDef, element $type is an XSD type" );
|
1976 |
+
$this->elements[ $type ]['phpType'] = 'scalar';
|
1977 |
+
}
|
1978 |
+
}
|
1979 |
+
|
1980 |
+
return $this->elements[ $type ];
|
1981 |
+
} elseif ( isset( $this->attributes[ $type ] ) ) {
|
1982 |
+
$this->xdebug( "in getTypeDef, found attribute $type" );
|
1983 |
+
|
1984 |
+
return $this->attributes[ $type ];
|
1985 |
+
} elseif ( preg_match( '/_ContainedType$/', $type ) ) {
|
1986 |
+
$this->xdebug( "in getTypeDef, have an untyped element $type" );
|
1987 |
+
$typeDef['typeClass'] = 'simpleType';
|
1988 |
+
$typeDef['phpType'] = 'scalar';
|
1989 |
+
$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
|
1990 |
+
|
1991 |
+
return $typeDef;
|
1992 |
+
}
|
1993 |
+
$this->xdebug( "in getTypeDef, did not find $type" );
|
1994 |
+
|
1995 |
+
return false;
|
1996 |
+
}
|
1997 |
+
|
1998 |
+
/**
|
1999 |
+
* returns a sample serialization of a given type, or false if no type by the given name
|
2000 |
+
*
|
2001 |
+
* @param string $type name of type
|
2002 |
+
*
|
2003 |
+
* @return mixed
|
2004 |
+
* @access public
|
2005 |
+
* @deprecated
|
2006 |
+
*/
|
2007 |
+
function serializeTypeDef( $type ) {
|
2008 |
+
//print "in sTD() for type $type<br>";
|
2009 |
+
if ( $typeDef = $this->getTypeDef( $type ) ) {
|
2010 |
+
$str .= '<' . $type;
|
2011 |
+
if ( is_array( $typeDef['attrs'] ) ) {
|
2012 |
+
foreach ( $typeDef['attrs'] as $attName => $data ) {
|
2013 |
+
$str .= " $attName=\"{type = " . $data['type'] . "}\"";
|
2014 |
+
}
|
2015 |
+
}
|
2016 |
+
$str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
|
2017 |
+
if ( count( $typeDef['elements'] ) > 0 ) {
|
2018 |
+
$str .= ">";
|
2019 |
+
foreach ( $typeDef['elements'] as $element => $eData ) {
|
2020 |
+
$str .= $this->serializeTypeDef( $element );
|
2021 |
+
}
|
2022 |
+
$str .= "</$type>";
|
2023 |
+
} elseif ( $typeDef['typeClass'] == 'element' ) {
|
2024 |
+
$str .= "></$type>";
|
2025 |
+
} else {
|
2026 |
+
$str .= "/>";
|
2027 |
+
}
|
2028 |
+
|
2029 |
+
return $str;
|
2030 |
+
}
|
2031 |
+
|
2032 |
+
return false;
|
2033 |
+
}
|
2034 |
+
|
2035 |
+
/**
|
2036 |
+
* returns HTML form elements that allow a user
|
2037 |
+
* to enter values for creating an instance of the given type.
|
2038 |
+
*
|
2039 |
+
* @param string $name name for type instance
|
2040 |
+
* @param string $type name of type
|
2041 |
+
*
|
2042 |
+
* @return string
|
2043 |
+
* @access public
|
2044 |
+
* @deprecated
|
2045 |
+
*/
|
2046 |
+
function typeToForm( $name, $type ) {
|
2047 |
+
// get typedef
|
2048 |
+
if ( $typeDef = $this->getTypeDef( $type ) ) {
|
2049 |
+
// if struct
|
2050 |
+
if ( $typeDef['phpType'] == 'struct' ) {
|
2051 |
+
$buffer .= '<table>';
|
2052 |
+
foreach ( $typeDef['elements'] as $child => $childDef ) {
|
2053 |
+
$buffer .= "
|
2054 |
+
<tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart( $childDef['type'] ) . "):</td>
|
2055 |
+
<td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
|
2056 |
+
}
|
2057 |
+
$buffer .= '</table>';
|
2058 |
+
// if array
|
2059 |
+
} elseif ( $typeDef['phpType'] == 'array' ) {
|
2060 |
+
$buffer .= '<table>';
|
2061 |
+
for ( $i = 0; $i < 3; $i ++ ) {
|
2062 |
+
$buffer .= "
|
2063 |
+
<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
|
2064 |
+
<td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
|
2065 |
+
}
|
2066 |
+
$buffer .= '</table>';
|
2067 |
+
// if scalar
|
2068 |
+
} else {
|
2069 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
2070 |
+
}
|
2071 |
+
} else {
|
2072 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
2073 |
+
}
|
2074 |
+
|
2075 |
+
return $buffer;
|
2076 |
+
}
|
2077 |
+
|
2078 |
+
/**
|
2079 |
+
* adds a complex type to the schema
|
2080 |
+
*
|
2081 |
+
* example: array
|
2082 |
+
*
|
2083 |
+
* addType(
|
2084 |
+
* 'ArrayOfstring',
|
2085 |
+
* 'complexType',
|
2086 |
+
* 'array',
|
2087 |
+
* '',
|
2088 |
+
* 'SOAP-ENC:Array',
|
2089 |
+
* array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
|
2090 |
+
* 'xsd:string'
|
2091 |
+
* );
|
2092 |
+
*
|
2093 |
+
* example: PHP associative array ( SOAP Struct )
|
2094 |
+
*
|
2095 |
+
* addType(
|
2096 |
+
* 'SOAPStruct',
|
2097 |
+
* 'complexType',
|
2098 |
+
* 'struct',
|
2099 |
+
* 'all',
|
2100 |
+
* array('myVar'=> array('name'=>'myVar','type'=>'string')
|
2101 |
+
* );
|
2102 |
+
*
|
2103 |
+
* @param name
|
2104 |
+
* @param typeClass (complexType|simpleType|attribute)
|
2105 |
+
* @param phpType : currently supported are array and struct (php assoc array)
|
2106 |
+
* @param compositor (all|sequence|choice)
|
2107 |
+
* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
2108 |
+
* @param elements = array ( name = array(name=>'',type=>'') )
|
2109 |
+
* @param attrs = array(
|
2110 |
+
* array(
|
2111 |
+
* 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
|
2112 |
+
* "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
|
2113 |
+
* )
|
2114 |
+
* )
|
2115 |
+
* @param arrayType : namespace:name (http://www.w3.org/2001/XMLSchema:string)
|
2116 |
+
*
|
2117 |
+
* @access public
|
2118 |
+
* @see getTypeDef
|
2119 |
+
*/
|
2120 |
+
function addComplexType( $name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '' ) {
|
2121 |
+
$this->complexTypes[ $name ] = array(
|
2122 |
+
'name' => $name,
|
2123 |
+
'typeClass' => $typeClass,
|
2124 |
+
'phpType' => $phpType,
|
2125 |
+
'compositor' => $compositor,
|
2126 |
+
'restrictionBase' => $restrictionBase,
|
2127 |
+
'elements' => $elements,
|
2128 |
+
'attrs' => $attrs,
|
2129 |
+
'arrayType' => $arrayType
|
2130 |
+
);
|
2131 |
+
|
2132 |
+
$this->xdebug( "addComplexType $name:" );
|
2133 |
+
$this->appendDebug( $this->varDump( $this->complexTypes[ $name ] ) );
|
2134 |
+
}
|
2135 |
+
|
2136 |
+
/**
|
2137 |
+
* adds a simple type to the schema
|
2138 |
+
*
|
2139 |
+
* @param string $name
|
2140 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
2141 |
+
* @param string $typeClass (should always be simpleType)
|
2142 |
+
* @param string $phpType (should always be scalar)
|
2143 |
+
* @param array $enumeration array of values
|
2144 |
+
*
|
2145 |
+
* @access public
|
2146 |
+
* @see nusoap_xmlschema
|
2147 |
+
* @see getTypeDef
|
2148 |
+
*/
|
2149 |
+
function addSimpleType( $name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array() ) {
|
2150 |
+
$this->simpleTypes[ $name ] = array(
|
2151 |
+
'name' => $name,
|
2152 |
+
'typeClass' => $typeClass,
|
2153 |
+
'phpType' => $phpType,
|
2154 |
+
'type' => $restrictionBase,
|
2155 |
+
'enumeration' => $enumeration
|
2156 |
+
);
|
2157 |
+
|
2158 |
+
$this->xdebug( "addSimpleType $name:" );
|
2159 |
+
$this->appendDebug( $this->varDump( $this->simpleTypes[ $name ] ) );
|
2160 |
+
}
|
2161 |
+
|
2162 |
+
/**
|
2163 |
+
* adds an element to the schema
|
2164 |
+
*
|
2165 |
+
* @param array $attrs attributes that must include name and type
|
2166 |
+
*
|
2167 |
+
* @see nusoap_xmlschema
|
2168 |
+
* @access public
|
2169 |
+
*/
|
2170 |
+
function addElement( $attrs ) {
|
2171 |
+
if ( ! $this->getPrefix( $attrs['type'] ) ) {
|
2172 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
|
2173 |
+
}
|
2174 |
+
$this->elements[ $attrs['name'] ] = $attrs;
|
2175 |
+
$this->elements[ $attrs['name'] ]['typeClass'] = 'element';
|
2176 |
+
|
2177 |
+
$this->xdebug( "addElement " . $attrs['name'] );
|
2178 |
+
$this->appendDebug( $this->varDump( $this->elements[ $attrs['name'] ] ) );
|
2179 |
+
}
|
2180 |
+
}
|
2181 |
+
|
2182 |
+
/**
|
2183 |
+
* Backward compatibility
|
2184 |
+
*/
|
2185 |
+
class XMLSchema extends nusoap_xmlschema {
|
2186 |
+
}
|
2187 |
+
|
2188 |
+
?><?php
|
2189 |
+
|
2190 |
+
|
2191 |
+
/**
|
2192 |
+
* For creating serializable abstractions of native PHP types. This class
|
2193 |
+
* allows element name/namespace, XSD type, and XML attributes to be
|
2194 |
+
* associated with a value. This is extremely useful when WSDL is not
|
2195 |
+
* used, but is also useful when WSDL is used with polymorphic types, including
|
2196 |
+
* xsd:anyType and user-defined types.
|
2197 |
+
*
|
2198 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2199 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2200 |
+
* @access public
|
2201 |
+
*/
|
2202 |
+
class soapval extends nusoap_base {
|
2203 |
+
/**
|
2204 |
+
* The XML element name
|
2205 |
+
*
|
2206 |
+
* @var string
|
2207 |
+
* @access private
|
2208 |
+
*/
|
2209 |
+
var $name;
|
2210 |
+
/**
|
2211 |
+
* The XML type name (string or false)
|
2212 |
+
*
|
2213 |
+
* @var mixed
|
2214 |
+
* @access private
|
2215 |
+
*/
|
2216 |
+
var $type;
|
2217 |
+
/**
|
2218 |
+
* The PHP value
|
2219 |
+
*
|
2220 |
+
* @var mixed
|
2221 |
+
* @access private
|
2222 |
+
*/
|
2223 |
+
var $value;
|
2224 |
+
/**
|
2225 |
+
* The XML element namespace (string or false)
|
2226 |
+
*
|
2227 |
+
* @var mixed
|
2228 |
+
* @access private
|
2229 |
+
*/
|
2230 |
+
var $element_ns;
|
2231 |
+
/**
|
2232 |
+
* The XML type namespace (string or false)
|
2233 |
+
*
|
2234 |
+
* @var mixed
|
2235 |
+
* @access private
|
2236 |
+
*/
|
2237 |
+
var $type_ns;
|
2238 |
+
/**
|
2239 |
+
* The XML element attributes (array or false)
|
2240 |
+
*
|
2241 |
+
* @var mixed
|
2242 |
+
* @access private
|
2243 |
+
*/
|
2244 |
+
var $attributes;
|
2245 |
+
|
2246 |
+
/**
|
2247 |
+
* constructor
|
2248 |
+
*
|
2249 |
+
* @param string $name optional name
|
2250 |
+
* @param mixed $type optional type name
|
2251 |
+
* @param mixed $value optional value
|
2252 |
+
* @param mixed $element_ns optional namespace of value
|
2253 |
+
* @param mixed $type_ns optional namespace of type
|
2254 |
+
* @param mixed $attributes associative array of attributes to add to element serialization
|
2255 |
+
*
|
2256 |
+
* @access public
|
2257 |
+
*/
|
2258 |
+
function soapval( $name = 'soapval', $type = false, $value = - 1, $element_ns = false, $type_ns = false, $attributes = false ) {
|
2259 |
+
parent::nusoap_base();
|
2260 |
+
$this->name = $name;
|
2261 |
+
$this->type = $type;
|
2262 |
+
$this->value = $value;
|
2263 |
+
$this->element_ns = $element_ns;
|
2264 |
+
$this->type_ns = $type_ns;
|
2265 |
+
$this->attributes = $attributes;
|
2266 |
+
}
|
2267 |
+
|
2268 |
+
/**
|
2269 |
+
* return serialized value
|
2270 |
+
*
|
2271 |
+
* @param string $use The WSDL use value (encoded|literal)
|
2272 |
+
*
|
2273 |
+
* @return string XML data
|
2274 |
+
* @access public
|
2275 |
+
*/
|
2276 |
+
function serialize( $use = 'encoded' ) {
|
2277 |
+
return $this->serialize_val( $this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true );
|
2278 |
+
}
|
2279 |
+
|
2280 |
+
/**
|
2281 |
+
* decodes a soapval object into a PHP native type
|
2282 |
+
*
|
2283 |
+
* @return mixed
|
2284 |
+
* @access public
|
2285 |
+
*/
|
2286 |
+
function decode() {
|
2287 |
+
return $this->value;
|
2288 |
+
}
|
2289 |
+
}
|
2290 |
+
|
2291 |
+
|
2292 |
+
?><?php
|
2293 |
+
|
2294 |
+
|
2295 |
+
/**
|
2296 |
+
* transport class for sending/receiving data via HTTP and HTTPS
|
2297 |
+
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
|
2298 |
+
*
|
2299 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2300 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
2301 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2302 |
+
* @access public
|
2303 |
+
*/
|
2304 |
+
class soap_transport_http extends nusoap_base {
|
2305 |
+
|
2306 |
+
var $url = '';
|
2307 |
+
var $uri = '';
|
2308 |
+
var $digest_uri = '';
|
2309 |
+
var $scheme = '';
|
2310 |
+
var $host = '';
|
2311 |
+
var $port = '';
|
2312 |
+
var $path = '';
|
2313 |
+
var $request_method = 'POST';
|
2314 |
+
var $protocol_version = '1.0';
|
2315 |
+
var $encoding = '';
|
2316 |
+
var $outgoing_headers = array();
|
2317 |
+
var $incoming_headers = array();
|
2318 |
+
var $incoming_cookies = array();
|
2319 |
+
var $outgoing_payload = '';
|
2320 |
+
var $incoming_payload = '';
|
2321 |
+
var $response_status_line; // HTTP response status line
|
2322 |
+
var $useSOAPAction = true;
|
2323 |
+
var $persistentConnection = false;
|
2324 |
+
var $ch = false; // cURL handle
|
2325 |
+
var $ch_options = array(); // cURL custom options
|
2326 |
+
var $use_curl = false; // force cURL use
|
2327 |
+
var $proxy = null; // proxy information (associative array)
|
2328 |
+
var $username = '';
|
2329 |
+
var $password = '';
|
2330 |
+
var $authtype = '';
|
2331 |
+
var $digestRequest = array();
|
2332 |
+
var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
|
2333 |
+
// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
|
2334 |
+
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
|
2335 |
+
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
|
2336 |
+
// passphrase: SSL key password/passphrase
|
2337 |
+
// certpassword: SSL certificate password
|
2338 |
+
// verifypeer: default is 1
|
2339 |
+
// verifyhost: default is 1
|
2340 |
+
|
2341 |
+
/**
|
2342 |
+
* constructor
|
2343 |
+
*
|
2344 |
+
* @param string $url The URL to which to connect
|
2345 |
+
* @param array $curl_options User-specified cURL options
|
2346 |
+
* @param boolean $use_curl Whether to try to force cURL use
|
2347 |
+
*
|
2348 |
+
* @access public
|
2349 |
+
*/
|
2350 |
+
function soap_transport_http( $url, $curl_options = null, $use_curl = false ) {
|
2351 |
+
parent::nusoap_base();
|
2352 |
+
$this->debug( "ctor url=$url use_curl=$use_curl curl_options:" );
|
2353 |
+
$this->appendDebug( $this->varDump( $curl_options ) );
|
2354 |
+
$this->setURL( $url );
|
2355 |
+
if ( is_array( $curl_options ) ) {
|
2356 |
+
$this->ch_options = $curl_options;
|
2357 |
+
}
|
2358 |
+
$this->use_curl = $use_curl;
|
2359 |
+
preg_match( '/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev );
|
2360 |
+
$this->setHeader( 'User-Agent', $this->title . '/' . $this->version . ' (' . $rev[1] . ')' );
|
2361 |
+
}
|
2362 |
+
|
2363 |
+
/**
|
2364 |
+
* sets a cURL option
|
2365 |
+
*
|
2366 |
+
* @param mixed $option The cURL option (always integer?)
|
2367 |
+
* @param mixed $value The cURL option value
|
2368 |
+
*
|
2369 |
+
* @access private
|
2370 |
+
*/
|
2371 |
+
function setCurlOption( $option, $value ) {
|
2372 |
+
$this->debug( "setCurlOption option=$option, value=" );
|
2373 |
+
$this->appendDebug( $this->varDump( $value ) );
|
2374 |
+
curl_setopt( $this->ch, $option, $value );
|
2375 |
+
}
|
2376 |
+
|
2377 |
+
/**
|
2378 |
+
* sets an HTTP header
|
2379 |
+
*
|
2380 |
+
* @param string $name The name of the header
|
2381 |
+
* @param string $value The value of the header
|
2382 |
+
*
|
2383 |
+
* @access private
|
2384 |
+
*/
|
2385 |
+
function setHeader( $name, $value ) {
|
2386 |
+
$this->outgoing_headers[ $name ] = $value;
|
2387 |
+
$this->debug( "set header $name: $value" );
|
2388 |
+
}
|
2389 |
+
|
2390 |
+
/**
|
2391 |
+
* unsets an HTTP header
|
2392 |
+
*
|
2393 |
+
* @param string $name The name of the header
|
2394 |
+
*
|
2395 |
+
* @access private
|
2396 |
+
*/
|
2397 |
+
function unsetHeader( $name ) {
|
2398 |
+
if ( isset( $this->outgoing_headers[ $name ] ) ) {
|
2399 |
+
$this->debug( "unset header $name" );
|
2400 |
+
unset( $this->outgoing_headers[ $name ] );
|
2401 |
+
}
|
2402 |
+
}
|
2403 |
+
|
2404 |
+
/**
|
2405 |
+
* sets the URL to which to connect
|
2406 |
+
*
|
2407 |
+
* @param string $url The URL to which to connect
|
2408 |
+
*
|
2409 |
+
* @access private
|
2410 |
+
*/
|
2411 |
+
function setURL( $url ) {
|
2412 |
+
$this->url = $url;
|
2413 |
+
|
2414 |
+
$u = parse_url( $url );
|
2415 |
+
foreach ( $u as $k => $v ) {
|
2416 |
+
$this->debug( "parsed URL $k = $v" );
|
2417 |
+
$this->$k = $v;
|
2418 |
+
}
|
2419 |
+
|
2420 |
+
// add any GET params to path
|
2421 |
+
if ( isset( $u['query'] ) && $u['query'] != '' ) {
|
2422 |
+
$this->path .= '?' . $u['query'];
|
2423 |
+
}
|
2424 |
+
|
2425 |
+
// set default port
|
2426 |
+
if ( ! isset( $u['port'] ) ) {
|
2427 |
+
if ( $u['scheme'] == 'https' ) {
|
2428 |
+
$this->port = 443;
|
2429 |
+
} else {
|
2430 |
+
$this->port = 80;
|
2431 |
+
}
|
2432 |
+
}
|
2433 |
+
|
2434 |
+
$this->uri = $this->path;
|
2435 |
+
$this->digest_uri = $this->uri;
|
2436 |
+
|
2437 |
+
// build headers
|
2438 |
+
if ( ! isset( $u['port'] ) ) {
|
2439 |
+
$this->setHeader( 'Host', $this->host );
|
2440 |
+
} else {
|
2441 |
+
$this->setHeader( 'Host', $this->host . ':' . $this->port );
|
2442 |
+
}
|
2443 |
+
|
2444 |
+
if ( isset( $u['user'] ) && $u['user'] != '' ) {
|
2445 |
+
$this->setCredentials( urldecode( $u['user'] ), isset( $u['pass'] ) ? urldecode( $u['pass'] ) : '' );
|
2446 |
+
}
|
2447 |
+
}
|
2448 |
+
|
2449 |
+
/**
|
2450 |
+
* gets the I/O method to use
|
2451 |
+
*
|
2452 |
+
* @return string I/O method to use (socket|curl|unknown)
|
2453 |
+
* @access private
|
2454 |
+
*/
|
2455 |
+
function io_method() {
|
2456 |
+
if ( $this->use_curl || ( $this->scheme == 'https' ) || ( $this->scheme == 'http' && $this->authtype == 'ntlm' ) || ( $this->scheme == 'http' && is_array( $this->proxy ) && $this->proxy['authtype'] == 'ntlm' ) ) {
|
2457 |
+
return 'curl';
|
2458 |
+
}
|
2459 |
+
if ( ( $this->scheme == 'http' || $this->scheme == 'ssl' ) && $this->authtype != 'ntlm' && ( ! is_array( $this->proxy ) || $this->proxy['authtype'] != 'ntlm' ) ) {
|
2460 |
+
return 'socket';
|
2461 |
+
}
|
2462 |
+
|
2463 |
+
return 'unknown';
|
2464 |
+
}
|
2465 |
+
|
2466 |
+
/**
|
2467 |
+
* establish an HTTP connection
|
2468 |
+
*
|
2469 |
+
* @param integer $timeout set connection timeout in seconds
|
2470 |
+
* @param integer $response_timeout set response timeout in seconds
|
2471 |
+
*
|
2472 |
+
* @return boolean true if connected, false if not
|
2473 |
+
* @access private
|
2474 |
+
*/
|
2475 |
+
function connect( $connection_timeout = 0, $response_timeout = 30 ) {
|
2476 |
+
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
|
2477 |
+
// "regular" socket.
|
2478 |
+
// TODO: disabled for now because OpenSSL must be *compiled* in (not just
|
2479 |
+
// loaded), and until PHP5 stream_get_wrappers is not available.
|
2480 |
+
// if ($this->scheme == 'https') {
|
2481 |
+
// if (version_compare(phpversion(), '4.3.0') >= 0) {
|
2482 |
+
// if (extension_loaded('openssl')) {
|
2483 |
+
// $this->scheme = 'ssl';
|
2484 |
+
// $this->debug('Using SSL over OpenSSL');
|
2485 |
+
// }
|
2486 |
+
// }
|
2487 |
+
// }
|
2488 |
+
$this->debug( "connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port" );
|
2489 |
+
if ( $this->io_method() == 'socket' ) {
|
2490 |
+
if ( ! is_array( $this->proxy ) ) {
|
2491 |
+
$host = $this->host;
|
2492 |
+
$port = $this->port;
|
2493 |
+
} else {
|
2494 |
+
$host = $this->proxy['host'];
|
2495 |
+
$port = $this->proxy['port'];
|
2496 |
+
}
|
2497 |
+
|
2498 |
+
// use persistent connection
|
2499 |
+
if ( $this->persistentConnection && isset( $this->fp ) && is_resource( $this->fp ) ) {
|
2500 |
+
if ( ! feof( $this->fp ) ) {
|
2501 |
+
$this->debug( 'Re-use persistent connection' );
|
2502 |
+
|
2503 |
+
return true;
|
2504 |
+
}
|
2505 |
+
fclose( $this->fp );
|
2506 |
+
$this->debug( 'Closed persistent connection at EOF' );
|
2507 |
+
}
|
2508 |
+
|
2509 |
+
// munge host if using OpenSSL
|
2510 |
+
if ( $this->scheme == 'ssl' ) {
|
2511 |
+
$host = 'ssl://' . $host;
|
2512 |
+
}
|
2513 |
+
$this->debug( 'calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout );
|
2514 |
+
|
2515 |
+
// open socket
|
2516 |
+
if ( $connection_timeout > 0 ) {
|
2517 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str, $connection_timeout );
|
2518 |
+
} else {
|
2519 |
+
$this->fp = @fsockopen( $host, $this->port, $this->errno, $this->error_str );
|
2520 |
+
}
|
2521 |
+
|
2522 |
+
// test pointer
|
2523 |
+
if ( ! $this->fp ) {
|
2524 |
+
$msg = 'Couldn\'t open socket connection to server ' . $this->url;
|
2525 |
+
if ( $this->errno ) {
|
2526 |
+
$msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
|
2527 |
+
} else {
|
2528 |
+
$msg .= ' prior to connect(). This is often a problem looking up the host name.';
|
2529 |
+
}
|
2530 |
+
$this->debug( $msg );
|
2531 |
+
$this->setError( $msg );
|
2532 |
+
|
2533 |
+
return false;
|
2534 |
+
}
|
2535 |
+
|
2536 |
+
// set response timeout
|
2537 |
+
$this->debug( 'set response timeout to ' . $response_timeout );
|
2538 |
+
socket_set_timeout( $this->fp, $response_timeout );
|
2539 |
+
|
2540 |
+
$this->debug( 'socket connected' );
|
2541 |
+
|
2542 |
+
return true;
|
2543 |
+
} else if ( $this->io_method() == 'curl' ) {
|
2544 |
+
if ( ! extension_loaded( 'curl' ) ) {
|
2545 |
+
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
|
2546 |
+
$this->setError( 'The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.' );
|
2547 |
+
|
2548 |
+
return false;
|
2549 |
+
}
|
2550 |
+
// Avoid warnings when PHP does not have these options
|
2551 |
+
if ( defined( 'CURLOPT_CONNECTIONTIMEOUT' ) ) {
|
2552 |
+
$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
|
2553 |
+
} else {
|
2554 |
+
$CURLOPT_CONNECTIONTIMEOUT = 78;
|
2555 |
+
}
|
2556 |
+
if ( defined( 'CURLOPT_HTTPAUTH' ) ) {
|
2557 |
+
$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
|
2558 |
+
} else {
|
2559 |
+
$CURLOPT_HTTPAUTH = 107;
|
2560 |
+
}
|
2561 |
+
if ( defined( 'CURLOPT_PROXYAUTH' ) ) {
|
2562 |
+
$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
|
2563 |
+
} else {
|
2564 |
+
$CURLOPT_PROXYAUTH = 111;
|
2565 |
+
}
|
2566 |
+
if ( defined( 'CURLAUTH_BASIC' ) ) {
|
2567 |
+
$CURLAUTH_BASIC = CURLAUTH_BASIC;
|
2568 |
+
} else {
|
2569 |
+
$CURLAUTH_BASIC = 1;
|
2570 |
+
}
|
2571 |
+
if ( defined( 'CURLAUTH_DIGEST' ) ) {
|
2572 |
+
$CURLAUTH_DIGEST = CURLAUTH_DIGEST;
|
2573 |
+
} else {
|
2574 |
+
$CURLAUTH_DIGEST = 2;
|
2575 |
+
}
|
2576 |
+
if ( defined( 'CURLAUTH_NTLM' ) ) {
|
2577 |
+
$CURLAUTH_NTLM = CURLAUTH_NTLM;
|
2578 |
+
} else {
|
2579 |
+
$CURLAUTH_NTLM = 8;
|
2580 |
+
}
|
2581 |
+
|
2582 |
+
$this->debug( 'connect using cURL' );
|
2583 |
+
// init CURL
|
2584 |
+
$this->ch = curl_init();
|
2585 |
+
// set url
|
2586 |
+
$hostURL = ( $this->port != '' ) ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
|
2587 |
+
// add path
|
2588 |
+
$hostURL .= $this->path;
|
2589 |
+
$this->setCurlOption( CURLOPT_URL, $hostURL );
|
2590 |
+
// follow location headers (re-directs)
|
2591 |
+
if ( ini_get( 'safe_mode' ) || ini_get( 'open_basedir' ) ) {
|
2592 |
+
$this->debug( 'safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION' );
|
2593 |
+
$this->debug( 'safe_mode = ' );
|
2594 |
+
$this->appendDebug( $this->varDump( ini_get( 'safe_mode' ) ) );
|
2595 |
+
$this->debug( 'open_basedir = ' );
|
2596 |
+
$this->appendDebug( $this->varDump( ini_get( 'open_basedir' ) ) );
|
2597 |
+
} else {
|
2598 |
+
$this->setCurlOption( CURLOPT_FOLLOWLOCATION, 1 );
|
2599 |
+
}
|
2600 |
+
// ask for headers in the response output
|
2601 |
+
$this->setCurlOption( CURLOPT_HEADER, 1 );
|
2602 |
+
// ask for the response output as the return value
|
2603 |
+
$this->setCurlOption( CURLOPT_RETURNTRANSFER, 1 );
|
2604 |
+
// encode
|
2605 |
+
// We manage this ourselves through headers and encoding
|
2606 |
+
// if(function_exists('gzuncompress')){
|
2607 |
+
// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
|
2608 |
+
// }
|
2609 |
+
// persistent connection
|
2610 |
+
if ( $this->persistentConnection ) {
|
2611 |
+
// I believe the following comment is now bogus, having applied to
|
2612 |
+
// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
|
2613 |
+
// The way we send data, we cannot use persistent connections, since
|
2614 |
+
// there will be some "junk" at the end of our request.
|
2615 |
+
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
|
2616 |
+
$this->persistentConnection = false;
|
2617 |
+
$this->setHeader( 'Connection', 'close' );
|
2618 |
+
}
|
2619 |
+
// set timeouts
|
2620 |
+
if ( $connection_timeout != 0 ) {
|
2621 |
+
$this->setCurlOption( $CURLOPT_CONNECTIONTIMEOUT, $connection_timeout );
|
2622 |
+
}
|
2623 |
+
if ( $response_timeout != 0 ) {
|
2624 |
+
$this->setCurlOption( CURLOPT_TIMEOUT, $response_timeout );
|
2625 |
+
}
|
2626 |
+
|
2627 |
+
if ( $this->scheme == 'https' ) {
|
2628 |
+
$this->debug( 'set cURL SSL verify options' );
|
2629 |
+
// recent versions of cURL turn on peer/host checking by default,
|
2630 |
+
// while PHP binaries are not compiled with a default location for the
|
2631 |
+
// CA cert bundle, so disable peer/host checking.
|
2632 |
+
//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
|
2633 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYPEER, 0 );
|
2634 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYHOST, 0 );
|
2635 |
+
|
2636 |
+
// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
|
2637 |
+
if ( $this->authtype == 'certificate' ) {
|
2638 |
+
$this->debug( 'set cURL certificate options' );
|
2639 |
+
if ( isset( $this->certRequest['cainfofile'] ) ) {
|
2640 |
+
$this->setCurlOption( CURLOPT_CAINFO, $this->certRequest['cainfofile'] );
|
2641 |
+
}
|
2642 |
+
if ( isset( $this->certRequest['verifypeer'] ) ) {
|
2643 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer'] );
|
2644 |
+
} else {
|
2645 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYPEER, 1 );
|
2646 |
+
}
|
2647 |
+
if ( isset( $this->certRequest['verifyhost'] ) ) {
|
2648 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost'] );
|
2649 |
+
} else {
|
2650 |
+
$this->setCurlOption( CURLOPT_SSL_VERIFYHOST, 1 );
|
2651 |
+
}
|
2652 |
+
if ( isset( $this->certRequest['sslcertfile'] ) ) {
|
2653 |
+
$this->setCurlOption( CURLOPT_SSLCERT, $this->certRequest['sslcertfile'] );
|
2654 |
+
}
|
2655 |
+
if ( isset( $this->certRequest['sslkeyfile'] ) ) {
|
2656 |
+
$this->setCurlOption( CURLOPT_SSLKEY, $this->certRequest['sslkeyfile'] );
|
2657 |
+
}
|
2658 |
+
if ( isset( $this->certRequest['passphrase'] ) ) {
|
2659 |
+
$this->setCurlOption( CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase'] );
|
2660 |
+
}
|
2661 |
+
if ( isset( $this->certRequest['certpassword'] ) ) {
|
2662 |
+
$this->setCurlOption( CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword'] );
|
2663 |
+
}
|
2664 |
+
}
|
2665 |
+
}
|
2666 |
+
if ( $this->authtype && ( $this->authtype != 'certificate' ) ) {
|
2667 |
+
if ( $this->username ) {
|
2668 |
+
$this->debug( 'set cURL username/password' );
|
2669 |
+
$this->setCurlOption( CURLOPT_USERPWD, "$this->username:$this->password" );
|
2670 |
+
}
|
2671 |
+
if ( $this->authtype == 'basic' ) {
|
2672 |
+
$this->debug( 'set cURL for Basic authentication' );
|
2673 |
+
$this->setCurlOption( $CURLOPT_HTTPAUTH, $CURLAUTH_BASIC );
|
2674 |
+
}
|
2675 |
+
if ( $this->authtype == 'digest' ) {
|
2676 |
+
$this->debug( 'set cURL for digest authentication' );
|
2677 |
+
$this->setCurlOption( $CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST );
|
2678 |
+
}
|
2679 |
+
if ( $this->authtype == 'ntlm' ) {
|
2680 |
+
$this->debug( 'set cURL for NTLM authentication' );
|
2681 |
+
$this->setCurlOption( $CURLOPT_HTTPAUTH, $CURLAUTH_NTLM );
|
2682 |
+
}
|
2683 |
+
}
|
2684 |
+
if ( is_array( $this->proxy ) ) {
|
2685 |
+
$this->debug( 'set cURL proxy options' );
|
2686 |
+
if ( $this->proxy['port'] != '' ) {
|
2687 |
+
$this->setCurlOption( CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port'] );
|
2688 |
+
} else {
|
2689 |
+
$this->setCurlOption( CURLOPT_PROXY, $this->proxy['host'] );
|
2690 |
+
}
|
2691 |
+
if ( $this->proxy['username'] || $this->proxy['password'] ) {
|
2692 |
+
$this->debug( 'set cURL proxy authentication options' );
|
2693 |
+
$this->setCurlOption( CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password'] );
|
2694 |
+
if ( $this->proxy['authtype'] == 'basic' ) {
|
2695 |
+
$this->setCurlOption( $CURLOPT_PROXYAUTH, $CURLAUTH_BASIC );
|
2696 |
+
}
|
2697 |
+
if ( $this->proxy['authtype'] == 'ntlm' ) {
|
2698 |
+
$this->setCurlOption( $CURLOPT_PROXYAUTH, $CURLAUTH_NTLM );
|
2699 |
+
}
|
2700 |
+
}
|
2701 |
+
}
|
2702 |
+
$this->debug( 'cURL connection set up' );
|
2703 |
+
|
2704 |
+
return true;
|
2705 |
+
} else {
|
2706 |
+
$this->setError( 'Unknown scheme ' . $this->scheme );
|
2707 |
+
$this->debug( 'Unknown scheme ' . $this->scheme );
|
2708 |
+
|
2709 |
+
return false;
|
2710 |
+
}
|
2711 |
+
}
|
2712 |
+
|
2713 |
+
/**
|
2714 |
+
* sends the SOAP request and gets the SOAP response via HTTP[S]
|
2715 |
+
*
|
2716 |
+
* @param string $data message data
|
2717 |
+
* @param integer $timeout set connection timeout in seconds
|
2718 |
+
* @param integer $response_timeout set response timeout in seconds
|
2719 |
+
* @param array $cookies cookies to send
|
2720 |
+
*
|
2721 |
+
* @return string data
|
2722 |
+
* @access public
|
2723 |
+
*/
|
2724 |
+
function send( $data, $timeout = 0, $response_timeout = 30, $cookies = null ) {
|
2725 |
+
|
2726 |
+
$this->debug( 'entered send() with data of length: ' . strlen( $data ) );
|
2727 |
+
|
2728 |
+
$this->tryagain = true;
|
2729 |
+
$tries = 0;
|
2730 |
+
while ( $this->tryagain ) {
|
2731 |
+
$this->tryagain = false;
|
2732 |
+
if ( $tries ++ < 2 ) {
|
2733 |
+
// make connnection
|
2734 |
+
if ( ! $this->connect( $timeout, $response_timeout ) ) {
|
2735 |
+
return false;
|
2736 |
+
}
|
2737 |
+
|
2738 |
+
// send request
|
2739 |
+
if ( ! $this->sendRequest( $data, $cookies ) ) {
|
2740 |
+
return false;
|
2741 |
+
}
|
2742 |
+
|
2743 |
+
// get response
|
2744 |
+
$respdata = $this->getResponse();
|
2745 |
+
} else {
|
2746 |
+
$this->setError( "Too many tries to get an OK response ($this->response_status_line)" );
|
2747 |
+
}
|
2748 |
+
}
|
2749 |
+
$this->debug( 'end of send()' );
|
2750 |
+
|
2751 |
+
return $respdata;
|
2752 |
+
}
|
2753 |
+
|
2754 |
+
|
2755 |
+
/**
|
2756 |
+
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
|
2757 |
+
*
|
2758 |
+
* @param string $data message data
|
2759 |
+
* @param integer $timeout set connection timeout in seconds
|
2760 |
+
* @param integer $response_timeout set response timeout in seconds
|
2761 |
+
* @param array $cookies cookies to send
|
2762 |
+
*
|
2763 |
+
* @return string data
|
2764 |
+
* @access public
|
2765 |
+
* @deprecated
|
2766 |
+
*/
|
2767 |
+
function sendHTTPS( $data, $timeout = 0, $response_timeout = 30, $cookies ) {
|
2768 |
+
return $this->send( $data, $timeout, $response_timeout, $cookies );
|
2769 |
+
}
|
2770 |
+
|
2771 |
+
/**
|
2772 |
+
* if authenticating, set user credentials here
|
2773 |
+
*
|
2774 |
+
* @param string $username
|
2775 |
+
* @param string $password
|
2776 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
2777 |
+
* @param array $digestRequest (keys must be nonce, nc, realm, qop)
|
2778 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
2779 |
+
*
|
2780 |
+
* @access public
|
2781 |
+
*/
|
2782 |
+
function setCredentials( $username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array() ) {
|
2783 |
+
$this->debug( "setCredentials username=$username authtype=$authtype digestRequest=" );
|
2784 |
+
$this->appendDebug( $this->varDump( $digestRequest ) );
|
2785 |
+
$this->debug( "certRequest=" );
|
2786 |
+
$this->appendDebug( $this->varDump( $certRequest ) );
|
2787 |
+
// cf. RFC 2617
|
2788 |
+
if ( $authtype == 'basic' ) {
|
2789 |
+
$this->setHeader( 'Authorization', 'Basic ' . base64_encode( str_replace( ':', '', $username ) . ':' . $password ) );
|
2790 |
+
} elseif ( $authtype == 'digest' ) {
|
2791 |
+
if ( isset( $digestRequest['nonce'] ) ) {
|
2792 |
+
$digestRequest['nc'] = isset( $digestRequest['nc'] ) ? $digestRequest['nc'] ++ : 1;
|
2793 |
+
|
2794 |
+
// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
|
2795 |
+
|
2796 |
+
// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
2797 |
+
$A1 = $username . ':' . ( isset( $digestRequest['realm'] ) ? $digestRequest['realm'] : '' ) . ':' . $password;
|
2798 |
+
|
2799 |
+
// H(A1) = MD5(A1)
|
2800 |
+
$HA1 = md5( $A1 );
|
2801 |
+
|
2802 |
+
// A2 = Method ":" digest-uri-value
|
2803 |
+
$A2 = $this->request_method . ':' . $this->digest_uri;
|
2804 |
+
|
2805 |
+
// H(A2)
|
2806 |
+
$HA2 = md5( $A2 );
|
2807 |
+
|
2808 |
+
// KD(secret, data) = H(concat(secret, ":", data))
|
2809 |
+
// if qop == auth:
|
2810 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value)
|
2811 |
+
// ":" nc-value
|
2812 |
+
// ":" unq(cnonce-value)
|
2813 |
+
// ":" unq(qop-value)
|
2814 |
+
// ":" H(A2)
|
2815 |
+
// ) <">
|
2816 |
+
// if qop is missing,
|
2817 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
|
2818 |
+
|
2819 |
+
$unhashedDigest = '';
|
2820 |
+
$nonce = isset( $digestRequest['nonce'] ) ? $digestRequest['nonce'] : '';
|
2821 |
+
$cnonce = $nonce;
|
2822 |
+
if ( $digestRequest['qop'] != '' ) {
|
2823 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf( "%08d", $digestRequest['nc'] ) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
|
2824 |
+
} else {
|
2825 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
|
2826 |
+
}
|
2827 |
+
|
2828 |
+
$hashedDigest = md5( $unhashedDigest );
|
2829 |
+
|
2830 |
+
$opaque = '';
|
2831 |
+
if ( isset( $digestRequest['opaque'] ) ) {
|
2832 |
+
$opaque = ', opaque="' . $digestRequest['opaque'] . '"';
|
2833 |
+
}
|
2834 |
+
|
2835 |
+
$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 . '"' );
|
2836 |
+
}
|
2837 |
+
} elseif ( $authtype == 'certificate' ) {
|
2838 |
+
$this->certRequest = $certRequest;
|
2839 |
+
$this->debug( 'Authorization header not set for certificate' );
|
2840 |
+
} elseif ( $authtype == 'ntlm' ) {
|
2841 |
+
// do nothing
|
2842 |
+
$this->debug( 'Authorization header not set for ntlm' );
|
2843 |
+
}
|
2844 |
+
$this->username = $username;
|
2845 |
+
$this->password = $password;
|
2846 |
+
$this->authtype = $authtype;
|
2847 |
+
$this->digestRequest = $digestRequest;
|
2848 |
+
}
|
2849 |
+
|
2850 |
+
/**
|
2851 |
+
* set the soapaction value
|
2852 |
+
*
|
2853 |
+
* @param string $soapaction
|
2854 |
+
*
|
2855 |
+
* @access public
|
2856 |
+
*/
|
2857 |
+
function setSOAPAction( $soapaction ) {
|
2858 |
+
$this->setHeader( 'SOAPAction', '"' . $soapaction . '"' );
|
2859 |
+
}
|
2860 |
+
|
2861 |
+
/**
|
2862 |
+
* use http encoding
|
2863 |
+
*
|
2864 |
+
* @param string $enc encoding style. supported values: gzip, deflate, or both
|
2865 |
+
*
|
2866 |
+
* @access public
|
2867 |
+
*/
|
2868 |
+
function setEncoding( $enc = 'gzip, deflate' ) {
|
2869 |
+
if ( function_exists( 'gzdeflate' ) ) {
|
2870 |
+
$this->protocol_version = '1.1';
|
2871 |
+
$this->setHeader( 'Accept-Encoding', $enc );
|
2872 |
+
if ( ! isset( $this->outgoing_headers['Connection'] ) ) {
|
2873 |
+
$this->setHeader( 'Connection', 'close' );
|
2874 |
+
$this->persistentConnection = false;
|
2875 |
+
}
|
2876 |
+
// deprecated as of PHP 5.3.0
|
2877 |
+
//set_magic_quotes_runtime(0);
|
2878 |
+
$this->encoding = $enc;
|
2879 |
+
}
|
2880 |
+
}
|
2881 |
+
|
2882 |
+
/**
|
2883 |
+
* set proxy info here
|
2884 |
+
*
|
2885 |
+
* @param string $proxyhost use an empty string to remove proxy
|
2886 |
+
* @param string $proxyport
|
2887 |
+
* @param string $proxyusername
|
2888 |
+
* @param string $proxypassword
|
2889 |
+
* @param string $proxyauthtype (basic|ntlm)
|
2890 |
+
*
|
2891 |
+
* @access public
|
2892 |
+
*/
|
2893 |
+
function setProxy( $proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic' ) {
|
2894 |
+
if ( $proxyhost ) {
|
2895 |
+
$this->proxy = array(
|
2896 |
+
'host' => $proxyhost,
|
2897 |
+
'port' => $proxyport,
|
2898 |
+
'username' => $proxyusername,
|
2899 |
+
'password' => $proxypassword,
|
2900 |
+
'authtype' => $proxyauthtype
|
2901 |
+
);
|
2902 |
+
if ( $proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic' ) {
|
2903 |
+
$this->setHeader( 'Proxy-Authorization', ' Basic ' . base64_encode( $proxyusername . ':' . $proxypassword ) );
|
2904 |
+
}
|
2905 |
+
} else {
|
2906 |
+
$this->debug( 'remove proxy' );
|
2907 |
+
$proxy = null;
|
2908 |
+
unsetHeader( 'Proxy-Authorization' );
|
2909 |
+
}
|
2910 |
+
}
|
2911 |
+
|
2912 |
+
|
2913 |
+
/**
|
2914 |
+
* Test if the given string starts with a header that is to be skipped.
|
2915 |
+
* Skippable headers result from chunked transfer and proxy requests.
|
2916 |
+
*
|
2917 |
+
* @param string $data The string to check.
|
2918 |
+
*
|
2919 |
+
* @returns boolean Whether a skippable header was found.
|
2920 |
+
* @access private
|
2921 |
+
*/
|
2922 |
+
function isSkippableCurlHeader( &$data ) {
|
2923 |
+
$skipHeaders = array(
|
2924 |
+
'HTTP/1.1 100',
|
2925 |
+
'HTTP/1.0 301',
|
2926 |
+
'HTTP/1.1 301',
|
2927 |
+
'HTTP/1.0 302',
|
2928 |
+
'HTTP/1.1 302',
|
2929 |
+
'HTTP/1.0 401',
|
2930 |
+
'HTTP/1.1 401',
|
2931 |
+
'HTTP/1.0 200 Connection established'
|
2932 |
+
);
|
2933 |
+
foreach ( $skipHeaders as $hd ) {
|
2934 |
+
$prefix = substr( $data, 0, strlen( $hd ) );
|
2935 |
+
if ( $prefix == $hd ) {
|
2936 |
+
return true;
|
2937 |
+
}
|
2938 |
+
}
|
2939 |
+
|
2940 |
+
return false;
|
2941 |
+
}
|
2942 |
+
|
2943 |
+
/**
|
2944 |
+
* decode a string that is encoded w/ "chunked' transfer encoding
|
2945 |
+
* as defined in RFC2068 19.4.6
|
2946 |
+
*
|
2947 |
+
* @param string $buffer
|
2948 |
+
* @param string $lb
|
2949 |
+
*
|
2950 |
+
* @returns string
|
2951 |
+
* @access public
|
2952 |
+
* @deprecated
|
2953 |
+
*/
|
2954 |
+
function decodeChunked( $buffer, $lb ) {
|
2955 |
+
// length := 0
|
2956 |
+
$length = 0;
|
2957 |
+
$new = '';
|
2958 |
+
|
2959 |
+
// read chunk-size, chunk-extension (if any) and CRLF
|
2960 |
+
// get the position of the linebreak
|
2961 |
+
$chunkend = strpos( $buffer, $lb );
|
2962 |
+
if ( $chunkend == false ) {
|
2963 |
+
$this->debug( 'no linebreak found in decodeChunked' );
|
2964 |
+
|
2965 |
+
return $new;
|
2966 |
+
}
|
2967 |
+
$temp = substr( $buffer, 0, $chunkend );
|
2968 |
+
$chunk_size = hexdec( trim( $temp ) );
|
2969 |
+
$chunkstart = $chunkend + strlen( $lb );
|
2970 |
+
// while (chunk-size > 0) {
|
2971 |
+
while ( $chunk_size > 0 ) {
|
2972 |
+
$this->debug( "chunkstart: $chunkstart chunk_size: $chunk_size" );
|
2973 |
+
$chunkend = strpos( $buffer, $lb, $chunkstart + $chunk_size );
|
2974 |
+
|
2975 |
+
// Just in case we got a broken connection
|
2976 |
+
if ( $chunkend == false ) {
|
2977 |
+
$chunk = substr( $buffer, $chunkstart );
|
2978 |
+
// append chunk-data to entity-body
|
2979 |
+
$new .= $chunk;
|
2980 |
+
$length += strlen( $chunk );
|
2981 |
+
break;
|
2982 |
+
}
|
2983 |
+
|
2984 |
+
// read chunk-data and CRLF
|
2985 |
+
$chunk = substr( $buffer, $chunkstart, $chunkend - $chunkstart );
|
2986 |
+
// append chunk-data to entity-body
|
2987 |
+
$new .= $chunk;
|
2988 |
+
// length := length + chunk-size
|
2989 |
+
$length += strlen( $chunk );
|
2990 |
+
// read chunk-size and CRLF
|
2991 |
+
$chunkstart = $chunkend + strlen( $lb );
|
2992 |
+
|
2993 |
+
$chunkend = strpos( $buffer, $lb, $chunkstart ) + strlen( $lb );
|
2994 |
+
if ( $chunkend == false ) {
|
2995 |
+
break; //Just in case we got a broken connection
|
2996 |
+
}
|
2997 |
+
$temp = substr( $buffer, $chunkstart, $chunkend - $chunkstart );
|
2998 |
+
$chunk_size = hexdec( trim( $temp ) );
|
2999 |
+
$chunkstart = $chunkend;
|
3000 |
+
}
|
3001 |
+
|
3002 |
+
return $new;
|
3003 |
+
}
|
3004 |
+
|
3005 |
+
/**
|
3006 |
+
* Writes the payload, including HTTP headers, to $this->outgoing_payload.
|
3007 |
+
*
|
3008 |
+
* @param string $data HTTP body
|
3009 |
+
* @param string $cookie_str data for HTTP Cookie header
|
3010 |
+
*
|
3011 |
+
* @return void
|
3012 |
+
* @access private
|
3013 |
+
*/
|
3014 |
+
function buildPayload( $data, $cookie_str = '' ) {
|
3015 |
+
// Note: for cURL connections, $this->outgoing_payload is ignored,
|
3016 |
+
// as is the Content-Length header, but these are still created as
|
3017 |
+
// debugging guides.
|
3018 |
+
|
3019 |
+
// add content-length header
|
3020 |
+
if ( $this->request_method != 'GET' ) {
|
3021 |
+
$this->setHeader( 'Content-Length', strlen( $data ) );
|
3022 |
+
}
|
3023 |
+
|
3024 |
+
// start building outgoing payload:
|
3025 |
+
if ( $this->proxy ) {
|
3026 |
+
$uri = $this->url;
|
3027 |
+
} else {
|
3028 |
+
$uri = $this->uri;
|
3029 |
+
}
|
3030 |
+
$req = "$this->request_method $uri HTTP/$this->protocol_version";
|
3031 |
+
$this->debug( "HTTP request: $req" );
|
3032 |
+
$this->outgoing_payload = "$req\r\n";
|
3033 |
+
|
3034 |
+
// loop thru headers, serializing
|
3035 |
+
foreach ( $this->outgoing_headers as $k => $v ) {
|
3036 |
+
$hdr = $k . ': ' . $v;
|
3037 |
+
$this->debug( "HTTP header: $hdr" );
|
3038 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
3039 |
+
}
|
3040 |
+
|
3041 |
+
// add any cookies
|
3042 |
+
if ( $cookie_str != '' ) {
|
3043 |
+
$hdr = 'Cookie: ' . $cookie_str;
|
3044 |
+
$this->debug( "HTTP header: $hdr" );
|
3045 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
3046 |
+
}
|
3047 |
+
|
3048 |
+
// header/body separator
|
3049 |
+
$this->outgoing_payload .= "\r\n";
|
3050 |
+
|
3051 |
+
// add data
|
3052 |
+
$this->outgoing_payload .= $data;
|
3053 |
+
}
|
3054 |
+
|
3055 |
+
/**
|
3056 |
+
* sends the SOAP request via HTTP[S]
|
3057 |
+
*
|
3058 |
+
* @param string $data message data
|
3059 |
+
* @param array $cookies cookies to send
|
3060 |
+
*
|
3061 |
+
* @return boolean true if OK, false if problem
|
3062 |
+
* @access private
|
3063 |
+
*/
|
3064 |
+
function sendRequest( $data, $cookies = null ) {
|
3065 |
+
// build cookie string
|
3066 |
+
$cookie_str = $this->getCookiesForRequest( $cookies, ( ( $this->scheme == 'ssl' ) || ( $this->scheme == 'https' ) ) );
|
3067 |
+
|
3068 |
+
// build payload
|
3069 |
+
$this->buildPayload( $data, $cookie_str );
|
3070 |
+
|
3071 |
+
if ( $this->io_method() == 'socket' ) {
|
3072 |
+
// send payload
|
3073 |
+
if ( ! fputs( $this->fp, $this->outgoing_payload, strlen( $this->outgoing_payload ) ) ) {
|
3074 |
+
$this->setError( 'couldn\'t write message data to socket' );
|
3075 |
+
$this->debug( 'couldn\'t write message data to socket' );
|
3076 |
+
|
3077 |
+
return false;
|
3078 |
+
}
|
3079 |
+
$this->debug( 'wrote data to socket, length = ' . strlen( $this->outgoing_payload ) );
|
3080 |
+
|
3081 |
+
return true;
|
3082 |
+
} else if ( $this->io_method() == 'curl' ) {
|
3083 |
+
// set payload
|
3084 |
+
// cURL does say this should only be the verb, and in fact it
|
3085 |
+
// turns out that the URI and HTTP version are appended to this, which
|
3086 |
+
// some servers refuse to work with (so we no longer use this method!)
|
3087 |
+
//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
|
3088 |
+
$curl_headers = array();
|
3089 |
+
foreach ( $this->outgoing_headers as $k => $v ) {
|
3090 |
+
if ( $k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization' ) {
|
3091 |
+
$this->debug( "Skip cURL header $k: $v" );
|
3092 |
+
} else {
|
3093 |
+
$curl_headers[] = "$k: $v";
|
3094 |
+
}
|
3095 |
+
}
|
3096 |
+
if ( $cookie_str != '' ) {
|
3097 |
+
$curl_headers[] = 'Cookie: ' . $cookie_str;
|
3098 |
+
}
|
3099 |
+
$this->setCurlOption( CURLOPT_HTTPHEADER, $curl_headers );
|
3100 |
+
$this->debug( 'set cURL HTTP headers' );
|
3101 |
+
if ( $this->request_method == "POST" ) {
|
3102 |
+
$this->setCurlOption( CURLOPT_POST, 1 );
|
3103 |
+
$this->setCurlOption( CURLOPT_POSTFIELDS, $data );
|
3104 |
+
$this->debug( 'set cURL POST data' );
|
3105 |
+
} else {
|
3106 |
+
}
|
3107 |
+
// insert custom user-set cURL options
|
3108 |
+
foreach ( $this->ch_options as $key => $val ) {
|
3109 |
+
$this->setCurlOption( $key, $val );
|
3110 |
+
}
|
3111 |
+
|
3112 |
+
$this->debug( 'set cURL payload' );
|
3113 |
+
|
3114 |
+
return true;
|
3115 |
+
}
|
3116 |
+
}
|
3117 |
+
|
3118 |
+
/**
|
3119 |
+
* gets the SOAP response via HTTP[S]
|
3120 |
+
*
|
3121 |
+
* @return string the response (also sets member variables like incoming_payload)
|
3122 |
+
* @access private
|
3123 |
+
*/
|
3124 |
+
function getResponse() {
|
3125 |
+
$this->incoming_payload = '';
|
3126 |
+
|
3127 |
+
if ( $this->io_method() == 'socket' ) {
|
3128 |
+
// loop until headers have been retrieved
|
3129 |
+
$data = '';
|
3130 |
+
while ( ! isset( $lb ) ) {
|
3131 |
+
|
3132 |
+
// We might EOF during header read.
|
3133 |
+
if ( feof( $this->fp ) ) {
|
3134 |
+
$this->incoming_payload = $data;
|
3135 |
+
$this->debug( 'found no headers before EOF after length ' . strlen( $data ) );
|
3136 |
+
$this->debug( "received before EOF:\n" . $data );
|
3137 |
+
$this->setError( 'server failed to send headers' );
|
3138 |
+
|
3139 |
+
return false;
|
3140 |
+
}
|
3141 |
+
|
3142 |
+
$tmp = fgets( $this->fp, 256 );
|
3143 |
+
$tmplen = strlen( $tmp );
|
3144 |
+
$this->debug( "read line of $tmplen bytes: " . trim( $tmp ) );
|
3145 |
+
|
3146 |
+
if ( $tmplen == 0 ) {
|
3147 |
+
$this->incoming_payload = $data;
|
3148 |
+
$this->debug( 'socket read of headers timed out after length ' . strlen( $data ) );
|
3149 |
+
$this->debug( "read before timeout: " . $data );
|
3150 |
+
$this->setError( 'socket read of headers timed out' );
|
3151 |
+
|
3152 |
+
return false;
|
3153 |
+
}
|
3154 |
+
|
3155 |
+
$data .= $tmp;
|
3156 |
+
$pos = strpos( $data, "\r\n\r\n" );
|
3157 |
+
if ( $pos > 1 ) {
|
3158 |
+
$lb = "\r\n";
|
3159 |
+
} else {
|
3160 |
+
$pos = strpos( $data, "\n\n" );
|
3161 |
+
if ( $pos > 1 ) {
|
3162 |
+
$lb = "\n";
|
3163 |
+
}
|
3164 |
+
}
|
3165 |
+
// remove 100 headers
|
3166 |
+
if ( isset( $lb ) && preg_match( '/^HTTP\/1.1 100/', $data ) ) {
|
3167 |
+
unset( $lb );
|
3168 |
+
$data = '';
|
3169 |
+
}//
|
3170 |
+
}
|
3171 |
+
// store header data
|
3172 |
+
$this->incoming_payload .= $data;
|
3173 |
+
$this->debug( 'found end of headers after length ' . strlen( $data ) );
|
3174 |
+
// process headers
|
3175 |
+
$header_data = trim( substr( $data, 0, $pos ) );
|
3176 |
+
$header_array = explode( $lb, $header_data );
|
3177 |
+
$this->incoming_headers = array();
|
3178 |
+
$this->incoming_cookies = array();
|
3179 |
+
foreach ( $header_array as $header_line ) {
|
3180 |
+
$arr = explode( ':', $header_line, 2 );
|
3181 |
+
if ( count( $arr ) > 1 ) {
|
3182 |
+
$header_name = strtolower( trim( $arr[0] ) );
|
3183 |
+
$this->incoming_headers[ $header_name ] = trim( $arr[1] );
|
3184 |
+
if ( $header_name == 'set-cookie' ) {
|
3185 |
+
// TODO: allow multiple cookies from parseCookie
|
3186 |
+
$cookie = $this->parseCookie( trim( $arr[1] ) );
|
3187 |
+
if ( $cookie ) {
|
3188 |
+
$this->incoming_cookies[] = $cookie;
|
3189 |
+
$this->debug( 'found cookie: ' . $cookie['name'] . ' = ' . $cookie['value'] );
|
3190 |
+
} else {
|
3191 |
+
$this->debug( 'did not find cookie in ' . trim( $arr[1] ) );
|
3192 |
+
}
|
3193 |
+
}
|
3194 |
+
} else if ( isset( $header_name ) ) {
|
3195 |
+
// append continuation line to previous header
|
3196 |
+
$this->incoming_headers[ $header_name ] .= $lb . ' ' . $header_line;
|
3197 |
+
}
|
3198 |
+
}
|
3199 |
+
|
3200 |
+
// loop until msg has been received
|
3201 |
+
if ( isset( $this->incoming_headers['transfer-encoding'] ) && strtolower( $this->incoming_headers['transfer-encoding'] ) == 'chunked' ) {
|
3202 |
+
$content_length = 2147483647; // ignore any content-length header
|
3203 |
+
$chunked = true;
|
3204 |
+
$this->debug( "want to read chunked content" );
|
3205 |
+
} elseif ( isset( $this->incoming_headers['content-length'] ) ) {
|
3206 |
+
$content_length = $this->incoming_headers['content-length'];
|
3207 |
+
$chunked = false;
|
3208 |
+
$this->debug( "want to read content of length $content_length" );
|
3209 |
+
} else {
|
3210 |
+
$content_length = 2147483647;
|
3211 |
+
$chunked = false;
|
3212 |
+
$this->debug( "want to read content to EOF" );
|
3213 |
+
}
|
3214 |
+
$data = '';
|
3215 |
+
do {
|
3216 |
+
if ( $chunked ) {
|
3217 |
+
$tmp = fgets( $this->fp, 256 );
|
3218 |
+
$tmplen = strlen( $tmp );
|
3219 |
+
$this->debug( "read chunk line of $tmplen bytes" );
|
3220 |
+
if ( $tmplen == 0 ) {
|
3221 |
+
$this->incoming_payload = $data;
|
3222 |
+
$this->debug( 'socket read of chunk length timed out after length ' . strlen( $data ) );
|
3223 |
+
$this->debug( "read before timeout:\n" . $data );
|
3224 |
+
$this->setError( 'socket read of chunk length timed out' );
|
3225 |
+
|
3226 |
+
return false;
|
3227 |
+
}
|
3228 |
+
$content_length = hexdec( trim( $tmp ) );
|
3229 |
+
$this->debug( "chunk length $content_length" );
|
3230 |
+
}
|
3231 |
+
$strlen = 0;
|
3232 |
+
while ( ( $strlen < $content_length ) && ( ! feof( $this->fp ) ) ) {
|
3233 |
+
$readlen = min( 8192, $content_length - $strlen );
|
3234 |
+
$tmp = fread( $this->fp, $readlen );
|
3235 |
+
$tmplen = strlen( $tmp );
|
3236 |
+
$this->debug( "read buffer of $tmplen bytes" );
|
3237 |
+
if ( ( $tmplen == 0 ) && ( ! feof( $this->fp ) ) ) {
|
3238 |
+
$this->incoming_payload = $data;
|
3239 |
+
$this->debug( 'socket read of body timed out after length ' . strlen( $data ) );
|
3240 |
+
$this->debug( "read before timeout:\n" . $data );
|
3241 |
+
$this->setError( 'socket read of body timed out' );
|
3242 |
+
|
3243 |
+
return false;
|
3244 |
+
}
|
3245 |
+
$strlen += $tmplen;
|
3246 |
+
$data .= $tmp;
|
3247 |
+
}
|
3248 |
+
if ( $chunked && ( $content_length > 0 ) ) {
|
3249 |
+
$tmp = fgets( $this->fp, 256 );
|
3250 |
+
$tmplen = strlen( $tmp );
|
3251 |
+
$this->debug( "read chunk terminator of $tmplen bytes" );
|
3252 |
+
if ( $tmplen == 0 ) {
|
3253 |
+
$this->incoming_payload = $data;
|
3254 |
+
$this->debug( 'socket read of chunk terminator timed out after length ' . strlen( $data ) );
|
3255 |
+
$this->debug( "read before timeout:\n" . $data );
|
3256 |
+
$this->setError( 'socket read of chunk terminator timed out' );
|
3257 |
+
|
3258 |
+
return false;
|
3259 |
+
}
|
3260 |
+
}
|
3261 |
+
} while ( $chunked && ( $content_length > 0 ) && ( ! feof( $this->fp ) ) );
|
3262 |
+
if ( feof( $this->fp ) ) {
|
3263 |
+
$this->debug( 'read to EOF' );
|
3264 |
+
}
|
3265 |
+
$this->debug( 'read body of length ' . strlen( $data ) );
|
3266 |
+
$this->incoming_payload .= $data;
|
3267 |
+
$this->debug( 'received a total of ' . strlen( $this->incoming_payload ) . ' bytes of data from server' );
|
3268 |
+
|
3269 |
+
// close filepointer
|
3270 |
+
if (
|
3271 |
+
( isset( $this->incoming_headers['connection'] ) && strtolower( $this->incoming_headers['connection'] ) == 'close' ) ||
|
3272 |
+
( ! $this->persistentConnection ) || feof( $this->fp ) ) {
|
3273 |
+
fclose( $this->fp );
|
3274 |
+
$this->fp = false;
|
3275 |
+
$this->debug( 'closed socket' );
|
3276 |
+
}
|
3277 |
+
|
3278 |
+
// connection was closed unexpectedly
|
3279 |
+
if ( $this->incoming_payload == '' ) {
|
3280 |
+
$this->setError( 'no response from server' );
|
3281 |
+
|
3282 |
+
return false;
|
3283 |
+
}
|
3284 |
+
|
3285 |
+
// decode transfer-encoding
|
3286 |
+
// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
|
3287 |
+
// if(!$data = $this->decodeChunked($data, $lb)){
|
3288 |
+
// $this->setError('Decoding of chunked data failed');
|
3289 |
+
// return false;
|
3290 |
+
// }
|
3291 |
+
//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
|
3292 |
+
// set decoded payload
|
3293 |
+
// $this->incoming_payload = $header_data.$lb.$lb.$data;
|
3294 |
+
// }
|
3295 |
+
|
3296 |
+
} else if ( $this->io_method() == 'curl' ) {
|
3297 |
+
// send and receive
|
3298 |
+
$this->debug( 'send and receive with cURL' );
|
3299 |
+
$this->incoming_payload = curl_exec( $this->ch );
|
3300 |
+
$data = $this->incoming_payload;
|
3301 |
+
|
3302 |
+
$cErr = curl_error( $this->ch );
|
3303 |
+
if ( $cErr != '' ) {
|
3304 |
+
$err = 'cURL ERROR: ' . curl_errno( $this->ch ) . ': ' . $cErr . '<br>';
|
3305 |
+
// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
|
3306 |
+
foreach ( curl_getinfo( $this->ch ) as $k => $v ) {
|
3307 |
+
$err .= "$k: $v<br>";
|
3308 |
+
}
|
3309 |
+
$this->debug( $err );
|
3310 |
+
$this->setError( $err );
|
3311 |
+
curl_close( $this->ch );
|
3312 |
+
|
3313 |
+
return false;
|
3314 |
+
} else {
|
3315 |
+
//echo '<pre>';
|
3316 |
+
//var_dump(curl_getinfo($this->ch));
|
3317 |
+
//echo '</pre>';
|
3318 |
+
}
|
3319 |
+
// close curl
|
3320 |
+
$this->debug( 'No cURL error, closing cURL' );
|
3321 |
+
curl_close( $this->ch );
|
3322 |
+
|
3323 |
+
// try removing skippable headers
|
3324 |
+
$savedata = $data;
|
3325 |
+
while ( $this->isSkippableCurlHeader( $data ) ) {
|
3326 |
+
$this->debug( "Found HTTP header to skip" );
|
3327 |
+
if ( $pos = strpos( $data, "\r\n\r\n" ) ) {
|
3328 |
+
$data = ltrim( substr( $data, $pos ) );
|
3329 |
+
} elseif ( $pos = strpos( $data, "\n\n" ) ) {
|
3330 |
+
$data = ltrim( substr( $data, $pos ) );
|
3331 |
+
}
|
3332 |
+
}
|
3333 |
+
|
3334 |
+
if ( $data == '' ) {
|
3335 |
+
// have nothing left; just remove 100 header(s)
|
3336 |
+
$data = $savedata;
|
3337 |
+
while ( preg_match( '/^HTTP\/1.1 100/', $data ) ) {
|
3338 |
+
if ( $pos = strpos( $data, "\r\n\r\n" ) ) {
|
3339 |
+
$data = ltrim( substr( $data, $pos ) );
|
3340 |
+
} elseif ( $pos = strpos( $data, "\n\n" ) ) {
|
3341 |
+
$data = ltrim( substr( $data, $pos ) );
|
3342 |
+
}
|
3343 |
+
}
|
3344 |
+
}
|
3345 |
+
|
3346 |
+
// separate content from HTTP headers
|
3347 |
+
if ( $pos = strpos( $data, "\r\n\r\n" ) ) {
|
3348 |
+
$lb = "\r\n";
|
3349 |
+
} elseif ( $pos = strpos( $data, "\n\n" ) ) {
|
3350 |
+
$lb = "\n";
|
3351 |
+
} else {
|
3352 |
+
$this->debug( 'no proper separation of headers and document' );
|
3353 |
+
$this->setError( 'no proper separation of headers and document' );
|
3354 |
+
|
3355 |
+
return false;
|
3356 |
+
}
|
3357 |
+
$header_data = trim( substr( $data, 0, $pos ) );
|
3358 |
+
$header_array = explode( $lb, $header_data );
|
3359 |
+
$data = ltrim( substr( $data, $pos ) );
|
3360 |
+
$this->debug( 'found proper separation of headers and document' );
|
3361 |
+
$this->debug( 'cleaned data, stringlen: ' . strlen( $data ) );
|
3362 |
+
// clean headers
|
3363 |
+
foreach ( $header_array as $header_line ) {
|
3364 |
+
$arr = explode( ':', $header_line, 2 );
|
3365 |
+
if ( count( $arr ) > 1 ) {
|
3366 |
+
$header_name = strtolower( trim( $arr[0] ) );
|
3367 |
+
$this->incoming_headers[ $header_name ] = trim( $arr[1] );
|
3368 |
+
if ( $header_name == 'set-cookie' ) {
|
3369 |
+
// TODO: allow multiple cookies from parseCookie
|
3370 |
+
$cookie = $this->parseCookie( trim( $arr[1] ) );
|
3371 |
+
if ( $cookie ) {
|
3372 |
+
$this->incoming_cookies[] = $cookie;
|
3373 |
+
$this->debug( 'found cookie: ' . $cookie['name'] . ' = ' . $cookie['value'] );
|
3374 |
+
} else {
|
3375 |
+
$this->debug( 'did not find cookie in ' . trim( $arr[1] ) );
|
3376 |
+
}
|
3377 |
+
}
|
3378 |
+
} else if ( isset( $header_name ) ) {
|
3379 |
+
// append continuation line to previous header
|
3380 |
+
$this->incoming_headers[ $header_name ] .= $lb . ' ' . $header_line;
|
3381 |
+
}
|
3382 |
+
}
|
3383 |
+
}
|
3384 |
+
|
3385 |
+
$this->response_status_line = $header_array[0];
|
3386 |
+
$arr = explode( ' ', $this->response_status_line, 3 );
|
3387 |
+
$http_version = $arr[0];
|
3388 |
+
$http_status = intval( $arr[1] );
|
3389 |
+
$http_reason = count( $arr ) > 2 ? $arr[2] : '';
|
3390 |
+
|
3391 |
+
// see if we need to resend the request with http digest authentication
|
3392 |
+
if ( isset( $this->incoming_headers['location'] ) && ( $http_status == 301 || $http_status == 302 ) ) {
|
3393 |
+
$this->debug( "Got $http_status $http_reason with Location: " . $this->incoming_headers['location'] );
|
3394 |
+
$this->setURL( $this->incoming_headers['location'] );
|
3395 |
+
$this->tryagain = true;
|
3396 |
+
|
3397 |
+
return false;
|
3398 |
+
}
|
3399 |
+
|
3400 |
+
// see if we need to resend the request with http digest authentication
|
3401 |
+
if ( isset( $this->incoming_headers['www-authenticate'] ) && $http_status == 401 ) {
|
3402 |
+
$this->debug( "Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate'] );
|
3403 |
+
if ( strstr( $this->incoming_headers['www-authenticate'], "Digest " ) ) {
|
3404 |
+
$this->debug( 'Server wants digest authentication' );
|
3405 |
+
// remove "Digest " from our elements
|
3406 |
+
$digestString = str_replace( 'Digest ', '', $this->incoming_headers['www-authenticate'] );
|
3407 |
+
|
3408 |
+
// parse elements into array
|
3409 |
+
$digestElements = explode( ',', $digestString );
|
3410 |
+
foreach ( $digestElements as $val ) {
|
3411 |
+
$tempElement = explode( '=', trim( $val ), 2 );
|
3412 |
+
$digestRequest[ $tempElement[0] ] = str_replace( "\"", '', $tempElement[1] );
|
3413 |
+
}
|
3414 |
+
|
3415 |
+
// should have (at least) qop, realm, nonce
|
3416 |
+
if ( isset( $digestRequest['nonce'] ) ) {
|
3417 |
+
$this->setCredentials( $this->username, $this->password, 'digest', $digestRequest );
|
3418 |
+
$this->tryagain = true;
|
3419 |
+
|
3420 |
+
return false;
|
3421 |
+
}
|
3422 |
+
}
|
3423 |
+
$this->debug( 'HTTP authentication failed' );
|
3424 |
+
$this->setError( 'HTTP authentication failed' );
|
3425 |
+
|
3426 |
+
return false;
|
3427 |
+
}
|
3428 |
+
|
3429 |
+
if (
|
3430 |
+
( $http_status >= 300 && $http_status <= 307 ) ||
|
3431 |
+
( $http_status >= 400 && $http_status <= 417 ) ||
|
3432 |
+
( $http_status >= 501 && $http_status <= 505 )
|
3433 |
+
) {
|
3434 |
+
$this->setError( "Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)" );
|
3435 |
+
|
3436 |
+
return false;
|
3437 |
+
}
|
3438 |
+
|
3439 |
+
// decode content-encoding
|
3440 |
+
if ( isset( $this->incoming_headers['content-encoding'] ) && $this->incoming_headers['content-encoding'] != '' ) {
|
3441 |
+
if ( strtolower( $this->incoming_headers['content-encoding'] ) == 'deflate' || strtolower( $this->incoming_headers['content-encoding'] ) == 'gzip' ) {
|
3442 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
3443 |
+
if ( function_exists( 'gzinflate' ) ) {
|
3444 |
+
//$timer->setMarker('starting decoding of gzip/deflated content');
|
3445 |
+
// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
|
3446 |
+
// this means there are no Zlib headers, although there should be
|
3447 |
+
$this->debug( 'The gzinflate function exists' );
|
3448 |
+
$datalen = strlen( $data );
|
3449 |
+
if ( $this->incoming_headers['content-encoding'] == 'deflate' ) {
|
3450 |
+
if ( $degzdata = @gzinflate( $data ) ) {
|
3451 |
+
$data = $degzdata;
|
3452 |
+
$this->debug( 'The payload has been inflated to ' . strlen( $data ) . ' bytes' );
|
3453 |
+
if ( strlen( $data ) < $datalen ) {
|
3454 |
+
// test for the case that the payload has been compressed twice
|
3455 |
+
$this->debug( 'The inflated payload is smaller than the gzipped one; try again' );
|
3456 |
+
if ( $degzdata = @gzinflate( $data ) ) {
|
3457 |
+
$data = $degzdata;
|
3458 |
+
$this->debug( 'The payload has been inflated again to ' . strlen( $data ) . ' bytes' );
|
3459 |
+
}
|
3460 |
+
}
|
3461 |
+
} else {
|
3462 |
+
$this->debug( 'Error using gzinflate to inflate the payload' );
|
3463 |
+
$this->setError( 'Error using gzinflate to inflate the payload' );
|
3464 |
+
}
|
3465 |
+
} elseif ( $this->incoming_headers['content-encoding'] == 'gzip' ) {
|
3466 |
+
if ( $degzdata = @gzinflate( substr( $data, 10 ) ) ) { // do our best
|
3467 |
+
$data = $degzdata;
|
3468 |
+
$this->debug( 'The payload has been un-gzipped to ' . strlen( $data ) . ' bytes' );
|
3469 |
+
if ( strlen( $data ) < $datalen ) {
|
3470 |
+
// test for the case that the payload has been compressed twice
|
3471 |
+
$this->debug( 'The un-gzipped payload is smaller than the gzipped one; try again' );
|
3472 |
+
if ( $degzdata = @gzinflate( substr( $data, 10 ) ) ) {
|
3473 |
+
$data = $degzdata;
|
3474 |
+
$this->debug( 'The payload has been un-gzipped again to ' . strlen( $data ) . ' bytes' );
|
3475 |
+
}
|
3476 |
+
}
|
3477 |
+
} else {
|
3478 |
+
$this->debug( 'Error using gzinflate to un-gzip the payload' );
|
3479 |
+
$this->setError( 'Error using gzinflate to un-gzip the payload' );
|
3480 |
+
}
|
3481 |
+
}
|
3482 |
+
//$timer->setMarker('finished decoding of gzip/deflated content');
|
3483 |
+
//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
|
3484 |
+
// set decoded payload
|
3485 |
+
$this->incoming_payload = $header_data . $lb . $lb . $data;
|
3486 |
+
} else {
|
3487 |
+
$this->debug( 'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.' );
|
3488 |
+
$this->setError( 'The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.' );
|
3489 |
+
}
|
3490 |
+
} else {
|
3491 |
+
$this->debug( 'Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding'] );
|
3492 |
+
$this->setError( 'Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding'] );
|
3493 |
+
}
|
3494 |
+
} else {
|
3495 |
+
$this->debug( 'No Content-Encoding header' );
|
3496 |
+
}
|
3497 |
+
|
3498 |
+
if ( strlen( $data ) == 0 ) {
|
3499 |
+
$this->debug( 'no data after headers!' );
|
3500 |
+
$this->setError( 'no data present after HTTP headers' );
|
3501 |
+
|
3502 |
+
return false;
|
3503 |
+
}
|
3504 |
+
|
3505 |
+
return $data;
|
3506 |
+
}
|
3507 |
+
|
3508 |
+
/**
|
3509 |
+
* sets the content-type for the SOAP message to be sent
|
3510 |
+
*
|
3511 |
+
* @param string $type the content type, MIME style
|
3512 |
+
* @param mixed $charset character set used for encoding (or false)
|
3513 |
+
*
|
3514 |
+
* @access public
|
3515 |
+
*/
|
3516 |
+
function setContentType( $type, $charset = false ) {
|
3517 |
+
$this->setHeader( 'Content-Type', $type . ( $charset ? '; charset=' . $charset : '' ) );
|
3518 |
+
}
|
3519 |
+
|
3520 |
+
/**
|
3521 |
+
* specifies that an HTTP persistent connection should be used
|
3522 |
+
*
|
3523 |
+
* @return boolean whether the request was honored by this method.
|
3524 |
+
* @access public
|
3525 |
+
*/
|
3526 |
+
function usePersistentConnection() {
|
3527 |
+
if ( isset( $this->outgoing_headers['Accept-Encoding'] ) ) {
|
3528 |
+
return false;
|
3529 |
+
}
|
3530 |
+
$this->protocol_version = '1.1';
|
3531 |
+
$this->persistentConnection = true;
|
3532 |
+
$this->setHeader( 'Connection', 'Keep-Alive' );
|
3533 |
+
|
3534 |
+
return true;
|
3535 |
+
}
|
3536 |
+
|
3537 |
+
/**
|
3538 |
+
* parse an incoming Cookie into it's parts
|
3539 |
+
*
|
3540 |
+
* @param string $cookie_str content of cookie
|
3541 |
+
*
|
3542 |
+
* @return array with data of that cookie
|
3543 |
+
* @access private
|
3544 |
+
*/
|
3545 |
+
/*
|
3546 |
+
* TODO: allow a Set-Cookie string to be parsed into multiple cookies
|
3547 |
+
*/
|
3548 |
+
function parseCookie( $cookie_str ) {
|
3549 |
+
$cookie_str = str_replace( '; ', ';', $cookie_str ) . ';';
|
3550 |
+
$data = preg_split( '/;/', $cookie_str );
|
3551 |
+
$value_str = $data[0];
|
3552 |
+
|
3553 |
+
$cookie_param = 'domain=';
|
3554 |
+
$start = strpos( $cookie_str, $cookie_param );
|
3555 |
+
if ( $start > 0 ) {
|
3556 |
+
$domain = substr( $cookie_str, $start + strlen( $cookie_param ) );
|
3557 |
+
$domain = substr( $domain, 0, strpos( $domain, ';' ) );
|
3558 |
+
} else {
|
3559 |
+
$domain = '';
|
3560 |
+
}
|
3561 |
+
|
3562 |
+
$cookie_param = 'expires=';
|
3563 |
+
$start = strpos( $cookie_str, $cookie_param );
|
3564 |
+
if ( $start > 0 ) {
|
3565 |
+
$expires = substr( $cookie_str, $start + strlen( $cookie_param ) );
|
3566 |
+
$expires = substr( $expires, 0, strpos( $expires, ';' ) );
|
3567 |
+
} else {
|
3568 |
+
$expires = '';
|
3569 |
+
}
|
3570 |
+
|
3571 |
+
$cookie_param = 'path=';
|
3572 |
+
$start = strpos( $cookie_str, $cookie_param );
|
3573 |
+
if ( $start > 0 ) {
|
3574 |
+
$path = substr( $cookie_str, $start + strlen( $cookie_param ) );
|
3575 |
+
$path = substr( $path, 0, strpos( $path, ';' ) );
|
3576 |
+
} else {
|
3577 |
+
$path = '/';
|
3578 |
+
}
|
3579 |
+
|
3580 |
+
$cookie_param = ';secure;';
|
3581 |
+
if ( strpos( $cookie_str, $cookie_param ) !== false ) {
|
3582 |
+
$secure = true;
|
3583 |
+
} else {
|
3584 |
+
$secure = false;
|
3585 |
+
}
|
3586 |
+
|
3587 |
+
$sep_pos = strpos( $value_str, '=' );
|
3588 |
+
|
3589 |
+
if ( $sep_pos ) {
|
3590 |
+
$name = substr( $value_str, 0, $sep_pos );
|
3591 |
+
$value = substr( $value_str, $sep_pos + 1 );
|
3592 |
+
$cookie = array(
|
3593 |
+
'name' => $name,
|
3594 |
+
'value' => $value,
|
3595 |
+
'domain' => $domain,
|
3596 |
+
'path' => $path,
|
3597 |
+
'expires' => $expires,
|
3598 |
+
'secure' => $secure
|
3599 |
+
);
|
3600 |
+
|
3601 |
+
return $cookie;
|
3602 |
+
}
|
3603 |
+
|
3604 |
+
return false;
|
3605 |
+
}
|
3606 |
+
|
3607 |
+
/**
|
3608 |
+
* sort out cookies for the current request
|
3609 |
+
*
|
3610 |
+
* @param array $cookies array with all cookies
|
3611 |
+
* @param boolean $secure is the send-content secure or not?
|
3612 |
+
*
|
3613 |
+
* @return string for Cookie-HTTP-Header
|
3614 |
+
* @access private
|
3615 |
+
*/
|
3616 |
+
function getCookiesForRequest( $cookies, $secure = false ) {
|
3617 |
+
$cookie_str = '';
|
3618 |
+
if ( ( ! is_null( $cookies ) ) && ( is_array( $cookies ) ) ) {
|
3619 |
+
foreach ( $cookies as $cookie ) {
|
3620 |
+
if ( ! is_array( $cookie ) ) {
|
3621 |
+
continue;
|
3622 |
+
}
|
3623 |
+
$this->debug( "check cookie for validity: " . $cookie['name'] . '=' . $cookie['value'] );
|
3624 |
+
if ( ( isset( $cookie['expires'] ) ) && ( ! empty( $cookie['expires'] ) ) ) {
|
3625 |
+
if ( strtotime( $cookie['expires'] ) <= time() ) {
|
3626 |
+
$this->debug( 'cookie has expired' );
|
3627 |
+
continue;
|
3628 |
+
}
|
3629 |
+
}
|
3630 |
+
if ( ( isset( $cookie['domain'] ) ) && ( ! empty( $cookie['domain'] ) ) ) {
|
3631 |
+
$domain = preg_quote( $cookie['domain'] );
|
3632 |
+
if ( ! preg_match( "'.*$domain$'i", $this->host ) ) {
|
3633 |
+
$this->debug( 'cookie has different domain' );
|
3634 |
+
continue;
|
3635 |
+
}
|
3636 |
+
}
|
3637 |
+
if ( ( isset( $cookie['path'] ) ) && ( ! empty( $cookie['path'] ) ) ) {
|
3638 |
+
$path = preg_quote( $cookie['path'] );
|
3639 |
+
if ( ! preg_match( "'^$path.*'i", $this->path ) ) {
|
3640 |
+
$this->debug( 'cookie is for a different path' );
|
3641 |
+
continue;
|
3642 |
+
}
|
3643 |
+
}
|
3644 |
+
if ( ( ! $secure ) && ( isset( $cookie['secure'] ) ) && ( $cookie['secure'] ) ) {
|
3645 |
+
$this->debug( 'cookie is secure, transport is not' );
|
3646 |
+
continue;
|
3647 |
+
}
|
3648 |
+
$cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
|
3649 |
+
$this->debug( 'add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value'] );
|
3650 |
+
}
|
3651 |
+
}
|
3652 |
+
|
3653 |
+
return $cookie_str;
|
3654 |
+
}
|
3655 |
+
}
|
3656 |
+
|
3657 |
+
?><?php
|
3658 |
+
|
3659 |
+
|
3660 |
+
/**
|
3661 |
+
*
|
3662 |
+
* nusoap_server allows the user to create a SOAP server
|
3663 |
+
* that is capable of receiving messages and returning responses
|
3664 |
+
*
|
3665 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
3666 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
3667 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
3668 |
+
* @access public
|
3669 |
+
*/
|
3670 |
+
class nusoap_server extends nusoap_base {
|
3671 |
+
/**
|
3672 |
+
* HTTP headers of request
|
3673 |
+
* @var array
|
3674 |
+
* @access private
|
3675 |
+
*/
|
3676 |
+
var $headers = array();
|
3677 |
+
/**
|
3678 |
+
* HTTP request
|
3679 |
+
* @var string
|
3680 |
+
* @access private
|
3681 |
+
*/
|
3682 |
+
var $request = '';
|
3683 |
+
/**
|
3684 |
+
* SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
|
3685 |
+
* @var string
|
3686 |
+
* @access public
|
3687 |
+
*/
|
3688 |
+
var $requestHeaders = '';
|
3689 |
+
/**
|
3690 |
+
* SOAP Headers from request (parsed)
|
3691 |
+
* @var mixed
|
3692 |
+
* @access public
|
3693 |
+
*/
|
3694 |
+
var $requestHeader = null;
|
3695 |
+
/**
|
3696 |
+
* SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
|
3697 |
+
* @var string
|
3698 |
+
* @access public
|
3699 |
+
*/
|
3700 |
+
var $document = '';
|
3701 |
+
/**
|
3702 |
+
* SOAP payload for request (text)
|
3703 |
+
* @var string
|
3704 |
+
* @access public
|
3705 |
+
*/
|
3706 |
+
var $requestSOAP = '';
|
3707 |
+
/**
|
3708 |
+
* requested method namespace URI
|
3709 |
+
* @var string
|
3710 |
+
* @access private
|
3711 |
+
*/
|
3712 |
+
var $methodURI = '';
|
3713 |
+
/**
|
3714 |
+
* name of method requested
|
3715 |
+
* @var string
|
3716 |
+
* @access private
|
3717 |
+
*/
|
3718 |
+
var $methodname = '';
|
3719 |
+
/**
|
3720 |
+
* method parameters from request
|
3721 |
+
* @var array
|
3722 |
+
* @access private
|
3723 |
+
*/
|
3724 |
+
var $methodparams = array();
|
3725 |
+
/**
|
3726 |
+
* SOAP Action from request
|
3727 |
+
* @var string
|
3728 |
+
* @access private
|
3729 |
+
*/
|
3730 |
+
var $SOAPAction = '';
|
3731 |
+
/**
|
3732 |
+
* character set encoding of incoming (request) messages
|
3733 |
+
* @var string
|
3734 |
+
* @access public
|
3735 |
+
*/
|
3736 |
+
var $xml_encoding = '';
|
3737 |
+
/**
|
3738 |
+
* toggles whether the parser decodes element content w/ utf8_decode()
|
3739 |
+
* @var boolean
|
3740 |
+
* @access public
|
3741 |
+
*/
|
3742 |
+
var $decode_utf8 = true;
|
3743 |
+
|
3744 |
+
/**
|
3745 |
+
* HTTP headers of response
|
3746 |
+
* @var array
|
3747 |
+
* @access public
|
3748 |
+
*/
|
3749 |
+
var $outgoing_headers = array();
|
3750 |
+
/**
|
3751 |
+
* HTTP response
|
3752 |
+
* @var string
|
3753 |
+
* @access private
|
3754 |
+
*/
|
3755 |
+
var $response = '';
|
3756 |
+
/**
|
3757 |
+
* SOAP headers for response (text or array of soapval or associative array)
|
3758 |
+
* @var mixed
|
3759 |
+
* @access public
|
3760 |
+
*/
|
3761 |
+
var $responseHeaders = '';
|
3762 |
+
/**
|
3763 |
+
* SOAP payload for response (text)
|
3764 |
+
* @var string
|
3765 |
+
* @access private
|
3766 |
+
*/
|
3767 |
+
var $responseSOAP = '';
|
3768 |
+
/**
|
3769 |
+
* method return value to place in response
|
3770 |
+
* @var mixed
|
3771 |
+
* @access private
|
3772 |
+
*/
|
3773 |
+
var $methodreturn = false;
|
3774 |
+
/**
|
3775 |
+
* whether $methodreturn is a string of literal XML
|
3776 |
+
* @var boolean
|
3777 |
+
* @access public
|
3778 |
+
*/
|
3779 |
+
var $methodreturnisliteralxml = false;
|
3780 |
+
/**
|
3781 |
+
* SOAP fault for response (or false)
|
3782 |
+
* @var mixed
|
3783 |
+
* @access private
|
3784 |
+
*/
|
3785 |
+
var $fault = false;
|
3786 |
+
/**
|
3787 |
+
* text indication of result (for debugging)
|
3788 |
+
* @var string
|
3789 |
+
* @access private
|
3790 |
+
*/
|
3791 |
+
var $result = 'successful';
|
3792 |
+
|
3793 |
+
/**
|
3794 |
+
* assoc array of operations => opData; operations are added by the register()
|
3795 |
+
* method or by parsing an external WSDL definition
|
3796 |
+
* @var array
|
3797 |
+
* @access private
|
3798 |
+
*/
|
3799 |
+
var $operations = array();
|
3800 |
+
/**
|
3801 |
+
* wsdl instance (if one)
|
3802 |
+
* @var mixed
|
3803 |
+
* @access private
|
3804 |
+
*/
|
3805 |
+
var $wsdl = false;
|
3806 |
+
/**
|
3807 |
+
* URL for WSDL (if one)
|
3808 |
+
* @var mixed
|
3809 |
+
* @access private
|
3810 |
+
*/
|
3811 |
+
var $externalWSDLURL = false;
|
3812 |
+
/**
|
3813 |
+
* whether to append debug to response as XML comment
|
3814 |
+
* @var boolean
|
3815 |
+
* @access public
|
3816 |
+
*/
|
3817 |
+
var $debug_flag = false;
|
3818 |
+
|
3819 |
+
|
3820 |
+
/**
|
3821 |
+
* constructor
|
3822 |
+
* the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
|
3823 |
+
*
|
3824 |
+
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
|
3825 |
+
*
|
3826 |
+
* @access public
|
3827 |
+
*/
|
3828 |
+
function nusoap_server( $wsdl = false ) {
|
3829 |
+
parent::nusoap_base();
|
3830 |
+
// turn on debugging?
|
3831 |
+
global $debug;
|
3832 |
+
global $HTTP_SERVER_VARS;
|
3833 |
+
|
3834 |
+
if ( isset( $_SERVER ) ) {
|
3835 |
+
$this->debug( "_SERVER is defined:" );
|
3836 |
+
$this->appendDebug( $this->varDump( $_SERVER ) );
|
3837 |
+
} elseif ( isset( $HTTP_SERVER_VARS ) ) {
|
3838 |
+
$this->debug( "HTTP_SERVER_VARS is defined:" );
|
3839 |
+
$this->appendDebug( $this->varDump( $HTTP_SERVER_VARS ) );
|
3840 |
+
} else {
|
3841 |
+
$this->debug( "Neither _SERVER nor HTTP_SERVER_VARS is defined." );
|
3842 |
+
}
|
3843 |
+
|
3844 |
+
if ( isset( $debug ) ) {
|
3845 |
+
$this->debug( "In nusoap_server, set debug_flag=$debug based on global flag" );
|
3846 |
+
$this->debug_flag = $debug;
|
3847 |
+
} elseif ( isset( $_SERVER['QUERY_STRING'] ) ) {
|
3848 |
+
$qs = explode( '&', $_SERVER['QUERY_STRING'] );
|
3849 |
+
foreach ( $qs as $v ) {
|
3850 |
+
if ( substr( $v, 0, 6 ) == 'debug=' ) {
|
3851 |
+
$this->debug( "In nusoap_server, set debug_flag=" . substr( $v, 6 ) . " based on query string #1" );
|
3852 |
+
$this->debug_flag = substr( $v, 6 );
|
3853 |
+
}
|
3854 |
+
}
|
3855 |
+
} elseif ( isset( $HTTP_SERVER_VARS['QUERY_STRING'] ) ) {
|
3856 |
+
$qs = explode( '&', $HTTP_SERVER_VARS['QUERY_STRING'] );
|
3857 |
+
foreach ( $qs as $v ) {
|
3858 |
+
if ( substr( $v, 0, 6 ) == 'debug=' ) {
|
3859 |
+
$this->debug( "In nusoap_server, set debug_flag=" . substr( $v, 6 ) . " based on query string #2" );
|
3860 |
+
$this->debug_flag = substr( $v, 6 );
|
3861 |
+
}
|
3862 |
+
}
|
3863 |
+
}
|
3864 |
+
|
3865 |
+
// wsdl
|
3866 |
+
if ( $wsdl ) {
|
3867 |
+
$this->debug( "In nusoap_server, WSDL is specified" );
|
3868 |
+
if ( is_object( $wsdl ) && ( get_class( $wsdl ) == 'wsdl' ) ) {
|
3869 |
+
$this->wsdl = $wsdl;
|
3870 |
+
$this->externalWSDLURL = $this->wsdl->wsdl;
|
3871 |
+
$this->debug( 'Use existing wsdl instance from ' . $this->externalWSDLURL );
|
3872 |
+
} else {
|
3873 |
+
$this->debug( 'Create wsdl from ' . $wsdl );
|
3874 |
+
$this->wsdl = new wsdl( $wsdl );
|
3875 |
+
$this->externalWSDLURL = $wsdl;
|
3876 |
+
}
|
3877 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
3878 |
+
$this->wsdl->clearDebug();
|
3879 |
+
if ( $err = $this->wsdl->getError() ) {
|
3880 |
+
die( 'WSDL ERROR: ' . $err );
|
3881 |
+
}
|
3882 |
+
}
|
3883 |
+
}
|
3884 |
+
|
3885 |
+
/**
|
3886 |
+
* processes request and returns response
|
3887 |
+
*
|
3888 |
+
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
|
3889 |
+
*
|
3890 |
+
* @access public
|
3891 |
+
*/
|
3892 |
+
function service( $data ) {
|
3893 |
+
global $HTTP_SERVER_VARS;
|
3894 |
+
|
3895 |
+
if ( isset( $_SERVER['REQUEST_METHOD'] ) ) {
|
3896 |
+
$rm = $_SERVER['REQUEST_METHOD'];
|
3897 |
+
} elseif ( isset( $HTTP_SERVER_VARS['REQUEST_METHOD'] ) ) {
|
3898 |
+
$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
|
3899 |
+
} else {
|
3900 |
+
$rm = '';
|
3901 |
+
}
|
3902 |
+
|
3903 |
+
if ( isset( $_SERVER['QUERY_STRING'] ) ) {
|
3904 |
+
$qs = $_SERVER['QUERY_STRING'];
|
3905 |
+
} elseif ( isset( $HTTP_SERVER_VARS['QUERY_STRING'] ) ) {
|
3906 |
+
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
|
3907 |
+
} else {
|
3908 |
+
$qs = '';
|
3909 |
+
}
|
3910 |
+
$this->debug( "In service, request method=$rm query string=$qs strlen(\$data)=" . strlen( $data ) );
|
3911 |
+
|
3912 |
+
if ( $rm == 'POST' ) {
|
3913 |
+
$this->debug( "In service, invoke the request" );
|
3914 |
+
$this->parse_request( $data );
|
3915 |
+
if ( ! $this->fault ) {
|
3916 |
+
$this->invoke_method();
|
3917 |
+
}
|
3918 |
+
if ( ! $this->fault ) {
|
3919 |
+
$this->serialize_return();
|
3920 |
+
}
|
3921 |
+
$this->send_response();
|
3922 |
+
} elseif ( preg_match( '/wsdl/', $qs ) ) {
|
3923 |
+
$this->debug( "In service, this is a request for WSDL" );
|
3924 |
+
if ( $this->externalWSDLURL ) {
|
3925 |
+
if ( strpos( $this->externalWSDLURL, "http://" ) !== false ) { // assume URL
|
3926 |
+
$this->debug( "In service, re-direct for WSDL" );
|
3927 |
+
header( 'Location: ' . $this->externalWSDLURL );
|
3928 |
+
} else { // assume file
|
3929 |
+
$this->debug( "In service, use file passthru for WSDL" );
|
3930 |
+
header( "Content-Type: text/xml\r\n" );
|
3931 |
+
$pos = strpos( $this->externalWSDLURL, "file://" );
|
3932 |
+
if ( $pos === false ) {
|
3933 |
+
$filename = $this->externalWSDLURL;
|
3934 |
+
} else {
|
3935 |
+
$filename = substr( $this->externalWSDLURL, $pos + 7 );
|
3936 |
+
}
|
3937 |
+
$fp = fopen( $this->externalWSDLURL, 'r' );
|
3938 |
+
fpassthru( $fp );
|
3939 |
+
}
|
3940 |
+
} elseif ( $this->wsdl ) {
|
3941 |
+
$this->debug( "In service, serialize WSDL" );
|
3942 |
+
header( "Content-Type: text/xml; charset=ISO-8859-1\r\n" );
|
3943 |
+
print $this->wsdl->serialize( $this->debug_flag );
|
3944 |
+
if ( $this->debug_flag ) {
|
3945 |
+
$this->debug( 'wsdl:' );
|
3946 |
+
$this->appendDebug( $this->varDump( $this->wsdl ) );
|
3947 |
+
print $this->getDebugAsXMLComment();
|
3948 |
+
}
|
3949 |
+
} else {
|
3950 |
+
$this->debug( "In service, there is no WSDL" );
|
3951 |
+
header( "Content-Type: text/html; charset=ISO-8859-1\r\n" );
|
3952 |
+
print "This service does not provide WSDL";
|
3953 |
+
}
|
3954 |
+
} elseif ( $this->wsdl ) {
|
3955 |
+
$this->debug( "In service, return Web description" );
|
3956 |
+
print $this->wsdl->webDescription();
|
3957 |
+
} else {
|
3958 |
+
$this->debug( "In service, no Web description" );
|
3959 |
+
header( "Content-Type: text/html; charset=ISO-8859-1\r\n" );
|
3960 |
+
print "This service does not provide a Web description";
|
3961 |
+
}
|
3962 |
+
}
|
3963 |
+
|
3964 |
+
/**
|
3965 |
+
* parses HTTP request headers.
|
3966 |
+
*
|
3967 |
+
* The following fields are set by this function (when successful)
|
3968 |
+
*
|
3969 |
+
* headers
|
3970 |
+
* request
|
3971 |
+
* xml_encoding
|
3972 |
+
* SOAPAction
|
3973 |
+
*
|
3974 |
+
* @access private
|
3975 |
+
*/
|
3976 |
+
function parse_http_headers() {
|
3977 |
+
global $HTTP_SERVER_VARS;
|
3978 |
+
|
3979 |
+
$this->request = '';
|
3980 |
+
$this->SOAPAction = '';
|
3981 |
+
if ( function_exists( 'getallheaders' ) ) {
|
3982 |
+
$this->debug( "In parse_http_headers, use getallheaders" );
|
3983 |
+
$headers = getallheaders();
|
3984 |
+
foreach ( $headers as $k => $v ) {
|
3985 |
+
$k = strtolower( $k );
|
3986 |
+
$this->headers[ $k ] = $v;
|
3987 |
+
$this->request .= "$k: $v\r\n";
|
3988 |
+
$this->debug( "$k: $v" );
|
3989 |
+
}
|
3990 |
+
// get SOAPAction header
|
3991 |
+
if ( isset( $this->headers['soapaction'] ) ) {
|
3992 |
+
$this->SOAPAction = str_replace( '"', '', $this->headers['soapaction'] );
|
3993 |
+
}
|
3994 |
+
// get the character encoding of the incoming request
|
3995 |
+
if ( isset( $this->headers['content-type'] ) && strpos( $this->headers['content-type'], '=' ) ) {
|
3996 |
+
$enc = str_replace( '"', '', substr( strstr( $this->headers["content-type"], '=' ), 1 ) );
|
3997 |
+
if ( preg_match( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc ) ) {
|
3998 |
+
$this->xml_encoding = strtoupper( $enc );
|
3999 |
+
} else {
|
4000 |
+
$this->xml_encoding = 'US-ASCII';
|
4001 |
+
}
|
4002 |
+
} else {
|
4003 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4004 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4005 |
+
}
|
4006 |
+
} elseif ( isset( $_SERVER ) && is_array( $_SERVER ) ) {
|
4007 |
+
$this->debug( "In parse_http_headers, use _SERVER" );
|
4008 |
+
foreach ( $_SERVER as $k => $v ) {
|
4009 |
+
if ( substr( $k, 0, 5 ) == 'HTTP_' ) {
|
4010 |
+
$k = str_replace( ' ', '-', strtolower( str_replace( '_', ' ', substr( $k, 5 ) ) ) );
|
4011 |
+
} else {
|
4012 |
+
$k = str_replace( ' ', '-', strtolower( str_replace( '_', ' ', $k ) ) );
|
4013 |
+
}
|
4014 |
+
if ( $k == 'soapaction' ) {
|
4015 |
+
// get SOAPAction header
|
4016 |
+
$k = 'SOAPAction';
|
4017 |
+
$v = str_replace( '"', '', $v );
|
4018 |
+
$v = str_replace( '\\', '', $v );
|
4019 |
+
$this->SOAPAction = $v;
|
4020 |
+
} else if ( $k == 'content-type' ) {
|
4021 |
+
// get the character encoding of the incoming request
|
4022 |
+
if ( strpos( $v, '=' ) ) {
|
4023 |
+
$enc = substr( strstr( $v, '=' ), 1 );
|
4024 |
+
$enc = str_replace( '"', '', $enc );
|
4025 |
+
$enc = str_replace( '\\', '', $enc );
|
4026 |
+
if ( preg_match( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc ) ) {
|
4027 |
+
$this->xml_encoding = strtoupper( $enc );
|
4028 |
+
} else {
|
4029 |
+
$this->xml_encoding = 'US-ASCII';
|
4030 |
+
}
|
4031 |
+
} else {
|
4032 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4033 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4034 |
+
}
|
4035 |
+
}
|
4036 |
+
$this->headers[ $k ] = $v;
|
4037 |
+
$this->request .= "$k: $v\r\n";
|
4038 |
+
$this->debug( "$k: $v" );
|
4039 |
+
}
|
4040 |
+
} elseif ( is_array( $HTTP_SERVER_VARS ) ) {
|
4041 |
+
$this->debug( "In parse_http_headers, use HTTP_SERVER_VARS" );
|
4042 |
+
foreach ( $HTTP_SERVER_VARS as $k => $v ) {
|
4043 |
+
if ( substr( $k, 0, 5 ) == 'HTTP_' ) {
|
4044 |
+
$k = str_replace( ' ', '-', strtolower( str_replace( '_', ' ', substr( $k, 5 ) ) ) );
|
4045 |
+
$k = strtolower( substr( $k, 5 ) );
|
4046 |
+
} else {
|
4047 |
+
$k = str_replace( ' ', '-', strtolower( str_replace( '_', ' ', $k ) ) );
|
4048 |
+
$k = strtolower( $k );
|
4049 |
+
}
|
4050 |
+
if ( $k == 'soapaction' ) {
|
4051 |
+
// get SOAPAction header
|
4052 |
+
$k = 'SOAPAction';
|
4053 |
+
$v = str_replace( '"', '', $v );
|
4054 |
+
$v = str_replace( '\\', '', $v );
|
4055 |
+
$this->SOAPAction = $v;
|
4056 |
+
} else if ( $k == 'content-type' ) {
|
4057 |
+
// get the character encoding of the incoming request
|
4058 |
+
if ( strpos( $v, '=' ) ) {
|
4059 |
+
$enc = substr( strstr( $v, '=' ), 1 );
|
4060 |
+
$enc = str_replace( '"', '', $enc );
|
4061 |
+
$enc = str_replace( '\\', '', $enc );
|
4062 |
+
if ( preg_match( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc ) ) {
|
4063 |
+
$this->xml_encoding = strtoupper( $enc );
|
4064 |
+
} else {
|
4065 |
+
$this->xml_encoding = 'US-ASCII';
|
4066 |
+
}
|
4067 |
+
} else {
|
4068 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4069 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4070 |
+
}
|
4071 |
+
}
|
4072 |
+
$this->headers[ $k ] = $v;
|
4073 |
+
$this->request .= "$k: $v\r\n";
|
4074 |
+
$this->debug( "$k: $v" );
|
4075 |
+
}
|
4076 |
+
} else {
|
4077 |
+
$this->debug( "In parse_http_headers, HTTP headers not accessible" );
|
4078 |
+
$this->setError( "HTTP headers not accessible" );
|
4079 |
+
}
|
4080 |
+
}
|
4081 |
+
|
4082 |
+
/**
|
4083 |
+
* parses a request
|
4084 |
+
*
|
4085 |
+
* The following fields are set by this function (when successful)
|
4086 |
+
*
|
4087 |
+
* headers
|
4088 |
+
* request
|
4089 |
+
* xml_encoding
|
4090 |
+
* SOAPAction
|
4091 |
+
* request
|
4092 |
+
* requestSOAP
|
4093 |
+
* methodURI
|
4094 |
+
* methodname
|
4095 |
+
* methodparams
|
4096 |
+
* requestHeaders
|
4097 |
+
* document
|
4098 |
+
*
|
4099 |
+
* This sets the fault field on error
|
4100 |
+
*
|
4101 |
+
* @param string $data XML string
|
4102 |
+
*
|
4103 |
+
* @access private
|
4104 |
+
*/
|
4105 |
+
function parse_request( $data = '' ) {
|
4106 |
+
$this->debug( 'entering parse_request()' );
|
4107 |
+
$this->parse_http_headers();
|
4108 |
+
$this->debug( 'got character encoding: ' . $this->xml_encoding );
|
4109 |
+
// uncompress if necessary
|
4110 |
+
if ( isset( $this->headers['content-encoding'] ) && $this->headers['content-encoding'] != '' ) {
|
4111 |
+
$this->debug( 'got content encoding: ' . $this->headers['content-encoding'] );
|
4112 |
+
if ( $this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip' ) {
|
4113 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
4114 |
+
if ( function_exists( 'gzuncompress' ) ) {
|
4115 |
+
if ( $this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress( $data ) ) {
|
4116 |
+
$data = $degzdata;
|
4117 |
+
} elseif ( $this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate( substr( $data, 10 ) ) ) {
|
4118 |
+
$data = $degzdata;
|
4119 |
+
} else {
|
4120 |
+
$this->fault( 'SOAP-ENV:Client', 'Errors occurred when trying to decode the data' );
|
4121 |
+
|
4122 |
+
return;
|
4123 |
+
}
|
4124 |
+
} else {
|
4125 |
+
$this->fault( 'SOAP-ENV:Client', 'This Server does not support compressed data' );
|
4126 |
+
|
4127 |
+
return;
|
4128 |
+
}
|
4129 |
+
}
|
4130 |
+
}
|
4131 |
+
$this->request .= "\r\n" . $data;
|
4132 |
+
$data = $this->parseRequest( $this->headers, $data );
|
4133 |
+
$this->requestSOAP = $data;
|
4134 |
+
$this->debug( 'leaving parse_request' );
|
4135 |
+
}
|
4136 |
+
|
4137 |
+
/**
|
4138 |
+
* invokes a PHP function for the requested SOAP method
|
4139 |
+
*
|
4140 |
+
* The following fields are set by this function (when successful)
|
4141 |
+
*
|
4142 |
+
* methodreturn
|
4143 |
+
*
|
4144 |
+
* Note that the PHP function that is called may also set the following
|
4145 |
+
* fields to affect the response sent to the client
|
4146 |
+
*
|
4147 |
+
* responseHeaders
|
4148 |
+
* outgoing_headers
|
4149 |
+
*
|
4150 |
+
* This sets the fault field on error
|
4151 |
+
*
|
4152 |
+
* @access private
|
4153 |
+
*/
|
4154 |
+
function invoke_method() {
|
4155 |
+
$this->debug( 'in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction );
|
4156 |
+
|
4157 |
+
//
|
4158 |
+
// if you are debugging in this area of the code, your service uses a class to implement methods,
|
4159 |
+
// you use SOAP RPC, and the client is .NET, please be aware of the following...
|
4160 |
+
// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
|
4161 |
+
// method name. that is fine for naming the .NET methods. it is not fine for properly constructing
|
4162 |
+
// the XML request and reading the XML response. you need to add the RequestElementName and
|
4163 |
+
// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
|
4164 |
+
// generates for the method. these parameters are used to specify the correct XML element names
|
4165 |
+
// for .NET to use, i.e. the names with the '.' in them.
|
4166 |
+
//
|
4167 |
+
$orig_methodname = $this->methodname;
|
4168 |
+
if ( $this->wsdl ) {
|
4169 |
+
if ( $this->opData = $this->wsdl->getOperationData( $this->methodname ) ) {
|
4170 |
+
$this->debug( 'in invoke_method, found WSDL operation=' . $this->methodname );
|
4171 |
+
$this->appendDebug( 'opData=' . $this->varDump( $this->opData ) );
|
4172 |
+
} elseif ( $this->opData = $this->wsdl->getOperationDataForSoapAction( $this->SOAPAction ) ) {
|
4173 |
+
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
|
4174 |
+
$this->debug( 'in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name'] );
|
4175 |
+
$this->appendDebug( 'opData=' . $this->varDump( $this->opData ) );
|
4176 |
+
$this->methodname = $this->opData['name'];
|
4177 |
+
} else {
|
4178 |
+
$this->debug( 'in invoke_method, no WSDL for operation=' . $this->methodname );
|
4179 |
+
$this->fault( 'SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service" );
|
4180 |
+
|
4181 |
+
return;
|
4182 |
+
}
|
4183 |
+
} else {
|
4184 |
+
$this->debug( 'in invoke_method, no WSDL to validate method' );
|
4185 |
+
}
|
4186 |
+
|
4187 |
+
// if a . is present in $this->methodname, we see if there is a class in scope,
|
4188 |
+
// which could be referred to. We will also distinguish between two deliminators,
|
4189 |
+
// to allow methods to be called a the class or an instance
|
4190 |
+
if ( strpos( $this->methodname, '..' ) > 0 ) {
|
4191 |
+
$delim = '..';
|
4192 |
+
} else if ( strpos( $this->methodname, '.' ) > 0 ) {
|
4193 |
+
$delim = '.';
|
4194 |
+
} else {
|
4195 |
+
$delim = '';
|
4196 |
+
}
|
4197 |
+
$this->debug( "in invoke_method, delim=$delim" );
|
4198 |
+
|
4199 |
+
$class = '';
|
4200 |
+
$method = '';
|
4201 |
+
if ( strlen( $delim ) > 0 && substr_count( $this->methodname, $delim ) == 1 ) {
|
4202 |
+
$try_class = substr( $this->methodname, 0, strpos( $this->methodname, $delim ) );
|
4203 |
+
if ( class_exists( $try_class ) ) {
|
4204 |
+
// get the class and method name
|
4205 |
+
$class = $try_class;
|
4206 |
+
$method = substr( $this->methodname, strpos( $this->methodname, $delim ) + strlen( $delim ) );
|
4207 |
+
$this->debug( "in invoke_method, class=$class method=$method delim=$delim" );
|
4208 |
+
} else {
|
4209 |
+
$this->debug( "in invoke_method, class=$try_class not found" );
|
4210 |
+
}
|
4211 |
+
} else {
|
4212 |
+
$try_class = '';
|
4213 |
+
$this->debug( "in invoke_method, no class to try" );
|
4214 |
+
}
|
4215 |
+
|
4216 |
+
// does method exist?
|
4217 |
+
if ( $class == '' ) {
|
4218 |
+
if ( ! function_exists( $this->methodname ) ) {
|
4219 |
+
$this->debug( "in invoke_method, function '$this->methodname' not found!" );
|
4220 |
+
$this->result = 'fault: method not found';
|
4221 |
+
$this->fault( 'SOAP-ENV:Client', "method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')" );
|
4222 |
+
|
4223 |
+
return;
|
4224 |
+
}
|
4225 |
+
} else {
|
4226 |
+
$method_to_compare = ( substr( phpversion(), 0, 2 ) == '4.' ) ? strtolower( $method ) : $method;
|
4227 |
+
if ( ! in_array( $method_to_compare, get_class_methods( $class ) ) ) {
|
4228 |
+
$this->debug( "in invoke_method, method '$this->methodname' not found in class '$class'!" );
|
4229 |
+
$this->result = 'fault: method not found';
|
4230 |
+
$this->fault( 'SOAP-ENV:Client', "method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')" );
|
4231 |
+
|
4232 |
+
return;
|
4233 |
+
}
|
4234 |
+
}
|
4235 |
+
|
4236 |
+
// evaluate message, getting back parameters
|
4237 |
+
// verify that request parameters match the method's signature
|
4238 |
+
if ( ! $this->verify_method( $this->methodname, $this->methodparams ) ) {
|
4239 |
+
// debug
|
4240 |
+
$this->debug( 'ERROR: request not verified against method signature' );
|
4241 |
+
$this->result = 'fault: request failed validation against method signature';
|
4242 |
+
// return fault
|
4243 |
+
$this->fault( 'SOAP-ENV:Client', "Operation '$this->methodname' not defined in service." );
|
4244 |
+
|
4245 |
+
return;
|
4246 |
+
}
|
4247 |
+
|
4248 |
+
// if there are parameters to pass
|
4249 |
+
$this->debug( 'in invoke_method, params:' );
|
4250 |
+
$this->appendDebug( $this->varDump( $this->methodparams ) );
|
4251 |
+
$this->debug( "in invoke_method, calling '$this->methodname'" );
|
4252 |
+
if ( ! function_exists( 'call_user_func_array' ) ) {
|
4253 |
+
if ( $class == '' ) {
|
4254 |
+
$this->debug( 'in invoke_method, calling function using eval()' );
|
4255 |
+
$funcCall = "\$this->methodreturn = $this->methodname(";
|
4256 |
+
} else {
|
4257 |
+
if ( $delim == '..' ) {
|
4258 |
+
$this->debug( 'in invoke_method, calling class method using eval()' );
|
4259 |
+
$funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
|
4260 |
+
} else {
|
4261 |
+
$this->debug( 'in invoke_method, calling instance method using eval()' );
|
4262 |
+
// generate unique instance name
|
4263 |
+
$instname = "\$inst_" . time();
|
4264 |
+
$funcCall = $instname . " = new " . $class . "(); ";
|
4265 |
+
$funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
|
4266 |
+
}
|
4267 |
+
}
|
4268 |
+
if ( $this->methodparams ) {
|
4269 |
+
foreach ( $this->methodparams as $param ) {
|
4270 |
+
if ( is_array( $param ) || is_object( $param ) ) {
|
4271 |
+
$this->fault( 'SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available' );
|
4272 |
+
|
4273 |
+
return;
|
4274 |
+
}
|
4275 |
+
$funcCall .= "\"$param\",";
|
4276 |
+
}
|
4277 |
+
$funcCall = substr( $funcCall, 0, - 1 );
|
4278 |
+
}
|
4279 |
+
$funcCall .= ');';
|
4280 |
+
$this->debug( 'in invoke_method, function call: ' . $funcCall );
|
4281 |
+
@eval( $funcCall );
|
4282 |
+
} else {
|
4283 |
+
if ( $class == '' ) {
|
4284 |
+
$this->debug( 'in invoke_method, calling function using call_user_func_array()' );
|
4285 |
+
$call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
|
4286 |
+
} elseif ( $delim == '..' ) {
|
4287 |
+
$this->debug( 'in invoke_method, calling class method using call_user_func_array()' );
|
4288 |
+
$call_arg = array( $class, $method );
|
4289 |
+
} else {
|
4290 |
+
$this->debug( 'in invoke_method, calling instance method using call_user_func_array()' );
|
4291 |
+
$instance = new $class ();
|
4292 |
+
$call_arg = array( &$instance, $method );
|
4293 |
+
}
|
4294 |
+
if ( is_array( $this->methodparams ) ) {
|
4295 |
+
$this->methodreturn = call_user_func_array( $call_arg, array_values( $this->methodparams ) );
|
4296 |
+
} else {
|
4297 |
+
$this->methodreturn = call_user_func_array( $call_arg, array() );
|
4298 |
+
}
|
4299 |
+
}
|
4300 |
+
$this->debug( 'in invoke_method, methodreturn:' );
|
4301 |
+
$this->appendDebug( $this->varDump( $this->methodreturn ) );
|
4302 |
+
$this->debug( "in invoke_method, called method $this->methodname, received data of type " . gettype( $this->methodreturn ) );
|
4303 |
+
}
|
4304 |
+
|
4305 |
+
/**
|
4306 |
+
* serializes the return value from a PHP function into a full SOAP Envelope
|
4307 |
+
*
|
4308 |
+
* The following fields are set by this function (when successful)
|
4309 |
+
*
|
4310 |
+
* responseSOAP
|
4311 |
+
*
|
4312 |
+
* This sets the fault field on error
|
4313 |
+
*
|
4314 |
+
* @access private
|
4315 |
+
*/
|
4316 |
+
function serialize_return() {
|
4317 |
+
$this->debug( 'Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI );
|
4318 |
+
// if fault
|
4319 |
+
if ( isset( $this->methodreturn ) && is_object( $this->methodreturn ) && ( ( get_class( $this->methodreturn ) == 'soap_fault' ) || ( get_class( $this->methodreturn ) == 'nusoap_fault' ) ) ) {
|
4320 |
+
$this->debug( 'got a fault object from method' );
|
4321 |
+
$this->fault = $this->methodreturn;
|
4322 |
+
|
4323 |
+
return;
|
4324 |
+
} elseif ( $this->methodreturnisliteralxml ) {
|
4325 |
+
$return_val = $this->methodreturn;
|
4326 |
+
// returned value(s)
|
4327 |
+
} else {
|
4328 |
+
$this->debug( 'got a(n) ' . gettype( $this->methodreturn ) . ' from method' );
|
4329 |
+
$this->debug( 'serializing return value' );
|
4330 |
+
if ( $this->wsdl ) {
|
4331 |
+
if ( sizeof( $this->opData['output']['parts'] ) > 1 ) {
|
4332 |
+
$this->debug( 'more than one output part, so use the method return unchanged' );
|
4333 |
+
$opParams = $this->methodreturn;
|
4334 |
+
} elseif ( sizeof( $this->opData['output']['parts'] ) == 1 ) {
|
4335 |
+
$this->debug( 'exactly one output part, so wrap the method return in a simple array' );
|
4336 |
+
// TODO: verify that it is not already wrapped!
|
4337 |
+
//foreach ($this->opData['output']['parts'] as $name => $type) {
|
4338 |
+
// $this->debug('wrap in element named ' . $name);
|
4339 |
+
//}
|
4340 |
+
$opParams = array( $this->methodreturn );
|
4341 |
+
}
|
4342 |
+
$return_val = $this->wsdl->serializeRPCParameters( $this->methodname, 'output', $opParams );
|
4343 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
4344 |
+
$this->wsdl->clearDebug();
|
4345 |
+
if ( $errstr = $this->wsdl->getError() ) {
|
4346 |
+
$this->debug( 'got wsdl error: ' . $errstr );
|
4347 |
+
$this->fault( 'SOAP-ENV:Server', 'unable to serialize result' );
|
4348 |
+
|
4349 |
+
return;
|
4350 |
+
}
|
4351 |
+
} else {
|
4352 |
+
if ( isset( $this->methodreturn ) ) {
|
4353 |
+
$return_val = $this->serialize_val( $this->methodreturn, 'return' );
|
4354 |
+
} else {
|
4355 |
+
$return_val = '';
|
4356 |
+
$this->debug( 'in absence of WSDL, assume void return for backward compatibility' );
|
4357 |
+
}
|
4358 |
+
}
|
4359 |
+
}
|
4360 |
+
$this->debug( 'return value:' );
|
4361 |
+
$this->appendDebug( $this->varDump( $return_val ) );
|
4362 |
+
|
4363 |
+
$this->debug( 'serializing response' );
|
4364 |
+
if ( $this->wsdl ) {
|
4365 |
+
$this->debug( 'have WSDL for serialization: style is ' . $this->opData['style'] );
|
4366 |
+
if ( $this->opData['style'] == 'rpc' ) {
|
4367 |
+
$this->debug( 'style is rpc for serialization: use is ' . $this->opData['output']['use'] );
|
4368 |
+
if ( $this->opData['output']['use'] == 'literal' ) {
|
4369 |
+
// 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
|
4370 |
+
if ( $this->methodURI ) {
|
4371 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4372 |
+
} else {
|
4373 |
+
$payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
|
4374 |
+
}
|
4375 |
+
} else {
|
4376 |
+
if ( $this->methodURI ) {
|
4377 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4378 |
+
} else {
|
4379 |
+
$payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
|
4380 |
+
}
|
4381 |
+
}
|
4382 |
+
} else {
|
4383 |
+
$this->debug( 'style is not rpc for serialization: assume document' );
|
4384 |
+
$payload = $return_val;
|
4385 |
+
}
|
4386 |
+
} else {
|
4387 |
+
$this->debug( 'do not have WSDL for serialization: assume rpc/encoded' );
|
4388 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4389 |
+
}
|
4390 |
+
$this->result = 'successful';
|
4391 |
+
if ( $this->wsdl ) {
|
4392 |
+
//if($this->debug_flag){
|
4393 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
4394 |
+
// }
|
4395 |
+
if ( isset( $this->opData['output']['encodingStyle'] ) ) {
|
4396 |
+
$encodingStyle = $this->opData['output']['encodingStyle'];
|
4397 |
+
} else {
|
4398 |
+
$encodingStyle = '';
|
4399 |
+
}
|
4400 |
+
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
|
4401 |
+
$this->responseSOAP = $this->serializeEnvelope( $payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle );
|
4402 |
+
} else {
|
4403 |
+
$this->responseSOAP = $this->serializeEnvelope( $payload, $this->responseHeaders );
|
4404 |
+
}
|
4405 |
+
$this->debug( "Leaving serialize_return" );
|
4406 |
+
}
|
4407 |
+
|
4408 |
+
/**
|
4409 |
+
* sends an HTTP response
|
4410 |
+
*
|
4411 |
+
* The following fields are set by this function (when successful)
|
4412 |
+
*
|
4413 |
+
* outgoing_headers
|
4414 |
+
* response
|
4415 |
+
*
|
4416 |
+
* @access private
|
4417 |
+
*/
|
4418 |
+
function send_response() {
|
4419 |
+
$this->debug( 'Enter send_response' );
|
4420 |
+
if ( $this->fault ) {
|
4421 |
+
$payload = $this->fault->serialize();
|
4422 |
+
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
|
4423 |
+
$this->outgoing_headers[] = "Status: 500 Internal Server Error";
|
4424 |
+
} else {
|
4425 |
+
$payload = $this->responseSOAP;
|
4426 |
+
// Some combinations of PHP+Web server allow the Status
|
4427 |
+
// to come through as a header. Since OK is the default
|
4428 |
+
// just do nothing.
|
4429 |
+
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
|
4430 |
+
// $this->outgoing_headers[] = "Status: 200 OK";
|
4431 |
+
}
|
4432 |
+
// add debug data if in debug mode
|
4433 |
+
if ( isset( $this->debug_flag ) && $this->debug_flag ) {
|
4434 |
+
$payload .= $this->getDebugAsXMLComment();
|
4435 |
+
}
|
4436 |
+
$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
|
4437 |
+
preg_match( '/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev );
|
4438 |
+
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
|
4439 |
+
// Let the Web server decide about this
|
4440 |
+
//$this->outgoing_headers[] = "Connection: Close\r\n";
|
4441 |
+
$payload = $this->getHTTPBody( $payload );
|
4442 |
+
$type = $this->getHTTPContentType();
|
4443 |
+
$charset = $this->getHTTPContentTypeCharset();
|
4444 |
+
$this->outgoing_headers[] = "Content-Type: $type" . ( $charset ? '; charset=' . $charset : '' );
|
4445 |
+
//begin code to compress payload - by John
|
4446 |
+
// NOTE: there is no way to know whether the Web server will also compress
|
4447 |
+
// this data.
|
4448 |
+
if ( strlen( $payload ) > 1024 && isset( $this->headers ) && isset( $this->headers['accept-encoding'] ) ) {
|
4449 |
+
if ( strstr( $this->headers['accept-encoding'], 'gzip' ) ) {
|
4450 |
+
if ( function_exists( 'gzencode' ) ) {
|
4451 |
+
if ( isset( $this->debug_flag ) && $this->debug_flag ) {
|
4452 |
+
$payload .= "<!-- Content being gzipped -->";
|
4453 |
+
}
|
4454 |
+
$this->outgoing_headers[] = "Content-Encoding: gzip";
|
4455 |
+
$payload = gzencode( $payload );
|
4456 |
+
} else {
|
4457 |
+
if ( isset( $this->debug_flag ) && $this->debug_flag ) {
|
4458 |
+
$payload .= "<!-- Content will not be gzipped: no gzencode -->";
|
4459 |
+
}
|
4460 |
+
}
|
4461 |
+
} elseif ( strstr( $this->headers['accept-encoding'], 'deflate' ) ) {
|
4462 |
+
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
|
4463 |
+
// instead of gzcompress output,
|
4464 |
+
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
|
4465 |
+
if ( function_exists( 'gzdeflate' ) ) {
|
4466 |
+
if ( isset( $this->debug_flag ) && $this->debug_flag ) {
|
4467 |
+
$payload .= "<!-- Content being deflated -->";
|
4468 |
+
}
|
4469 |
+
$this->outgoing_headers[] = "Content-Encoding: deflate";
|
4470 |
+
$payload = gzdeflate( $payload );
|
4471 |
+
} else {
|
4472 |
+
if ( isset( $this->debug_flag ) && $this->debug_flag ) {
|
4473 |
+
$payload .= "<!-- Content will not be deflated: no gzcompress -->";
|
4474 |
+
}
|
4475 |
+
}
|
4476 |
+
}
|
4477 |
+
}
|
4478 |
+
//end code
|
4479 |
+
$this->outgoing_headers[] = "Content-Length: " . strlen( $payload );
|
4480 |
+
reset( $this->outgoing_headers );
|
4481 |
+
foreach ( $this->outgoing_headers as $hdr ) {
|
4482 |
+
header( $hdr, false );
|
4483 |
+
}
|
4484 |
+
print $payload;
|
4485 |
+
$this->response = join( "\r\n", $this->outgoing_headers ) . "\r\n\r\n" . $payload;
|
4486 |
+
}
|
4487 |
+
|
4488 |
+
/**
|
4489 |
+
* takes the value that was created by parsing the request
|
4490 |
+
* and compares to the method's signature, if available.
|
4491 |
+
*
|
4492 |
+
* @param string $operation The operation to be invoked
|
4493 |
+
* @param array $request The array of parameter values
|
4494 |
+
*
|
4495 |
+
* @return boolean Whether the operation was found
|
4496 |
+
* @access private
|
4497 |
+
*/
|
4498 |
+
function verify_method( $operation, $request ) {
|
4499 |
+
if ( isset( $this->wsdl ) && is_object( $this->wsdl ) ) {
|
4500 |
+
if ( $this->wsdl->getOperationData( $operation ) ) {
|
4501 |
+
return true;
|
4502 |
+
}
|
4503 |
+
} elseif ( isset( $this->operations[ $operation ] ) ) {
|
4504 |
+
return true;
|
4505 |
+
}
|
4506 |
+
|
4507 |
+
return false;
|
4508 |
+
}
|
4509 |
+
|
4510 |
+
/**
|
4511 |
+
* processes SOAP message received from client
|
4512 |
+
*
|
4513 |
+
* @param array $headers The HTTP headers
|
4514 |
+
* @param string $data unprocessed request data from client
|
4515 |
+
*
|
4516 |
+
* @return mixed value of the message, decoded into a PHP type
|
4517 |
+
* @access private
|
4518 |
+
*/
|
4519 |
+
function parseRequest( $headers, $data ) {
|
4520 |
+
$this->debug( 'Entering parseRequest() for data of length ' . strlen( $data ) . ' headers:' );
|
4521 |
+
$this->appendDebug( $this->varDump( $headers ) );
|
4522 |
+
if ( ! isset( $headers['content-type'] ) ) {
|
4523 |
+
$this->setError( 'Request not of type text/xml (no content-type header)' );
|
4524 |
+
|
4525 |
+
return false;
|
4526 |
+
}
|
4527 |
+
if ( ! strstr( $headers['content-type'], 'text/xml' ) ) {
|
4528 |
+
$this->setError( 'Request not of type text/xml' );
|
4529 |
+
|
4530 |
+
return false;
|
4531 |
+
}
|
4532 |
+
if ( strpos( $headers['content-type'], '=' ) ) {
|
4533 |
+
$enc = str_replace( '"', '', substr( strstr( $headers["content-type"], '=' ), 1 ) );
|
4534 |
+
$this->debug( 'Got response encoding: ' . $enc );
|
4535 |
+
if ( preg_match( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc ) ) {
|
4536 |
+
$this->xml_encoding = strtoupper( $enc );
|
4537 |
+
} else {
|
4538 |
+
$this->xml_encoding = 'US-ASCII';
|
4539 |
+
}
|
4540 |
+
} else {
|
4541 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4542 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4543 |
+
}
|
4544 |
+
$this->debug( 'Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser' );
|
4545 |
+
// parse response, get soap parser obj
|
4546 |
+
$parser = new nusoap_parser( $data, $this->xml_encoding, '', $this->decode_utf8 );
|
4547 |
+
// parser debug
|
4548 |
+
$this->debug( "parser debug: \n" . $parser->getDebug() );
|
4549 |
+
// if fault occurred during message parsing
|
4550 |
+
if ( $err = $parser->getError() ) {
|
4551 |
+
$this->result = 'fault: error in msg parsing: ' . $err;
|
4552 |
+
$this->fault( 'SOAP-ENV:Client', "error in msg parsing:\n" . $err );
|
4553 |
+
// else successfully parsed request into soapval object
|
4554 |
+
} else {
|
4555 |
+
// get/set methodname
|
4556 |
+
$this->methodURI = $parser->root_struct_namespace;
|
4557 |
+
$this->methodname = $parser->root_struct_name;
|
4558 |
+
$this->debug( 'methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI );
|
4559 |
+
$this->debug( 'calling parser->get_soapbody()' );
|
4560 |
+
$this->methodparams = $parser->get_soapbody();
|
4561 |
+
// get SOAP headers
|
4562 |
+
$this->requestHeaders = $parser->getHeaders();
|
4563 |
+
// get SOAP Header
|
4564 |
+
$this->requestHeader = $parser->get_soapheader();
|
4565 |
+
// add document for doclit support
|
4566 |
+
$this->document = $parser->document;
|
4567 |
+
}
|
4568 |
+
}
|
4569 |
+
|
4570 |
+
/**
|
4571 |
+
* gets the HTTP body for the current response.
|
4572 |
+
*
|
4573 |
+
* @param string $soapmsg The SOAP payload
|
4574 |
+
*
|
4575 |
+
* @return string The HTTP body, which includes the SOAP payload
|
4576 |
+
* @access private
|
4577 |
+
*/
|
4578 |
+
function getHTTPBody( $soapmsg ) {
|
4579 |
+
return $soapmsg;
|
4580 |
+
}
|
4581 |
+
|
4582 |
+
/**
|
4583 |
+
* gets the HTTP content type for the current response.
|
4584 |
+
*
|
4585 |
+
* Note: getHTTPBody must be called before this.
|
4586 |
+
*
|
4587 |
+
* @return string the HTTP content type for the current response.
|
4588 |
+
* @access private
|
4589 |
+
*/
|
4590 |
+
function getHTTPContentType() {
|
4591 |
+
return 'text/xml';
|
4592 |
+
}
|
4593 |
+
|
4594 |
+
/**
|
4595 |
+
* gets the HTTP content type charset for the current response.
|
4596 |
+
* returns false for non-text content types.
|
4597 |
+
*
|
4598 |
+
* Note: getHTTPBody must be called before this.
|
4599 |
+
*
|
4600 |
+
* @return string the HTTP content type charset for the current response.
|
4601 |
+
* @access private
|
4602 |
+
*/
|
4603 |
+
function getHTTPContentTypeCharset() {
|
4604 |
+
return $this->soap_defencoding;
|
4605 |
+
}
|
4606 |
+
|
4607 |
+
/**
|
4608 |
+
* add a method to the dispatch map (this has been replaced by the register method)
|
4609 |
+
*
|
4610 |
+
* @param string $methodname
|
4611 |
+
* @param string $in array of input values
|
4612 |
+
* @param string $out array of output values
|
4613 |
+
*
|
4614 |
+
* @access public
|
4615 |
+
* @deprecated
|
4616 |
+
*/
|
4617 |
+
function add_to_map( $methodname, $in, $out ) {
|
4618 |
+
$this->operations[ $methodname ] = array( 'name' => $methodname, 'in' => $in, 'out' => $out );
|
4619 |
+
}
|
4620 |
+
|
4621 |
+
/**
|
4622 |
+
* register a service function with the server
|
4623 |
+
*
|
4624 |
+
* @param string $name the name of the PHP function, class.method or class..method
|
4625 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
4626 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
4627 |
+
* @param mixed $namespace the element namespace for the method or false
|
4628 |
+
* @param mixed $soapaction the soapaction for the method or false
|
4629 |
+
* @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
|
4630 |
+
* @param mixed $use optional (encoded|literal) or false
|
4631 |
+
* @param string $documentation optional Description to include in WSDL
|
4632 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
4633 |
+
*
|
4634 |
+
* @access public
|
4635 |
+
*/
|
4636 |
+
function register( $name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '' ) {
|
4637 |
+
global $HTTP_SERVER_VARS;
|
4638 |
+
|
4639 |
+
if ( $this->externalWSDLURL ) {
|
4640 |
+
die( 'You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.' );
|
4641 |
+
}
|
4642 |
+
if ( ! $name ) {
|
4643 |
+
die( 'You must specify a name when you register an operation' );
|
4644 |
+
}
|
4645 |
+
if ( ! is_array( $in ) ) {
|
4646 |
+
die( 'You must provide an array for operation inputs' );
|
4647 |
+
}
|
4648 |
+
if ( ! is_array( $out ) ) {
|
4649 |
+
die( 'You must provide an array for operation outputs' );
|
4650 |
+
}
|
4651 |
+
if ( false == $namespace ) {
|
4652 |
+
}
|
4653 |
+
if ( false == $soapaction ) {
|
4654 |
+
if ( isset( $_SERVER ) ) {
|
4655 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4656 |
+
$SCRIPT_NAME = isset( $_SERVER['PHP_SELF'] ) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4657 |
+
$HTTPS = isset( $_SERVER['HTTPS'] ) ? $_SERVER['HTTPS'] : ( isset( $HTTP_SERVER_VARS['HTTPS'] ) ? $HTTP_SERVER_VARS['HTTPS'] : 'off' );
|
4658 |
+
} elseif ( isset( $HTTP_SERVER_VARS ) ) {
|
4659 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4660 |
+
$SCRIPT_NAME = isset( $HTTP_SERVER_VARS['PHP_SELF'] ) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4661 |
+
$HTTPS = isset( $HTTP_SERVER_VARS['HTTPS'] ) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4662 |
+
} else {
|
4663 |
+
$this->setError( "Neither _SERVER nor HTTP_SERVER_VARS is available" );
|
4664 |
+
}
|
4665 |
+
if ( $HTTPS == '1' || $HTTPS == 'on' ) {
|
4666 |
+
$SCHEME = 'https';
|
4667 |
+
} else {
|
4668 |
+
$SCHEME = 'http';
|
4669 |
+
}
|
4670 |
+
$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
|
4671 |
+
}
|
4672 |
+
if ( false == $style ) {
|
4673 |
+
$style = "rpc";
|
4674 |
+
}
|
4675 |
+
if ( false == $use ) {
|
4676 |
+
$use = "encoded";
|
4677 |
+
}
|
4678 |
+
if ( $use == 'encoded' && $encodingStyle == '' ) {
|
4679 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
4680 |
+
}
|
4681 |
+
|
4682 |
+
$this->operations[ $name ] = array(
|
4683 |
+
'name' => $name,
|
4684 |
+
'in' => $in,
|
4685 |
+
'out' => $out,
|
4686 |
+
'namespace' => $namespace,
|
4687 |
+
'soapaction' => $soapaction,
|
4688 |
+
'style' => $style
|
4689 |
+
);
|
4690 |
+
if ( $this->wsdl ) {
|
4691 |
+
$this->wsdl->addOperation( $name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle );
|
4692 |
+
}
|
4693 |
+
|
4694 |
+
return true;
|
4695 |
+
}
|
4696 |
+
|
4697 |
+
/**
|
4698 |
+
* Specify a fault to be returned to the client.
|
4699 |
+
* This also acts as a flag to the server that a fault has occured.
|
4700 |
+
*
|
4701 |
+
* @param string $faultcode
|
4702 |
+
* @param string $faultstring
|
4703 |
+
* @param string $faultactor
|
4704 |
+
* @param string $faultdetail
|
4705 |
+
*
|
4706 |
+
* @access public
|
4707 |
+
*/
|
4708 |
+
function fault( $faultcode, $faultstring, $faultactor = '', $faultdetail = '' ) {
|
4709 |
+
if ( $faultdetail == '' && $this->debug_flag ) {
|
4710 |
+
$faultdetail = $this->getDebug();
|
4711 |
+
}
|
4712 |
+
$this->fault = new nusoap_fault( $faultcode, $faultactor, $faultstring, $faultdetail );
|
4713 |
+
$this->fault->soap_defencoding = $this->soap_defencoding;
|
4714 |
+
}
|
4715 |
+
|
4716 |
+
/**
|
4717 |
+
* Sets up wsdl object.
|
4718 |
+
* Acts as a flag to enable internal WSDL generation
|
4719 |
+
*
|
4720 |
+
* @param string $serviceName , name of the service
|
4721 |
+
* @param mixed $namespace optional 'tns' service namespace or false
|
4722 |
+
* @param mixed $endpoint optional URL of service endpoint or false
|
4723 |
+
* @param string $style optional (rpc|document) WSDL style (also specified by operation)
|
4724 |
+
* @param string $transport optional SOAP transport
|
4725 |
+
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
|
4726 |
+
*/
|
4727 |
+
function configureWSDL( $serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false ) {
|
4728 |
+
global $HTTP_SERVER_VARS;
|
4729 |
+
|
4730 |
+
if ( isset( $_SERVER ) ) {
|
4731 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4732 |
+
$SERVER_PORT = $_SERVER['SERVER_PORT'];
|
4733 |
+
$SCRIPT_NAME = isset( $_SERVER['PHP_SELF'] ) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4734 |
+
$HTTPS = isset( $_SERVER['HTTPS'] ) ? $_SERVER['HTTPS'] : ( isset( $HTTP_SERVER_VARS['HTTPS'] ) ? $HTTP_SERVER_VARS['HTTPS'] : 'off' );
|
4735 |
+
} elseif ( isset( $HTTP_SERVER_VARS ) ) {
|
4736 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4737 |
+
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
|
4738 |
+
$SCRIPT_NAME = isset( $HTTP_SERVER_VARS['PHP_SELF'] ) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4739 |
+
$HTTPS = isset( $HTTP_SERVER_VARS['HTTPS'] ) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4740 |
+
} else {
|
4741 |
+
$this->setError( "Neither _SERVER nor HTTP_SERVER_VARS is available" );
|
4742 |
+
}
|
4743 |
+
// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
|
4744 |
+
$colon = strpos( $SERVER_NAME, ":" );
|
4745 |
+
if ( $colon ) {
|
4746 |
+
$SERVER_NAME = substr( $SERVER_NAME, 0, $colon );
|
4747 |
+
}
|
4748 |
+
if ( $SERVER_PORT == 80 ) {
|
4749 |
+
$SERVER_PORT = '';
|
4750 |
+
} else {
|
4751 |
+
$SERVER_PORT = ':' . $SERVER_PORT;
|
4752 |
+
}
|
4753 |
+
if ( false == $namespace ) {
|
4754 |
+
$namespace = "http://$SERVER_NAME/soap/$serviceName";
|
4755 |
+
}
|
4756 |
+
|
4757 |
+
if ( false == $endpoint ) {
|
4758 |
+
if ( $HTTPS == '1' || $HTTPS == 'on' ) {
|
4759 |
+
$SCHEME = 'https';
|
4760 |
+
} else {
|
4761 |
+
$SCHEME = 'http';
|
4762 |
+
}
|
4763 |
+
$endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
|
4764 |
+
}
|
4765 |
+
|
4766 |
+
if ( false == $schemaTargetNamespace ) {
|
4767 |
+
$schemaTargetNamespace = $namespace;
|
4768 |
+
}
|
4769 |
+
|
4770 |
+
$this->wsdl = new wsdl;
|
4771 |
+
$this->wsdl->serviceName = $serviceName;
|
4772 |
+
$this->wsdl->endpoint = $endpoint;
|
4773 |
+
$this->wsdl->namespaces['tns'] = $namespace;
|
4774 |
+
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
4775 |
+
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
|
4776 |
+
if ( $schemaTargetNamespace != $namespace ) {
|
4777 |
+
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
|
4778 |
+
}
|
4779 |
+
$this->wsdl->schemas[ $schemaTargetNamespace ][0] = new nusoap_xmlschema( '', '', $this->wsdl->namespaces );
|
4780 |
+
if ( $style == 'document' ) {
|
4781 |
+
$this->wsdl->schemas[ $schemaTargetNamespace ][0]->schemaInfo['elementFormDefault'] = 'qualified';
|
4782 |
+
}
|
4783 |
+
$this->wsdl->schemas[ $schemaTargetNamespace ][0]->schemaTargetNamespace = $schemaTargetNamespace;
|
4784 |
+
$this->wsdl->schemas[ $schemaTargetNamespace ][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array(
|
4785 |
+
'location' => '',
|
4786 |
+
'loaded' => true
|
4787 |
+
);
|
4788 |
+
$this->wsdl->schemas[ $schemaTargetNamespace ][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array(
|
4789 |
+
'location' => '',
|
4790 |
+
'loaded' => true
|
4791 |
+
);
|
4792 |
+
$this->wsdl->bindings[ $serviceName . 'Binding' ] = array(
|
4793 |
+
'name' => $serviceName . 'Binding',
|
4794 |
+
'style' => $style,
|
4795 |
+
'transport' => $transport,
|
4796 |
+
'portType' => $serviceName . 'PortType'
|
4797 |
+
);
|
4798 |
+
$this->wsdl->ports[ $serviceName . 'Port' ] = array(
|
4799 |
+
'binding' => $serviceName . 'Binding',
|
4800 |
+
'location' => $endpoint,
|
4801 |
+
'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/'
|
4802 |
+
);
|
4803 |
+
}
|
4804 |
+
}
|
4805 |
+
|
4806 |
+
/**
|
4807 |
+
* Backward compatibility
|
4808 |
+
*/
|
4809 |
+
class soap_server extends nusoap_server {
|
4810 |
+
}
|
4811 |
+
|
4812 |
+
?><?php
|
4813 |
+
|
4814 |
+
|
4815 |
+
/**
|
4816 |
+
* parses a WSDL file, allows access to it's data, other utility methods.
|
4817 |
+
* also builds WSDL structures programmatically.
|
4818 |
+
*
|
4819 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
4820 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
4821 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
4822 |
+
* @access public
|
4823 |
+
*/
|
4824 |
+
class wsdl extends nusoap_base {
|
4825 |
+
// URL or filename of the root of this WSDL
|
4826 |
+
var $wsdl;
|
4827 |
+
// define internal arrays of bindings, ports, operations, messages, etc.
|
4828 |
+
var $schemas = array();
|
4829 |
+
var $currentSchema;
|
4830 |
+
var $message = array();
|
4831 |
+
var $complexTypes = array();
|
4832 |
+
var $messages = array();
|
4833 |
+
var $currentMessage;
|
4834 |
+
var $currentOperation;
|
4835 |
+
var $portTypes = array();
|
4836 |
+
var $currentPortType;
|
4837 |
+
var $bindings = array();
|
4838 |
+
var $currentBinding;
|
4839 |
+
var $ports = array();
|
4840 |
+
var $currentPort;
|
4841 |
+
var $opData = array();
|
4842 |
+
var $status = '';
|
4843 |
+
var $documentation = false;
|
4844 |
+
var $endpoint = '';
|
4845 |
+
// array of wsdl docs to import
|
4846 |
+
var $import = array();
|
4847 |
+
// parser vars
|
4848 |
+
var $parser;
|
4849 |
+
var $position = 0;
|
4850 |
+
var $depth = 0;
|
4851 |
+
var $depth_array = array();
|
4852 |
+
// for getting wsdl
|
4853 |
+
var $proxyhost = '';
|
4854 |
+
var $proxyport = '';
|
4855 |
+
var $proxyusername = '';
|
4856 |
+
var $proxypassword = '';
|
4857 |
+
var $timeout = 0;
|
4858 |
+
var $response_timeout = 30;
|
4859 |
+
var $curl_options = array(); // User-specified cURL options
|
4860 |
+
var $use_curl = false; // whether to always try to use cURL
|
4861 |
+
// for HTTP authentication
|
4862 |
+
var $username = ''; // Username for HTTP authentication
|
4863 |
+
var $password = ''; // Password for HTTP authentication
|
4864 |
+
var $authtype = ''; // Type of HTTP authentication
|
4865 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
4866 |
+
|
4867 |
+
/**
|
4868 |
+
* constructor
|
4869 |
+
*
|
4870 |
+
* @param string $wsdl WSDL document URL
|
4871 |
+
* @param string $proxyhost
|
4872 |
+
* @param string $proxyport
|
4873 |
+
* @param string $proxyusername
|
4874 |
+
* @param string $proxypassword
|
4875 |
+
* @param integer $timeout set the connection timeout
|
4876 |
+
* @param integer $response_timeout set the response timeout
|
4877 |
+
* @param array $curl_options user-specified cURL options
|
4878 |
+
* @param boolean $use_curl try to use cURL
|
4879 |
+
*
|
4880 |
+
* @access public
|
4881 |
+
*/
|
4882 |
+
function wsdl( $wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false ) {
|
4883 |
+
parent::nusoap_base();
|
4884 |
+
$this->debug( "ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout" );
|
4885 |
+
$this->proxyhost = $proxyhost;
|
4886 |
+
$this->proxyport = $proxyport;
|
4887 |
+
$this->proxyusername = $proxyusername;
|
4888 |
+
$this->proxypassword = $proxypassword;
|
4889 |
+
$this->timeout = $timeout;
|
4890 |
+
$this->response_timeout = $response_timeout;
|
4891 |
+
if ( is_array( $curl_options ) ) {
|
4892 |
+
$this->curl_options = $curl_options;
|
4893 |
+
}
|
4894 |
+
$this->use_curl = $use_curl;
|
4895 |
+
$this->fetchWSDL( $wsdl );
|
4896 |
+
}
|
4897 |
+
|
4898 |
+
/**
|
4899 |
+
* fetches the WSDL document and parses it
|
4900 |
+
*
|
4901 |
+
* @access public
|
4902 |
+
*/
|
4903 |
+
function fetchWSDL( $wsdl ) {
|
4904 |
+
$this->debug( "parse and process WSDL path=$wsdl" );
|
4905 |
+
$this->wsdl = $wsdl;
|
4906 |
+
// parse wsdl file
|
4907 |
+
if ( $this->wsdl != "" ) {
|
4908 |
+
$this->parseWSDL( $this->wsdl );
|
4909 |
+
}
|
4910 |
+
// imports
|
4911 |
+
// TODO: handle imports more properly, grabbing them in-line and nesting them
|
4912 |
+
$imported_urls = array();
|
4913 |
+
$imported = 1;
|
4914 |
+
while ( $imported > 0 ) {
|
4915 |
+
$imported = 0;
|
4916 |
+
// Schema imports
|
4917 |
+
foreach ( $this->schemas as $ns => $list ) {
|
4918 |
+
foreach ( $list as $xs ) {
|
4919 |
+
$wsdlparts = parse_url( $this->wsdl ); // this is bogusly simple!
|
4920 |
+
foreach ( $xs->imports as $ns2 => $list2 ) {
|
4921 |
+
for ( $ii = 0; $ii < count( $list2 ); $ii ++ ) {
|
4922 |
+
if ( ! $list2[ $ii ]['loaded'] ) {
|
4923 |
+
$this->schemas[ $ns ]->imports[ $ns2 ][ $ii ]['loaded'] = true;
|
4924 |
+
$url = $list2[ $ii ]['location'];
|
4925 |
+
if ( $url != '' ) {
|
4926 |
+
$urlparts = parse_url( $url );
|
4927 |
+
if ( ! isset( $urlparts['host'] ) ) {
|
4928 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . ( isset( $wsdlparts['port'] ) ? ':' . $wsdlparts['port'] : '' ) .
|
4929 |
+
substr( $wsdlparts['path'], 0, strrpos( $wsdlparts['path'], '/' ) + 1 ) . $urlparts['path'];
|
4930 |
+
}
|
4931 |
+
if ( ! in_array( $url, $imported_urls ) ) {
|
4932 |
+
$this->parseWSDL( $url );
|
4933 |
+
$imported ++;
|
4934 |
+
$imported_urls[] = $url;
|
4935 |
+
}
|
4936 |
+
} else {
|
4937 |
+
$this->debug( "Unexpected scenario: empty URL for unloaded import" );
|
4938 |
+
}
|
4939 |
+
}
|
4940 |
+
}
|
4941 |
+
}
|
4942 |
+
}
|
4943 |
+
}
|
4944 |
+
// WSDL imports
|
4945 |
+
$wsdlparts = parse_url( $this->wsdl ); // this is bogusly simple!
|
4946 |
+
foreach ( $this->import as $ns => $list ) {
|
4947 |
+
for ( $ii = 0; $ii < count( $list ); $ii ++ ) {
|
4948 |
+
if ( ! $list[ $ii ]['loaded'] ) {
|
4949 |
+
$this->import[ $ns ][ $ii ]['loaded'] = true;
|
4950 |
+
$url = $list[ $ii ]['location'];
|
4951 |
+
if ( $url != '' ) {
|
4952 |
+
$urlparts = parse_url( $url );
|
4953 |
+
if ( ! isset( $urlparts['host'] ) ) {
|
4954 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . ( isset( $wsdlparts['port'] ) ? ':' . $wsdlparts['port'] : '' ) .
|
4955 |
+
substr( $wsdlparts['path'], 0, strrpos( $wsdlparts['path'], '/' ) + 1 ) . $urlparts['path'];
|
4956 |
+
}
|
4957 |
+
if ( ! in_array( $url, $imported_urls ) ) {
|
4958 |
+
$this->parseWSDL( $url );
|
4959 |
+
$imported ++;
|
4960 |
+
$imported_urls[] = $url;
|
4961 |
+
}
|
4962 |
+
} else {
|
4963 |
+
$this->debug( "Unexpected scenario: empty URL for unloaded import" );
|
4964 |
+
}
|
4965 |
+
}
|
4966 |
+
}
|
4967 |
+
}
|
4968 |
+
}
|
4969 |
+
// add new data to operation data
|
4970 |
+
foreach ( $this->bindings as $binding => $bindingData ) {
|
4971 |
+
if ( isset( $bindingData['operations'] ) && is_array( $bindingData['operations'] ) ) {
|
4972 |
+
foreach ( $bindingData['operations'] as $operation => $data ) {
|
4973 |
+
$this->debug( 'post-parse data gathering for ' . $operation );
|
4974 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['input'] =
|
4975 |
+
isset( $this->bindings[ $binding ]['operations'][ $operation ]['input'] ) ?
|
4976 |
+
array_merge( $this->bindings[ $binding ]['operations'][ $operation ]['input'], $this->portTypes[ $bindingData['portType'] ][ $operation ]['input'] ) :
|
4977 |
+
$this->portTypes[ $bindingData['portType'] ][ $operation ]['input'];
|
4978 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['output'] =
|
4979 |
+
isset( $this->bindings[ $binding ]['operations'][ $operation ]['output'] ) ?
|
4980 |
+
array_merge( $this->bindings[ $binding ]['operations'][ $operation ]['output'], $this->portTypes[ $bindingData['portType'] ][ $operation ]['output'] ) :
|
4981 |
+
$this->portTypes[ $bindingData['portType'] ][ $operation ]['output'];
|
4982 |
+
if ( isset( $this->messages[ $this->bindings[ $binding ]['operations'][ $operation ]['input']['message'] ] ) ) {
|
4983 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['input']['parts'] = $this->messages[ $this->bindings[ $binding ]['operations'][ $operation ]['input']['message'] ];
|
4984 |
+
}
|
4985 |
+
if ( isset( $this->messages[ $this->bindings[ $binding ]['operations'][ $operation ]['output']['message'] ] ) ) {
|
4986 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['output']['parts'] = $this->messages[ $this->bindings[ $binding ]['operations'][ $operation ]['output']['message'] ];
|
4987 |
+
}
|
4988 |
+
// Set operation style if necessary, but do not override one already provided
|
4989 |
+
if ( isset( $bindingData['style'] ) && ! isset( $this->bindings[ $binding ]['operations'][ $operation ]['style'] ) ) {
|
4990 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['style'] = $bindingData['style'];
|
4991 |
+
}
|
4992 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['transport'] = isset( $bindingData['transport'] ) ? $bindingData['transport'] : '';
|
4993 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['documentation'] = isset( $this->portTypes[ $bindingData['portType'] ][ $operation ]['documentation'] ) ? $this->portTypes[ $bindingData['portType'] ][ $operation ]['documentation'] : '';
|
4994 |
+
$this->bindings[ $binding ]['operations'][ $operation ]['endpoint'] = isset( $bindingData['endpoint'] ) ? $bindingData['endpoint'] : '';
|
4995 |
+
}
|
4996 |
+
}
|
4997 |
+
}
|
4998 |
+
}
|
4999 |
+
|
5000 |
+
/**
|
5001 |
+
* parses the wsdl document
|
5002 |
+
*
|
5003 |
+
* @param string $wsdl path or URL
|
5004 |
+
*
|
5005 |
+
* @access private
|
5006 |
+
*/
|
5007 |
+
function parseWSDL( $wsdl = '' ) {
|
5008 |
+
$this->debug( "parse WSDL at path=$wsdl" );
|
5009 |
+
|
5010 |
+
if ( $wsdl == '' ) {
|
5011 |
+
$this->debug( 'no wsdl passed to parseWSDL()!!' );
|
5012 |
+
$this->setError( 'no wsdl passed to parseWSDL()!!' );
|
5013 |
+
|
5014 |
+
return false;
|
5015 |
+
}
|
5016 |
+
|
5017 |
+
// parse $wsdl for url format
|
5018 |
+
$wsdl_props = parse_url( $wsdl );
|
5019 |
+
|
5020 |
+
if ( isset( $wsdl_props['scheme'] ) && ( $wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https' ) ) {
|
5021 |
+
$this->debug( 'getting WSDL http(s) URL ' . $wsdl );
|
5022 |
+
// get wsdl
|
5023 |
+
$tr = new soap_transport_http( $wsdl, $this->curl_options, $this->use_curl );
|
5024 |
+
$tr->request_method = 'GET';
|
5025 |
+
$tr->useSOAPAction = false;
|
5026 |
+
if ( $this->proxyhost && $this->proxyport ) {
|
5027 |
+
$tr->setProxy( $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword );
|
5028 |
+
}
|
5029 |
+
if ( $this->authtype != '' ) {
|
5030 |
+
$tr->setCredentials( $this->username, $this->password, $this->authtype, array(), $this->certRequest );
|
5031 |
+
}
|
5032 |
+
$tr->setEncoding( 'gzip, deflate' );
|
5033 |
+
$wsdl_string = $tr->send( '', $this->timeout, $this->response_timeout );
|
5034 |
+
//$this->debug("WSDL request\n" . $tr->outgoing_payload);
|
5035 |
+
//$this->debug("WSDL response\n" . $tr->incoming_payload);
|
5036 |
+
$this->appendDebug( $tr->getDebug() );
|
5037 |
+
// catch errors
|
5038 |
+
if ( $err = $tr->getError() ) {
|
5039 |
+
$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: ' . $err;
|
5040 |
+
$this->debug( $errstr );
|
5041 |
+
$this->setError( $errstr );
|
5042 |
+
unset( $tr );
|
5043 |
+
|
5044 |
+
return false;
|
5045 |
+
}
|
5046 |
+
unset( $tr );
|
5047 |
+
$this->debug( "got WSDL URL" );
|
5048 |
+
} else {
|
5049 |
+
// $wsdl is not http(s), so treat it as a file URL or plain file path
|
5050 |
+
if ( isset( $wsdl_props['scheme'] ) && ( $wsdl_props['scheme'] == 'file' ) && isset( $wsdl_props['path'] ) ) {
|
5051 |
+
$path = isset( $wsdl_props['host'] ) ? ( $wsdl_props['host'] . ':' . $wsdl_props['path'] ) : $wsdl_props['path'];
|
5052 |
+
} else {
|
5053 |
+
$path = $wsdl;
|
5054 |
+
}
|
5055 |
+
$this->debug( 'getting WSDL file ' . $path );
|
5056 |
+
if ( $fp = @fopen( $path, 'r' ) ) {
|
5057 |
+
$wsdl_string = '';
|
5058 |
+
while ( $data = fread( $fp, 32768 ) ) {
|
5059 |
+
$wsdl_string .= $data;
|
5060 |
+
}
|
5061 |
+
fclose( $fp );
|
5062 |
+
} else {
|
5063 |
+
$errstr = "Bad path to WSDL file $path";
|
5064 |
+
$this->debug( $errstr );
|
5065 |
+
$this->setError( $errstr );
|
5066 |
+
|
5067 |
+
return false;
|
5068 |
+
}
|
5069 |
+
}
|
5070 |
+
$this->debug( 'Parse WSDL' );
|
5071 |
+
// end new code added
|
5072 |
+
// Create an XML parser.
|
5073 |
+
$this->parser = xml_parser_create();
|
5074 |
+
// Set the options for parsing the XML data.
|
5075 |
+
// xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
5076 |
+
xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, 0 );
|
5077 |
+
// Set the object for the parser.
|
5078 |
+
xml_set_object( $this->parser, $this );
|
5079 |
+
// Set the element handlers for the parser.
|
5080 |
+
xml_set_element_handler( $this->parser, 'start_element', 'end_element' );
|
5081 |
+
xml_set_character_data_handler( $this->parser, 'character_data' );
|
5082 |
+
// Parse the XML file.
|
5083 |
+
if ( ! xml_parse( $this->parser, $wsdl_string, true ) ) {
|
5084 |
+
// Display an error message.
|
5085 |
+
$errstr = sprintf(
|
5086 |
+
'XML error parsing WSDL from %s on line %d: %s',
|
5087 |
+
$wsdl,
|
5088 |
+
xml_get_current_line_number( $this->parser ),
|
5089 |
+
xml_error_string( xml_get_error_code( $this->parser ) )
|
5090 |
+
);
|
5091 |
+
$this->debug( $errstr );
|
5092 |
+
$this->debug( "XML payload:\n" . $wsdl_string );
|
5093 |
+
$this->setError( $errstr );
|
5094 |
+
|
5095 |
+
return false;
|
5096 |
+
}
|
5097 |
+
// free the parser
|
5098 |
+
xml_parser_free( $this->parser );
|
5099 |
+
$this->debug( 'Parsing WSDL done' );
|
5100 |
+
// catch wsdl parse errors
|
5101 |
+
if ( $this->getError() ) {
|
5102 |
+
return false;
|
5103 |
+
}
|
5104 |
+
|
5105 |
+
return true;
|
5106 |
+
}
|
5107 |
+
|
5108 |
+
/**
|
5109 |
+
* start-element handler
|
5110 |
+
*
|
5111 |
+
* @param string $parser XML parser object
|
5112 |
+
* @param string $name element name
|
5113 |
+
* @param string $attrs associative array of attributes
|
5114 |
+
*
|
5115 |
+
* @access private
|
5116 |
+
*/
|
5117 |
+
function start_element( $parser, $name, $attrs ) {
|
5118 |
+
if ( $this->status == 'schema' ) {
|
5119 |
+
$this->currentSchema->schemaStartElement( $parser, $name, $attrs );
|
5120 |
+
$this->appendDebug( $this->currentSchema->getDebug() );
|
5121 |
+
$this->currentSchema->clearDebug();
|
5122 |
+
} elseif ( preg_match( '/schema$/', $name ) ) {
|
5123 |
+
$this->debug( 'Parsing WSDL schema' );
|
5124 |
+
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
|
5125 |
+
$this->status = 'schema';
|
5126 |
+
$this->currentSchema = new nusoap_xmlschema( '', '', $this->namespaces );
|
5127 |
+
$this->currentSchema->schemaStartElement( $parser, $name, $attrs );
|
5128 |
+
$this->appendDebug( $this->currentSchema->getDebug() );
|
5129 |
+
$this->currentSchema->clearDebug();
|
5130 |
+
} else {
|
5131 |
+
// position in the total number of elements, starting from 0
|
5132 |
+
$pos = $this->position ++;
|
5133 |
+
$depth = $this->depth ++;
|
5134 |
+
// set self as current value for this depth
|
5135 |
+
$this->depth_array[ $depth ] = $pos;
|
5136 |
+
$this->message[ $pos ] = array( 'cdata' => '' );
|
5137 |
+
// process attributes
|
5138 |
+
if ( count( $attrs ) > 0 ) {
|
5139 |
+
// register namespace declarations
|
5140 |
+
foreach ( $attrs as $k => $v ) {
|
5141 |
+
if ( preg_match( '/^xmlns/', $k ) ) {
|
5142 |
+
if ( $ns_prefix = substr( strrchr( $k, ':' ), 1 ) ) {
|
5143 |
+
$this->namespaces[ $ns_prefix ] = $v;
|
5144 |
+
} else {
|
5145 |
+
$this->namespaces[ 'ns' . ( count( $this->namespaces ) + 1 ) ] = $v;
|
5146 |
+
}
|
5147 |
+
if ( $v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema' ) {
|
5148 |
+
$this->XMLSchemaVersion = $v;
|
5149 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
5150 |
+
}
|
5151 |
+
}
|
5152 |
+
}
|
5153 |
+
// expand each attribute prefix to its namespace
|
5154 |
+
foreach ( $attrs as $k => $v ) {
|
5155 |
+
$k = strpos( $k, ':' ) ? $this->expandQname( $k ) : $k;
|
5156 |
+
if ( $k != 'location' && $k != 'soapAction' && $k != 'namespace' ) {
|
5157 |
+
$v = strpos( $v, ':' ) ? $this->expandQname( $v ) : $v;
|
5158 |
+
}
|
5159 |
+
$eAttrs[ $k ] = $v;
|
5160 |
+
}
|
5161 |
+
$attrs = $eAttrs;
|
5162 |
+
} else {
|
5163 |
+
$attrs = array();
|
5164 |
+
}
|
5165 |
+
// get element prefix, namespace and name
|
5166 |
+
if ( preg_match( '/:/', $name ) ) {
|
5167 |
+
// get ns prefix
|
5168 |
+
$prefix = substr( $name, 0, strpos( $name, ':' ) );
|
5169 |
+
// get ns
|
5170 |
+
$namespace = isset( $this->namespaces[ $prefix ] ) ? $this->namespaces[ $prefix ] : '';
|
5171 |
+
// get unqualified name
|
5172 |
+
$name = substr( strstr( $name, ':' ), 1 );
|
5173 |
+
}
|
5174 |
+
// process attributes, expanding any prefixes to namespaces
|
5175 |
+
// find status, register data
|
5176 |
+
switch ( $this->status ) {
|
5177 |
+
case 'message':
|
5178 |
+
if ( $name == 'part' ) {
|
5179 |
+
if ( isset( $attrs['type'] ) ) {
|
5180 |
+
$this->debug( "msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode( ',', $attrs ) );
|
5181 |
+
$this->messages[ $this->currentMessage ][ $attrs['name'] ] = $attrs['type'];
|
5182 |
+
}
|
5183 |
+
if ( isset( $attrs['element'] ) ) {
|
5184 |
+
$this->debug( "msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode( ',', $attrs ) );
|
5185 |
+
$this->messages[ $this->currentMessage ][ $attrs['name'] ] = $attrs['element'] . '^';
|
5186 |
+
}
|
5187 |
+
}
|
5188 |
+
break;
|
5189 |
+
case 'portType':
|
5190 |
+
switch ( $name ) {
|
5191 |
+
case 'operation':
|
5192 |
+
$this->currentPortOperation = $attrs['name'];
|
5193 |
+
$this->debug( "portType $this->currentPortType operation: $this->currentPortOperation" );
|
5194 |
+
if ( isset( $attrs['parameterOrder'] ) ) {
|
5195 |
+
$this->portTypes[ $this->currentPortType ][ $attrs['name'] ]['parameterOrder'] = $attrs['parameterOrder'];
|
5196 |
+
}
|
5197 |
+
break;
|
5198 |
+
case 'documentation':
|
5199 |
+
$this->documentation = true;
|
5200 |
+
break;
|
5201 |
+
// merge input/output data
|
5202 |
+
default:
|
5203 |
+
$m = isset( $attrs['message'] ) ? $this->getLocalPart( $attrs['message'] ) : '';
|
5204 |
+
$this->portTypes[ $this->currentPortType ][ $this->currentPortOperation ][ $name ]['message'] = $m;
|
5205 |
+
break;
|
5206 |
+
}
|
5207 |
+
break;
|
5208 |
+
case 'binding':
|
5209 |
+
switch ( $name ) {
|
5210 |
+
case 'binding':
|
5211 |
+
// get ns prefix
|
5212 |
+
if ( isset( $attrs['style'] ) ) {
|
5213 |
+
$this->bindings[ $this->currentBinding ]['prefix'] = $prefix;
|
5214 |
+
}
|
5215 |
+
$this->bindings[ $this->currentBinding ] = array_merge( $this->bindings[ $this->currentBinding ], $attrs );
|
5216 |
+
break;
|
5217 |
+
case 'header':
|
5218 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ][ $this->opStatus ]['headers'][] = $attrs;
|
5219 |
+
break;
|
5220 |
+
case 'operation':
|
5221 |
+
if ( isset( $attrs['soapAction'] ) ) {
|
5222 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ]['soapAction'] = $attrs['soapAction'];
|
5223 |
+
}
|
5224 |
+
if ( isset( $attrs['style'] ) ) {
|
5225 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ]['style'] = $attrs['style'];
|
5226 |
+
}
|
5227 |
+
if ( isset( $attrs['name'] ) ) {
|
5228 |
+
$this->currentOperation = $attrs['name'];
|
5229 |
+
$this->debug( "current binding operation: $this->currentOperation" );
|
5230 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ]['name'] = $attrs['name'];
|
5231 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ]['binding'] = $this->currentBinding;
|
5232 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ]['endpoint'] = isset( $this->bindings[ $this->currentBinding ]['endpoint'] ) ? $this->bindings[ $this->currentBinding ]['endpoint'] : '';
|
5233 |
+
}
|
5234 |
+
break;
|
5235 |
+
case 'input':
|
5236 |
+
$this->opStatus = 'input';
|
5237 |
+
break;
|
5238 |
+
case 'output':
|
5239 |
+
$this->opStatus = 'output';
|
5240 |
+
break;
|
5241 |
+
case 'body':
|
5242 |
+
if ( isset( $this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ][ $this->opStatus ] ) ) {
|
5243 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ][ $this->opStatus ] = array_merge( $this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ][ $this->opStatus ], $attrs );
|
5244 |
+
} else {
|
5245 |
+
$this->bindings[ $this->currentBinding ]['operations'][ $this->currentOperation ][ $this->opStatus ] = $attrs;
|
5246 |
+
}
|
5247 |
+
break;
|
5248 |
+
}
|
5249 |
+
break;
|
5250 |
+
case 'service':
|
5251 |
+
switch ( $name ) {
|
5252 |
+
case 'port':
|
5253 |
+
$this->currentPort = $attrs['name'];
|
5254 |
+
$this->debug( 'current port: ' . $this->currentPort );
|
5255 |
+
$this->ports[ $this->currentPort ]['binding'] = $this->getLocalPart( $attrs['binding'] );
|
5256 |
+
|
5257 |
+
break;
|
5258 |
+
case 'address':
|
5259 |
+
$this->ports[ $this->currentPort ]['location'] = $attrs['location'];
|
5260 |
+
$this->ports[ $this->currentPort ]['bindingType'] = $namespace;
|
5261 |
+
$this->bindings[ $this->ports[ $this->currentPort ]['binding'] ]['bindingType'] = $namespace;
|
5262 |
+
$this->bindings[ $this->ports[ $this->currentPort ]['binding'] ]['endpoint'] = $attrs['location'];
|
5263 |
+
break;
|
5264 |
+
}
|
5265 |
+
break;
|
5266 |
+
}
|
5267 |
+
// set status
|
5268 |
+
switch ( $name ) {
|
5269 |
+
case 'import':
|
5270 |
+
if ( isset( $attrs['location'] ) ) {
|
5271 |
+
$this->import[ $attrs['namespace'] ][] = array(
|
5272 |
+
'location' => $attrs['location'],
|
5273 |
+
'loaded' => false
|
5274 |
+
);
|
5275 |
+
$this->debug( 'parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count( $this->import[ $attrs['namespace'] ] ) . ')' );
|
5276 |
+
} else {
|
5277 |
+
$this->import[ $attrs['namespace'] ][] = array( 'location' => '', 'loaded' => true );
|
5278 |
+
if ( ! $this->getPrefixFromNamespace( $attrs['namespace'] ) ) {
|
5279 |
+
$this->namespaces[ 'ns' . ( count( $this->namespaces ) + 1 ) ] = $attrs['namespace'];
|
5280 |
+
}
|
5281 |
+
$this->debug( 'parsing import ' . $attrs['namespace'] . ' - [no location] (' . count( $this->import[ $attrs['namespace'] ] ) . ')' );
|
5282 |
+
}
|
5283 |
+
break;
|
5284 |
+
//wait for schema
|
5285 |
+
//case 'types':
|
5286 |
+
// $this->status = 'schema';
|
5287 |
+
// break;
|
5288 |
+
case 'message':
|
5289 |
+
$this->status = 'message';
|
5290 |
+
$this->messages[ $attrs['name'] ] = array();
|
5291 |
+
$this->currentMessage = $attrs['name'];
|
5292 |
+
break;
|
5293 |
+
case 'portType':
|
5294 |
+
$this->status = 'portType';
|
5295 |
+
$this->portTypes[ $attrs['name'] ] = array();
|
5296 |
+
$this->currentPortType = $attrs['name'];
|
5297 |
+
break;
|
5298 |
+
case "binding":
|
5299 |
+
if ( isset( $attrs['name'] ) ) {
|
5300 |
+
// get binding name
|
5301 |
+
if ( strpos( $attrs['name'], ':' ) ) {
|
5302 |
+
$this->currentBinding = $this->getLocalPart( $attrs['name'] );
|
5303 |
+
} else {
|
5304 |
+
$this->currentBinding = $attrs['name'];
|
5305 |
+
}
|
5306 |
+
$this->status = 'binding';
|
5307 |
+
$this->bindings[ $this->currentBinding ]['portType'] = $this->getLocalPart( $attrs['type'] );
|
5308 |
+
$this->debug( "current binding: $this->currentBinding of portType: " . $attrs['type'] );
|
5309 |
+
}
|
5310 |
+
break;
|
5311 |
+
case 'service':
|
5312 |
+
$this->serviceName = $attrs['name'];
|
5313 |
+
$this->status = 'service';
|
5314 |
+
$this->debug( 'current service: ' . $this->serviceName );
|
5315 |
+
break;
|
5316 |
+
case 'definitions':
|
5317 |
+
foreach ( $attrs as $name => $value ) {
|
5318 |
+
$this->wsdl_info[ $name ] = $value;
|
5319 |
+
}
|
5320 |
+
break;
|
5321 |
+
}
|
5322 |
+
}
|
5323 |
+
}
|
5324 |
+
|
5325 |
+
/**
|
5326 |
+
* end-element handler
|
5327 |
+
*
|
5328 |
+
* @param string $parser XML parser object
|
5329 |
+
* @param string $name element name
|
5330 |
+
*
|
5331 |
+
* @access private
|
5332 |
+
*/
|
5333 |
+
function end_element( $parser, $name ) {
|
5334 |
+
// unset schema status
|
5335 |
+
if (/*preg_match('/types$/', $name) ||*/
|
5336 |
+
preg_match( '/schema$/', $name ) ) {
|
5337 |
+
$this->status = "";
|
5338 |
+
$this->appendDebug( $this->currentSchema->getDebug() );
|
5339 |
+
$this->currentSchema->clearDebug();
|
5340 |
+
$this->schemas[ $this->currentSchema->schemaTargetNamespace ][] = $this->currentSchema;
|
5341 |
+
$this->debug( 'Parsing WSDL schema done' );
|
5342 |
+
}
|
5343 |
+
if ( $this->status == 'schema' ) {
|
5344 |
+
$this->currentSchema->schemaEndElement( $parser, $name );
|
5345 |
+
} else {
|
5346 |
+
// bring depth down a notch
|
5347 |
+
$this->depth --;
|
5348 |
+
}
|
5349 |
+
// end documentation
|
5350 |
+
if ( $this->documentation ) {
|
5351 |
+
//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
|
5352 |
+
//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
|
5353 |
+
$this->documentation = false;
|
5354 |
+
}
|
5355 |
+
}
|
5356 |
+
|
5357 |
+
/**
|
5358 |
+
* element content handler
|
5359 |
+
*
|
5360 |
+
* @param string $parser XML parser object
|
5361 |
+
* @param string $data element content
|
5362 |
+
*
|
5363 |
+
* @access private
|
5364 |
+
*/
|
5365 |
+
function character_data( $parser, $data ) {
|
5366 |
+
$pos = isset( $this->depth_array[ $this->depth ] ) ? $this->depth_array[ $this->depth ] : 0;
|
5367 |
+
if ( isset( $this->message[ $pos ]['cdata'] ) ) {
|
5368 |
+
$this->message[ $pos ]['cdata'] .= $data;
|
5369 |
+
}
|
5370 |
+
if ( $this->documentation ) {
|
5371 |
+
$this->documentation .= $data;
|
5372 |
+
}
|
5373 |
+
}
|
5374 |
+
|
5375 |
+
/**
|
5376 |
+
* if authenticating, set user credentials here
|
5377 |
+
*
|
5378 |
+
* @param string $username
|
5379 |
+
* @param string $password
|
5380 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
5381 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
5382 |
+
*
|
5383 |
+
* @access public
|
5384 |
+
*/
|
5385 |
+
function setCredentials( $username, $password, $authtype = 'basic', $certRequest = array() ) {
|
5386 |
+
$this->debug( "setCredentials username=$username authtype=$authtype certRequest=" );
|
5387 |
+
$this->appendDebug( $this->varDump( $certRequest ) );
|
5388 |
+
$this->username = $username;
|
5389 |
+
$this->password = $password;
|
5390 |
+
$this->authtype = $authtype;
|
5391 |
+
$this->certRequest = $certRequest;
|
5392 |
+
}
|
5393 |
+
|
5394 |
+
function getBindingData( $binding ) {
|
5395 |
+
if ( is_array( $this->bindings[ $binding ] ) ) {
|
5396 |
+
return $this->bindings[ $binding ];
|
5397 |
+
}
|
5398 |
+
}
|
5399 |
+
|
5400 |
+
/**
|
5401 |
+
* returns an assoc array of operation names => operation data
|
5402 |
+
*
|
5403 |
+
* @param string $portName WSDL port name
|
5404 |
+
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
|
5405 |
+
*
|
5406 |
+
* @return array
|
5407 |
+
* @access public
|
5408 |
+
*/
|
5409 |
+
function getOperations( $portName = '', $bindingType = 'soap' ) {
|
5410 |
+
$ops = array();
|
5411 |
+
if ( $bindingType == 'soap' ) {
|
5412 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5413 |
+
} elseif ( $bindingType == 'soap12' ) {
|
5414 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5415 |
+
} else {
|
5416 |
+
$this->debug( "getOperations bindingType $bindingType may not be supported" );
|
5417 |
+
}
|
5418 |
+
$this->debug( "getOperations for port '$portName' bindingType $bindingType" );
|
5419 |
+
// loop thru ports
|
5420 |
+
foreach ( $this->ports as $port => $portData ) {
|
5421 |
+
$this->debug( "getOperations checking port $port bindingType " . $portData['bindingType'] );
|
5422 |
+
if ( $portName == '' || $port == $portName ) {
|
5423 |
+
// binding type of port matches parameter
|
5424 |
+
if ( $portData['bindingType'] == $bindingType ) {
|
5425 |
+
$this->debug( "getOperations found port $port bindingType $bindingType" );
|
5426 |
+
//$this->debug("port data: " . $this->varDump($portData));
|
5427 |
+
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
|
5428 |
+
// merge bindings
|
5429 |
+
if ( isset( $this->bindings[ $portData['binding'] ]['operations'] ) ) {
|
5430 |
+
$ops = array_merge( $ops, $this->bindings[ $portData['binding'] ]['operations'] );
|
5431 |
+
}
|
5432 |
+
}
|
5433 |
+
}
|
5434 |
+
}
|
5435 |
+
if ( count( $ops ) == 0 ) {
|
5436 |
+
$this->debug( "getOperations found no operations for port '$portName' bindingType $bindingType" );
|
5437 |
+
}
|
5438 |
+
|
5439 |
+
return $ops;
|
5440 |
+
}
|
5441 |
+
|
5442 |
+
/**
|
5443 |
+
* returns an associative array of data necessary for calling an operation
|
5444 |
+
*
|
5445 |
+
* @param string $operation name of operation
|
5446 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5447 |
+
*
|
5448 |
+
* @return array
|
5449 |
+
* @access public
|
5450 |
+
*/
|
5451 |
+
function getOperationData( $operation, $bindingType = 'soap' ) {
|
5452 |
+
if ( $bindingType == 'soap' ) {
|
5453 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5454 |
+
} elseif ( $bindingType == 'soap12' ) {
|
5455 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5456 |
+
}
|
5457 |
+
// loop thru ports
|
5458 |
+
foreach ( $this->ports as $port => $portData ) {
|
5459 |
+
// binding type of port matches parameter
|
5460 |
+
if ( $portData['bindingType'] == $bindingType ) {
|
5461 |
+
// get binding
|
5462 |
+
//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
5463 |
+
foreach ( array_keys( $this->bindings[ $portData['binding'] ]['operations'] ) as $bOperation ) {
|
5464 |
+
// note that we could/should also check the namespace here
|
5465 |
+
if ( $operation == $bOperation ) {
|
5466 |
+
$opData = $this->bindings[ $portData['binding'] ]['operations'][ $operation ];
|
5467 |
+
|
5468 |
+
return $opData;
|
5469 |
+
}
|
5470 |
+
}
|
5471 |
+
}
|
5472 |
+
}
|
5473 |
+
}
|
5474 |
+
|
5475 |
+
/**
|
5476 |
+
* returns an associative array of data necessary for calling an operation
|
5477 |
+
*
|
5478 |
+
* @param string $soapAction soapAction for operation
|
5479 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5480 |
+
*
|
5481 |
+
* @return array
|
5482 |
+
* @access public
|
5483 |
+
*/
|
5484 |
+
function getOperationDataForSoapAction( $soapAction, $bindingType = 'soap' ) {
|
5485 |
+
if ( $bindingType == 'soap' ) {
|
5486 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5487 |
+
} elseif ( $bindingType == 'soap12' ) {
|
5488 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5489 |
+
}
|
5490 |
+
// loop thru ports
|
5491 |
+
foreach ( $this->ports as $port => $portData ) {
|
5492 |
+
// binding type of port matches parameter
|
5493 |
+
if ( $portData['bindingType'] == $bindingType ) {
|
5494 |
+
// loop through operations for the binding
|
5495 |
+
foreach ( $this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData ) {
|
5496 |
+
if ( $opData['soapAction'] == $soapAction ) {
|
5497 |
+
return $opData;
|
5498 |
+
}
|
5499 |
+
}
|
5500 |
+
}
|
5501 |
+
}
|
5502 |
+
}
|
5503 |
+
|
5504 |
+
/**
|
5505 |
+
* returns an array of information about a given type
|
5506 |
+
* returns false if no type exists by the given name
|
5507 |
+
*
|
5508 |
+
* typeDef = array(
|
5509 |
+
* 'elements' => array(), // refs to elements array
|
5510 |
+
* 'restrictionBase' => '',
|
5511 |
+
* 'phpType' => '',
|
5512 |
+
* 'order' => '(sequence|all)',
|
5513 |
+
* 'attrs' => array() // refs to attributes array
|
5514 |
+
* )
|
5515 |
+
*
|
5516 |
+
* @param string $type the type
|
5517 |
+
* @param string $ns namespace (not prefix) of the type
|
5518 |
+
*
|
5519 |
+
* @return mixed
|
5520 |
+
* @access public
|
5521 |
+
* @see nusoap_xmlschema
|
5522 |
+
*/
|
5523 |
+
function getTypeDef( $type, $ns ) {
|
5524 |
+
$this->debug( "in getTypeDef: type=$type, ns=$ns" );
|
5525 |
+
if ( ( ! $ns ) && isset( $this->namespaces['tns'] ) ) {
|
5526 |
+
$ns = $this->namespaces['tns'];
|
5527 |
+
$this->debug( "in getTypeDef: type namespace forced to $ns" );
|
5528 |
+
}
|
5529 |
+
if ( ! isset( $this->schemas[ $ns ] ) ) {
|
5530 |
+
foreach ( $this->schemas as $ns0 => $schema0 ) {
|
5531 |
+
if ( strcasecmp( $ns, $ns0 ) == 0 ) {
|
5532 |
+
$this->debug( "in getTypeDef: replacing schema namespace $ns with $ns0" );
|
5533 |
+
$ns = $ns0;
|
5534 |
+
break;
|
5535 |
+
}
|
5536 |
+
}
|
5537 |
+
}
|
5538 |
+
if ( isset( $this->schemas[ $ns ] ) ) {
|
5539 |
+
$this->debug( "in getTypeDef: have schema for namespace $ns" );
|
5540 |
+
for ( $i = 0; $i < count( $this->schemas[ $ns ] ); $i ++ ) {
|
5541 |
+
$xs = &$this->schemas[ $ns ][ $i ];
|
5542 |
+
$t = $xs->getTypeDef( $type );
|
5543 |
+
$this->appendDebug( $xs->getDebug() );
|
5544 |
+
$xs->clearDebug();
|
5545 |
+
if ( $t ) {
|
5546 |
+
$this->debug( "in getTypeDef: found type $type" );
|
5547 |
+
if ( ! isset( $t['phpType'] ) ) {
|
5548 |
+
// get info for type to tack onto the element
|
5549 |
+
$uqType = substr( $t['type'], strrpos( $t['type'], ':' ) + 1 );
|
5550 |
+
$ns = substr( $t['type'], 0, strrpos( $t['type'], ':' ) );
|
5551 |
+
$etype = $this->getTypeDef( $uqType, $ns );
|
5552 |
+
if ( $etype ) {
|
5553 |
+
$this->debug( "found type for [element] $type:" );
|
5554 |
+
$this->debug( $this->varDump( $etype ) );
|
5555 |
+
if ( isset( $etype['phpType'] ) ) {
|
5556 |
+
$t['phpType'] = $etype['phpType'];
|
5557 |
+
}
|
5558 |
+
if ( isset( $etype['elements'] ) ) {
|
5559 |
+
$t['elements'] = $etype['elements'];
|
5560 |
+
}
|
5561 |
+
if ( isset( $etype['attrs'] ) ) {
|
5562 |
+
$t['attrs'] = $etype['attrs'];
|
5563 |
+
}
|
5564 |
+
} else {
|
5565 |
+
$this->debug( "did not find type for [element] $type" );
|
5566 |
+
}
|
5567 |
+
}
|
5568 |
+
|
5569 |
+
return $t;
|
5570 |
+
}
|
5571 |
+
}
|
5572 |
+
$this->debug( "in getTypeDef: did not find type $type" );
|
5573 |
+
} else {
|
5574 |
+
$this->debug( "in getTypeDef: do not have schema for namespace $ns" );
|
5575 |
+
}
|
5576 |
+
|
5577 |
+
return false;
|
5578 |
+
}
|
5579 |
+
|
5580 |
+
/**
|
5581 |
+
* prints html description of services
|
5582 |
+
*
|
5583 |
+
* @access private
|
5584 |
+
*/
|
5585 |
+
function webDescription() {
|
5586 |
+
global $HTTP_SERVER_VARS;
|
5587 |
+
|
5588 |
+
if ( isset( $_SERVER ) ) {
|
5589 |
+
$PHP_SELF = $_SERVER['PHP_SELF'];
|
5590 |
+
} elseif ( isset( $HTTP_SERVER_VARS ) ) {
|
5591 |
+
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
|
5592 |
+
} else {
|
5593 |
+
$this->setError( "Neither _SERVER nor HTTP_SERVER_VARS is available" );
|
5594 |
+
}
|
5595 |
+
|
5596 |
+
$b = '
|
5597 |
+
<html><head><title>NuSOAP: ' . $this->serviceName . '</title>
|
5598 |
+
<style type="text/css">
|
5599 |
+
body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
|
5600 |
+
p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
|
5601 |
+
pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
|
5602 |
+
ul { margin-top: 10px; margin-left: 20px; }
|
5603 |
+
li { list-style-type: none; margin-top: 10px; color: #000000; }
|
5604 |
+
.content{
|
5605 |
+
margin-left: 0px; padding-bottom: 2em; }
|
5606 |
+
.nav {
|
5607 |
+
padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
|
5608 |
+
margin-top: 10px; margin-left: 0px; color: #000000;
|
5609 |
+
background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
|
5610 |
+
.title {
|
5611 |
+
font-family: arial; font-size: 26px; color: #ffffff;
|
5612 |
+
background-color: #999999; width: 100%;
|
5613 |
+
margin-left: 0px; margin-right: 0px;
|
5614 |
+
padding-top: 10px; padding-bottom: 10px;}
|
5615 |
+
.hidden {
|
5616 |
+
position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
|
5617 |
+
font-family: arial; overflow: hidden; width: 600;
|
5618 |
+
padding: 20px; font-size: 10px; background-color: #999999;
|
5619 |
+
layer-background-color:#FFFFFF; }
|
5620 |
+
a,a:active { color: charcoal; font-weight: bold; }
|
5621 |
+
a:visited { color: #666666; font-weight: bold; }
|
5622 |
+
a:hover { color: cc3300; font-weight: bold; }
|
5623 |
+
</style>
|
5624 |
+
<script language="JavaScript" type="text/javascript">
|
5625 |
+
<!--
|
5626 |
+
// POP-UP CAPTIONS...
|
5627 |
+
function lib_bwcheck(){ //Browsercheck (needed)
|
5628 |
+
this.ver=navigator.appVersion
|
5629 |
+
this.agent=navigator.userAgent
|
5630 |
+
this.dom=document.getElementById?1:0
|
5631 |
+
this.opera5=this.agent.indexOf("Opera 5")>-1
|
5632 |
+
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
|
5633 |
+
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
|
5634 |
+
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
|
5635 |
+
this.ie=this.ie4||this.ie5||this.ie6
|
5636 |
+
this.mac=this.agent.indexOf("Mac")>-1
|
5637 |
+
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
|
5638 |
+
this.ns4=(document.layers && !this.dom)?1:0;
|
5639 |
+
this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
|
5640 |
+
return this
|
5641 |
+
}
|
5642 |
+
var bw = new lib_bwcheck()
|
5643 |
+
//Makes crossbrowser object.
|
5644 |
+
function makeObj(obj){
|
5645 |
+
this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
|
5646 |
+
if(!this.evnt) return false
|
5647 |
+
this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
|
5648 |
+
this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
|
5649 |
+
this.writeIt=b_writeIt;
|
5650 |
+
return this
|
5651 |
+
}
|
5652 |
+
// A unit of measure that will be added when setting the position of a layer.
|
5653 |
+
//var px = bw.ns4||window.opera?"":"px";
|
5654 |
+
function b_writeIt(text){
|
5655 |
+
if (bw.ns4){this.wref.write(text);this.wref.close()}
|
5656 |
+
else this.wref.innerHTML = text
|
5657 |
+
}
|
5658 |
+
//Shows the messages
|
5659 |
+
var oDesc;
|
5660 |
+
function popup(divid){
|
5661 |
+
if(oDesc = new makeObj(divid)){
|
5662 |
+
oDesc.css.visibility = "visible"
|
5663 |
+
}
|
5664 |
+
}
|
5665 |
+
function popout(){ // Hides message
|
5666 |
+
if(oDesc) oDesc.css.visibility = "hidden"
|
5667 |
+
}
|
5668 |
+
//-->
|
5669 |
+
</script>
|
5670 |
+
</head>
|
5671 |
+
<body>
|
5672 |
+
<div class=content>
|
5673 |
+
<br><br>
|
5674 |
+
<div class=title>' . $this->serviceName . '</div>
|
5675 |
+
<div class=nav>
|
5676 |
+
<p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
|
5677 |
+
Click on an operation name to view it's details.</p>
|
5678 |
+
<ul>';
|
5679 |
+
foreach ( $this->getOperations() as $op => $data ) {
|
5680 |
+
$b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
|
5681 |
+
// create hidden div
|
5682 |
+
$b .= "<div id='$op' class='hidden'>
|
5683 |
+
<a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
|
5684 |
+
foreach ( $data as $donnie => $marie ) { // loop through opdata
|
5685 |
+
if ( $donnie == 'input' || $donnie == 'output' ) { // show input/output data
|
5686 |
+
$b .= "<font color='white'>" . ucfirst( $donnie ) . ':</font><br>';
|
5687 |
+
foreach ( $marie as $captain => $tenille ) { // loop through data
|
5688 |
+
if ( $captain == 'parts' ) { // loop thru parts
|
5689 |
+
$b .= " $captain:<br>";
|
5690 |
+
//if(is_array($tenille)){
|
5691 |
+
foreach ( $tenille as $joanie => $chachi ) {
|
5692 |
+
$b .= " $joanie: $chachi<br>";
|
5693 |
+
}
|
5694 |
+
//}
|
5695 |
+
} else {
|
5696 |
+
$b .= " $captain: $tenille<br>";
|
5697 |
+
}
|
5698 |
+
}
|
5699 |
+
} else {
|
5700 |
+
$b .= "<font color='white'>" . ucfirst( $donnie ) . ":</font> $marie<br>";
|
5701 |
+
}
|
5702 |
+
}
|
5703 |
+
$b .= '</div>';
|
5704 |
+
}
|
5705 |
+
$b .= '
|
5706 |
+
<ul>
|
5707 |
+
</div>
|
5708 |
+
</div></body></html>';
|
5709 |
+
|
5710 |
+
return $b;
|
5711 |
+
}
|
5712 |
+
|
5713 |
+
/**
|
5714 |
+
* serialize the parsed wsdl
|
5715 |
+
*
|
5716 |
+
* @param mixed $debug whether to put debug=1 in endpoint URL
|
5717 |
+
*
|
5718 |
+
* @return string serialization of WSDL
|
5719 |
+
* @access public
|
5720 |
+
*/
|
5721 |
+
function serialize( $debug = 0 ) {
|
5722 |
+
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
|
5723 |
+
$xml .= "\n<definitions";
|
5724 |
+
foreach ( $this->namespaces as $k => $v ) {
|
5725 |
+
$xml .= " xmlns:$k=\"$v\"";
|
5726 |
+
}
|
5727 |
+
// 10.9.02 - add poulter fix for wsdl and tns declarations
|
5728 |
+
if ( isset( $this->namespaces['wsdl'] ) ) {
|
5729 |
+
$xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
|
5730 |
+
}
|
5731 |
+
if ( isset( $this->namespaces['tns'] ) ) {
|
5732 |
+
$xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
|
5733 |
+
}
|
5734 |
+
$xml .= '>';
|
5735 |
+
// imports
|
5736 |
+
if ( sizeof( $this->import ) > 0 ) {
|
5737 |
+
foreach ( $this->import as $ns => $list ) {
|
5738 |
+
foreach ( $list as $ii ) {
|
5739 |
+
if ( $ii['location'] != '' ) {
|
5740 |
+
$xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
|
5741 |
+
} else {
|
5742 |
+
$xml .= '<import namespace="' . $ns . '" />';
|
5743 |
+
}
|
5744 |
+
}
|
5745 |
+
}
|
5746 |
+
}
|
5747 |
+
// types
|
5748 |
+
if ( count( $this->schemas ) >= 1 ) {
|
5749 |
+
$xml .= "\n<types>\n";
|
5750 |
+
foreach ( $this->schemas as $ns => $list ) {
|
5751 |
+
foreach ( $list as $xs ) {
|
5752 |
+
$xml .= $xs->serializeSchema();
|
5753 |
+
}
|
5754 |
+
}
|
5755 |
+
$xml .= '</types>';
|
5756 |
+
}
|
5757 |
+
// messages
|
5758 |
+
if ( count( $this->messages ) >= 1 ) {
|
5759 |
+
foreach ( $this->messages as $msgName => $msgParts ) {
|
5760 |
+
$xml .= "\n<message name=\"" . $msgName . '">';
|
5761 |
+
if ( is_array( $msgParts ) ) {
|
5762 |
+
foreach ( $msgParts as $partName => $partType ) {
|
5763 |
+
// print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
|
5764 |
+
if ( strpos( $partType, ':' ) ) {
|
5765 |
+
$typePrefix = $this->getPrefixFromNamespace( $this->getPrefix( $partType ) );
|
5766 |
+
} elseif ( isset( $this->typemap[ $this->namespaces['xsd'] ][ $partType ] ) ) {
|
5767 |
+
// print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
|
5768 |
+
$typePrefix = 'xsd';
|
5769 |
+
} else {
|
5770 |
+
foreach ( $this->typemap as $ns => $types ) {
|
5771 |
+
if ( isset( $types[ $partType ] ) ) {
|
5772 |
+
$typePrefix = $this->getPrefixFromNamespace( $ns );
|
5773 |
+
}
|
5774 |
+
}
|
5775 |
+
if ( ! isset( $typePrefix ) ) {
|
5776 |
+
die( "$partType has no namespace!" );
|
5777 |
+
}
|
5778 |
+
}
|
5779 |
+
$ns = $this->getNamespaceFromPrefix( $typePrefix );
|
5780 |
+
$localPart = $this->getLocalPart( $partType );
|
5781 |
+
$typeDef = $this->getTypeDef( $localPart, $ns );
|
5782 |
+
if ( $typeDef['typeClass'] == 'element' ) {
|
5783 |
+
$elementortype = 'element';
|
5784 |
+
if ( substr( $localPart, - 1 ) == '^' ) {
|
5785 |
+
$localPart = substr( $localPart, 0, - 1 );
|
5786 |
+
}
|
5787 |
+
} else {
|
5788 |
+
$elementortype = 'type';
|
5789 |
+
}
|
5790 |
+
$xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
|
5791 |
+
}
|
5792 |
+
}
|
5793 |
+
$xml .= '</message>';
|
5794 |
+
}
|
5795 |
+
}
|
5796 |
+
// bindings & porttypes
|
5797 |
+
if ( count( $this->bindings ) >= 1 ) {
|
5798 |
+
$binding_xml = '';
|
5799 |
+
$portType_xml = '';
|
5800 |
+
foreach ( $this->bindings as $bindingName => $attrs ) {
|
5801 |
+
$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
|
5802 |
+
$binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
|
5803 |
+
$portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
|
5804 |
+
foreach ( $attrs['operations'] as $opName => $opParts ) {
|
5805 |
+
$binding_xml .= "\n" . ' <operation name="' . $opName . '">';
|
5806 |
+
$binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
|
5807 |
+
if ( isset( $opParts['input']['encodingStyle'] ) && $opParts['input']['encodingStyle'] != '' ) {
|
5808 |
+
$enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
|
5809 |
+
} else {
|
5810 |
+
$enc_style = '';
|
5811 |
+
}
|
5812 |
+
$binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
|
5813 |
+
if ( isset( $opParts['output']['encodingStyle'] ) && $opParts['output']['encodingStyle'] != '' ) {
|
5814 |
+
$enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
|
5815 |
+
} else {
|
5816 |
+
$enc_style = '';
|
5817 |
+
}
|
5818 |
+
$binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
|
5819 |
+
$binding_xml .= "\n" . ' </operation>';
|
5820 |
+
$portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
|
5821 |
+
if ( isset( $opParts['parameterOrder'] ) ) {
|
5822 |
+
$portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
|
5823 |
+
}
|
5824 |
+
$portType_xml .= '>';
|
5825 |
+
if ( isset( $opParts['documentation'] ) && $opParts['documentation'] != '' ) {
|
5826 |
+
$portType_xml .= "\n" . ' <documentation>' . htmlspecialchars( $opParts['documentation'] ) . '</documentation>';
|
5827 |
+
}
|
5828 |
+
$portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
|
5829 |
+
$portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
|
5830 |
+
$portType_xml .= "\n" . ' </operation>';
|
5831 |
+
}
|
5832 |
+
$portType_xml .= "\n" . '</portType>';
|
5833 |
+
$binding_xml .= "\n" . '</binding>';
|
5834 |
+
}
|
5835 |
+
$xml .= $portType_xml . $binding_xml;
|
5836 |
+
}
|
5837 |
+
// services
|
5838 |
+
$xml .= "\n<service name=\"" . $this->serviceName . '">';
|
5839 |
+
if ( count( $this->ports ) >= 1 ) {
|
5840 |
+
foreach ( $this->ports as $pName => $attrs ) {
|
5841 |
+
$xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
|
5842 |
+
$xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ( $debug ? '?debug=1' : '' ) . '"/>';
|
5843 |
+
$xml .= "\n" . ' </port>';
|
5844 |
+
}
|
5845 |
+
}
|
5846 |
+
$xml .= "\n" . '</service>';
|
5847 |
+
|
5848 |
+
return $xml . "\n</definitions>";
|
5849 |
+
}
|
5850 |
+
|
5851 |
+
/**
|
5852 |
+
* determine whether a set of parameters are unwrapped
|
5853 |
+
* when they are expect to be wrapped, Microsoft-style.
|
5854 |
+
*
|
5855 |
+
* @param string $type the type (element name) of the wrapper
|
5856 |
+
* @param array $parameters the parameter values for the SOAP call
|
5857 |
+
*
|
5858 |
+
* @return boolean whether they parameters are unwrapped (and should be wrapped)
|
5859 |
+
* @access private
|
5860 |
+
*/
|
5861 |
+
function parametersMatchWrapped( $type, &$parameters ) {
|
5862 |
+
$this->debug( "in parametersMatchWrapped type=$type, parameters=" );
|
5863 |
+
$this->appendDebug( $this->varDump( $parameters ) );
|
5864 |
+
|
5865 |
+
// split type into namespace:unqualified-type
|
5866 |
+
if ( strpos( $type, ':' ) ) {
|
5867 |
+
$uqType = substr( $type, strrpos( $type, ':' ) + 1 );
|
5868 |
+
$ns = substr( $type, 0, strrpos( $type, ':' ) );
|
5869 |
+
$this->debug( "in parametersMatchWrapped: got a prefixed type: $uqType, $ns" );
|
5870 |
+
if ( $this->getNamespaceFromPrefix( $ns ) ) {
|
5871 |
+
$ns = $this->getNamespaceFromPrefix( $ns );
|
5872 |
+
$this->debug( "in parametersMatchWrapped: expanded prefixed type: $uqType, $ns" );
|
5873 |
+
}
|
5874 |
+
} else {
|
5875 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
5876 |
+
// set to XSD if the type matches?
|
5877 |
+
$this->debug( "in parametersMatchWrapped: No namespace for type $type" );
|
5878 |
+
$ns = '';
|
5879 |
+
$uqType = $type;
|
5880 |
+
}
|
5881 |
+
|
5882 |
+
// get the type information
|
5883 |
+
if ( ! $typeDef = $this->getTypeDef( $uqType, $ns ) ) {
|
5884 |
+
$this->debug( "in parametersMatchWrapped: $type ($uqType) is not a supported type." );
|
5885 |
+
|
5886 |
+
return false;
|
5887 |
+
}
|
5888 |
+
$this->debug( "in parametersMatchWrapped: found typeDef=" );
|
5889 |
+
$this->appendDebug( $this->varDump( $typeDef ) );
|
5890 |
+
if ( substr( $uqType, - 1 ) == '^' ) {
|
5891 |
+
$uqType = substr( $uqType, 0, - 1 );
|
5892 |
+
}
|
5893 |
+
$phpType = $typeDef['phpType'];
|
5894 |
+
$arrayType = ( isset( $typeDef['arrayType'] ) ? $typeDef['arrayType'] : '' );
|
5895 |
+
$this->debug( "in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType" );
|
5896 |
+
|
5897 |
+
// we expect a complexType or element of complexType
|
5898 |
+
if ( $phpType != 'struct' ) {
|
5899 |
+
$this->debug( "in parametersMatchWrapped: not a struct" );
|
5900 |
+
|
5901 |
+
return false;
|
5902 |
+
}
|
5903 |
+
|
5904 |
+
// see whether the parameter names match the elements
|
5905 |
+
if ( isset( $typeDef['elements'] ) && is_array( $typeDef['elements'] ) ) {
|
5906 |
+
$elements = 0;
|
5907 |
+
$matches = 0;
|
5908 |
+
foreach ( $typeDef['elements'] as $name => $attrs ) {
|
5909 |
+
if ( isset( $parameters[ $name ] ) ) {
|
5910 |
+
$this->debug( "in parametersMatchWrapped: have parameter named $name" );
|
5911 |
+
$matches ++;
|
5912 |
+
} else {
|
5913 |
+
$this->debug( "in parametersMatchWrapped: do not have parameter named $name" );
|
5914 |
+
}
|
5915 |
+
$elements ++;
|
5916 |
+
}
|
5917 |
+
|
5918 |
+
$this->debug( "in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names" );
|
5919 |
+
if ( $matches == 0 ) {
|
5920 |
+
return false;
|
5921 |
+
}
|
5922 |
+
|
5923 |
+
return true;
|
5924 |
+
}
|
5925 |
+
|
5926 |
+
// since there are no elements for the type, if the user passed no
|
5927 |
+
// parameters, the parameters match wrapped.
|
5928 |
+
$this->debug( "in parametersMatchWrapped: no elements type $ns:$uqType" );
|
5929 |
+
|
5930 |
+
return count( $parameters ) == 0;
|
5931 |
+
}
|
5932 |
+
|
5933 |
+
/**
|
5934 |
+
* serialize PHP values according to a WSDL message definition
|
5935 |
+
* contrary to the method name, this is not limited to RPC
|
5936 |
+
*
|
5937 |
+
* TODO
|
5938 |
+
* - multi-ref serialization
|
5939 |
+
* - validate PHP values against type definitions, return errors if invalid
|
5940 |
+
*
|
5941 |
+
* @param string $operation operation name
|
5942 |
+
* @param string $direction (input|output)
|
5943 |
+
* @param mixed $parameters parameter value(s)
|
5944 |
+
* @param string $bindingType (soap|soap12)
|
5945 |
+
*
|
5946 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
5947 |
+
* @access public
|
5948 |
+
*/
|
5949 |
+
function serializeRPCParameters( $operation, $direction, $parameters, $bindingType = 'soap' ) {
|
5950 |
+
$this->debug( "in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType" );
|
5951 |
+
$this->appendDebug( 'parameters=' . $this->varDump( $parameters ) );
|
5952 |
+
|
5953 |
+
if ( $direction != 'input' && $direction != 'output' ) {
|
5954 |
+
$this->debug( 'The value of the \$direction argument needs to be either "input" or "output"' );
|
5955 |
+
$this->setError( 'The value of the \$direction argument needs to be either "input" or "output"' );
|
5956 |
+
|
5957 |
+
return false;
|
5958 |
+
}
|
5959 |
+
if ( ! $opData = $this->getOperationData( $operation, $bindingType ) ) {
|
5960 |
+
$this->debug( 'Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType );
|
5961 |
+
$this->setError( 'Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType );
|
5962 |
+
|
5963 |
+
return false;
|
5964 |
+
}
|
5965 |
+
$this->debug( 'in serializeRPCParameters: opData:' );
|
5966 |
+
$this->appendDebug( $this->varDump( $opData ) );
|
5967 |
+
|
5968 |
+
// Get encoding style for output and set to current
|
5969 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
5970 |
+
if ( ( $direction == 'input' ) && isset( $opData['output']['encodingStyle'] ) && ( $opData['output']['encodingStyle'] != $encodingStyle ) ) {
|
5971 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
5972 |
+
$enc_style = $encodingStyle;
|
5973 |
+
}
|
5974 |
+
|
5975 |
+
// set input params
|
5976 |
+
$xml = '';
|
5977 |
+
if ( isset( $opData[ $direction ]['parts'] ) && sizeof( $opData[ $direction ]['parts'] ) > 0 ) {
|
5978 |
+
$parts = &$opData[ $direction ]['parts'];
|
5979 |
+
$part_count = sizeof( $parts );
|
5980 |
+
$style = $opData['style'];
|
5981 |
+
$use = $opData[ $direction ]['use'];
|
5982 |
+
$this->debug( "have $part_count part(s) to serialize using $style/$use" );
|
5983 |
+
if ( is_array( $parameters ) ) {
|
5984 |
+
$parametersArrayType = $this->isArraySimpleOrStruct( $parameters );
|
5985 |
+
$parameter_count = count( $parameters );
|
5986 |
+
$this->debug( "have $parameter_count parameter(s) provided as $parametersArrayType to serialize" );
|
5987 |
+
// check for Microsoft-style wrapped parameters
|
5988 |
+
if ( $style == 'document' && $use == 'literal' && $part_count == 1 && isset( $parts['parameters'] ) ) {
|
5989 |
+
$this->debug( 'check whether the caller has wrapped the parameters' );
|
5990 |
+
if ( $direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1 ) {
|
5991 |
+
// TODO: consider checking here for double-wrapping, when
|
5992 |
+
// service function wraps, then NuSOAP wraps again
|
5993 |
+
$this->debug( "change simple array to associative with 'parameters' element" );
|
5994 |
+
$parameters['parameters'] = $parameters[0];
|
5995 |
+
unset( $parameters[0] );
|
5996 |
+
}
|
5997 |
+
if ( ( $parametersArrayType == 'arrayStruct' || $parameter_count == 0 ) && ! isset( $parameters['parameters'] ) ) {
|
5998 |
+
$this->debug( 'check whether caller\'s parameters match the wrapped ones' );
|
5999 |
+
if ( $this->parametersMatchWrapped( $parts['parameters'], $parameters ) ) {
|
6000 |
+
$this->debug( 'wrap the parameters for the caller' );
|
6001 |
+
$parameters = array( 'parameters' => $parameters );
|
6002 |
+
$parameter_count = 1;
|
6003 |
+
}
|
6004 |
+
}
|
6005 |
+
}
|
6006 |
+
foreach ( $parts as $name => $type ) {
|
6007 |
+
$this->debug( "serializing part $name of type $type" );
|
6008 |
+
// Track encoding style
|
6009 |
+
if ( isset( $opData[ $direction ]['encodingStyle'] ) && $encodingStyle != $opData[ $direction ]['encodingStyle'] ) {
|
6010 |
+
$encodingStyle = $opData[ $direction ]['encodingStyle'];
|
6011 |
+
$enc_style = $encodingStyle;
|
6012 |
+
} else {
|
6013 |
+
$enc_style = false;
|
6014 |
+
}
|
6015 |
+
// NOTE: add error handling here
|
6016 |
+
// if serializeType returns false, then catch global error and fault
|
6017 |
+
if ( $parametersArrayType == 'arraySimple' ) {
|
6018 |
+
$p = array_shift( $parameters );
|
6019 |
+
$this->debug( 'calling serializeType w/indexed param' );
|
6020 |
+
$xml .= $this->serializeType( $name, $type, $p, $use, $enc_style );
|
6021 |
+
} elseif ( isset( $parameters[ $name ] ) ) {
|
6022 |
+
$this->debug( 'calling serializeType w/named param' );
|
6023 |
+
$xml .= $this->serializeType( $name, $type, $parameters[ $name ], $use, $enc_style );
|
6024 |
+
} else {
|
6025 |
+
// TODO: only send nillable
|
6026 |
+
$this->debug( 'calling serializeType w/null param' );
|
6027 |
+
$xml .= $this->serializeType( $name, $type, null, $use, $enc_style );
|
6028 |
+
}
|
6029 |
+
}
|
6030 |
+
} else {
|
6031 |
+
$this->debug( 'no parameters passed.' );
|
6032 |
+
}
|
6033 |
+
}
|
6034 |
+
$this->debug( "serializeRPCParameters returning: $xml" );
|
6035 |
+
|
6036 |
+
return $xml;
|
6037 |
+
}
|
6038 |
+
|
6039 |
+
/**
|
6040 |
+
* serialize a PHP value according to a WSDL message definition
|
6041 |
+
*
|
6042 |
+
* TODO
|
6043 |
+
* - multi-ref serialization
|
6044 |
+
* - validate PHP values against type definitions, return errors if invalid
|
6045 |
+
*
|
6046 |
+
* @param string $operation operation name
|
6047 |
+
* @param string $direction (input|output)
|
6048 |
+
* @param mixed $parameters parameter value(s)
|
6049 |
+
*
|
6050 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
6051 |
+
* @access public
|
6052 |
+
* @deprecated
|
6053 |
+
*/
|
6054 |
+
function serializeParameters( $operation, $direction, $parameters ) {
|
6055 |
+
$this->debug( "in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion" );
|
6056 |
+
$this->appendDebug( 'parameters=' . $this->varDump( $parameters ) );
|
6057 |
+
|
6058 |
+
if ( $direction != 'input' && $direction != 'output' ) {
|
6059 |
+
$this->debug( 'The value of the \$direction argument needs to be either "input" or "output"' );
|
6060 |
+
$this->setError( 'The value of the \$direction argument needs to be either "input" or "output"' );
|
6061 |
+
|
6062 |
+
return false;
|
6063 |
+
}
|
6064 |
+
if ( ! $opData = $this->getOperationData( $operation ) ) {
|
6065 |
+
$this->debug( 'Unable to retrieve WSDL data for operation: ' . $operation );
|
6066 |
+
$this->setError( 'Unable to retrieve WSDL data for operation: ' . $operation );
|
6067 |
+
|
6068 |
+
return false;
|
6069 |
+
}
|
6070 |
+
$this->debug( 'opData:' );
|
6071 |
+
$this->appendDebug( $this->varDump( $opData ) );
|
6072 |
+
|
6073 |
+
// Get encoding style for output and set to current
|
6074 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
6075 |
+
if ( ( $direction == 'input' ) && isset( $opData['output']['encodingStyle'] ) && ( $opData['output']['encodingStyle'] != $encodingStyle ) ) {
|
6076 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
6077 |
+
$enc_style = $encodingStyle;
|
6078 |
+
}
|
6079 |
+
|
6080 |
+
// set input params
|
6081 |
+
$xml = '';
|
6082 |
+
if ( isset( $opData[ $direction ]['parts'] ) && sizeof( $opData[ $direction ]['parts'] ) > 0 ) {
|
6083 |
+
|
6084 |
+
$use = $opData[ $direction ]['use'];
|
6085 |
+
$this->debug( "use=$use" );
|
6086 |
+
$this->debug( 'got ' . count( $opData[ $direction ]['parts'] ) . ' part(s)' );
|
6087 |
+
if ( is_array( $parameters ) ) {
|
6088 |
+
$parametersArrayType = $this->isArraySimpleOrStruct( $parameters );
|
6089 |
+
$this->debug( 'have ' . $parametersArrayType . ' parameters' );
|
6090 |
+
foreach ( $opData[ $direction ]['parts'] as $name => $type ) {
|
6091 |
+
$this->debug( 'serializing part "' . $name . '" of type "' . $type . '"' );
|
6092 |
+
// Track encoding style
|
6093 |
+
if ( isset( $opData[ $direction ]['encodingStyle'] ) && $encodingStyle != $opData[ $direction ]['encodingStyle'] ) {
|
6094 |
+
$encodingStyle = $opData[ $direction ]['encodingStyle'];
|
6095 |
+
$enc_style = $encodingStyle;
|
6096 |
+
} else {
|
6097 |
+
$enc_style = false;
|
6098 |
+
}
|
6099 |
+
// NOTE: add error handling here
|
6100 |
+
// if serializeType returns false, then catch global error and fault
|
6101 |
+
if ( $parametersArrayType == 'arraySimple' ) {
|
6102 |
+
$p = array_shift( $parameters );
|
6103 |
+
$this->debug( 'calling serializeType w/indexed param' );
|
6104 |
+
$xml .= $this->serializeType( $name, $type, $p, $use, $enc_style );
|
6105 |
+
} elseif ( isset( $parameters[ $name ] ) ) {
|
6106 |
+
$this->debug( 'calling serializeType w/named param' );
|
6107 |
+
$xml .= $this->serializeType( $name, $type, $parameters[ $name ], $use, $enc_style );
|
6108 |
+
} else {
|
6109 |
+
// TODO: only send nillable
|
6110 |
+
$this->debug( 'calling serializeType w/null param' );
|
6111 |
+
$xml .= $this->serializeType( $name, $type, null, $use, $enc_style );
|
6112 |
+
}
|
6113 |
+
}
|
6114 |
+
} else {
|
6115 |
+
$this->debug( 'no parameters passed.' );
|
6116 |
+
}
|
6117 |
+
}
|
6118 |
+
$this->debug( "serializeParameters returning: $xml" );
|
6119 |
+
|
6120 |
+
return $xml;
|
6121 |
+
}
|
6122 |
+
|
6123 |
+
/**
|
6124 |
+
* serializes a PHP value according a given type definition
|
6125 |
+
*
|
6126 |
+
* @param string $name name of value (part or element)
|
6127 |
+
* @param string $type XML schema type of value (type or element)
|
6128 |
+
* @param mixed $value a native PHP value (parameter value)
|
6129 |
+
* @param string $use use for part (encoded|literal)
|
6130 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
6131 |
+
* @param boolean $unqualified a kludge for what should be XML namespace form handling
|
6132 |
+
*
|
6133 |
+
* @return string value serialized as an XML string
|
6134 |
+
* @access private
|
6135 |
+
*/
|
6136 |
+
function serializeType( $name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false ) {
|
6137 |
+
$this->debug( "in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ( $unqualified ? "unqualified" : "qualified" ) );
|
6138 |
+
$this->appendDebug( "value=" . $this->varDump( $value ) );
|
6139 |
+
if ( $use == 'encoded' && $encodingStyle ) {
|
6140 |
+
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
|
6141 |
+
}
|
6142 |
+
|
6143 |
+
// if a soapval has been supplied, let its type override the WSDL
|
6144 |
+
if ( is_object( $value ) && get_class( $value ) == 'soapval' ) {
|
6145 |
+
if ( $value->type_ns ) {
|
6146 |
+
$type = $value->type_ns . ':' . $value->type;
|
6147 |
+
$forceType = true;
|
6148 |
+
$this->debug( "in serializeType: soapval overrides type to $type" );
|
6149 |
+
} elseif ( $value->type ) {
|
6150 |
+
$type = $value->type;
|
6151 |
+
$forceType = true;
|
6152 |
+
$this->debug( "in serializeType: soapval overrides type to $type" );
|
6153 |
+
} else {
|
6154 |
+
$forceType = false;
|
6155 |
+
$this->debug( "in serializeType: soapval does not override type" );
|
6156 |
+
}
|
6157 |
+
$attrs = $value->attributes;
|
6158 |
+
$value = $value->value;
|
6159 |
+
$this->debug( "in serializeType: soapval overrides value to $value" );
|
6160 |
+
if ( $attrs ) {
|
6161 |
+
if ( ! is_array( $value ) ) {
|
6162 |
+
$value['!'] = $value;
|
6163 |
+
}
|
6164 |
+
foreach ( $attrs as $n => $v ) {
|
6165 |
+
$value[ '!' . $n ] = $v;
|
6166 |
+
}
|
6167 |
+
$this->debug( "in serializeType: soapval provides attributes" );
|
6168 |
+
}
|
6169 |
+
} else {
|
6170 |
+
$forceType = false;
|
6171 |
+
}
|
6172 |
+
|
6173 |
+
$xml = '';
|
6174 |
+
if ( strpos( $type, ':' ) ) {
|
6175 |
+
$uqType = substr( $type, strrpos( $type, ':' ) + 1 );
|
6176 |
+
$ns = substr( $type, 0, strrpos( $type, ':' ) );
|
6177 |
+
$this->debug( "in serializeType: got a prefixed type: $uqType, $ns" );
|
6178 |
+
if ( $this->getNamespaceFromPrefix( $ns ) ) {
|
6179 |
+
$ns = $this->getNamespaceFromPrefix( $ns );
|
6180 |
+
$this->debug( "in serializeType: expanded prefixed type: $uqType, $ns" );
|
6181 |
+
}
|
6182 |
+
|
6183 |
+
if ( $ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/' ) {
|
6184 |
+
$this->debug( 'in serializeType: type namespace indicates XML Schema or SOAP Encoding type' );
|
6185 |
+
if ( $unqualified && $use == 'literal' ) {
|
6186 |
+
$elementNS = " xmlns=\"\"";
|
6187 |
+
} else {
|
6188 |
+
$elementNS = '';
|
6189 |
+
}
|
6190 |
+
if ( is_null( $value ) ) {
|
6191 |
+
if ( $use == 'literal' ) {
|
6192 |
+
// TODO: depends on minOccurs
|
6193 |
+
$xml = "<$name$elementNS/>";
|
6194 |
+
} else {
|
6195 |
+
// TODO: depends on nillable, which should be checked before calling this method
|
6196 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\"/>";
|
6197 |
+
}
|
6198 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6199 |
+
|
6200 |
+
return $xml;
|
6201 |
+
}
|
6202 |
+
if ( $uqType == 'Array' ) {
|
6203 |
+
// JBoss/Axis does this sometimes
|
6204 |
+
return $this->serialize_val( $value, $name, false, false, false, false, $use );
|
6205 |
+
}
|
6206 |
+
if ( $uqType == 'boolean' ) {
|
6207 |
+
if ( ( is_string( $value ) && $value == 'false' ) || ( ! $value ) ) {
|
6208 |
+
$value = 'false';
|
6209 |
+
} else {
|
6210 |
+
$value = 'true';
|
6211 |
+
}
|
6212 |
+
}
|
6213 |
+
if ( $uqType == 'string' && gettype( $value ) == 'string' ) {
|
6214 |
+
$value = $this->expandEntities( $value );
|
6215 |
+
}
|
6216 |
+
if ( ( $uqType == 'long' || $uqType == 'unsignedLong' ) && gettype( $value ) == 'double' ) {
|
6217 |
+
$value = sprintf( "%.0lf", $value );
|
6218 |
+
}
|
6219 |
+
// it's a scalar
|
6220 |
+
// TODO: what about null/nil values?
|
6221 |
+
// check type isn't a custom type extending xmlschema namespace
|
6222 |
+
if ( ! $this->getTypeDef( $uqType, $ns ) ) {
|
6223 |
+
if ( $use == 'literal' ) {
|
6224 |
+
if ( $forceType ) {
|
6225 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\">$value</$name>";
|
6226 |
+
} else {
|
6227 |
+
$xml = "<$name$elementNS>$value</$name>";
|
6228 |
+
}
|
6229 |
+
} else {
|
6230 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\"$encodingStyle>$value</$name>";
|
6231 |
+
}
|
6232 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6233 |
+
|
6234 |
+
return $xml;
|
6235 |
+
}
|
6236 |
+
$this->debug( 'custom type extends XML Schema or SOAP Encoding namespace (yuck)' );
|
6237 |
+
} else if ( $ns == 'http://xml.apache.org/xml-soap' ) {
|
6238 |
+
$this->debug( 'in serializeType: appears to be Apache SOAP type' );
|
6239 |
+
if ( $uqType == 'Map' ) {
|
6240 |
+
$tt_prefix = $this->getPrefixFromNamespace( 'http://xml.apache.org/xml-soap' );
|
6241 |
+
if ( ! $tt_prefix ) {
|
6242 |
+
$this->debug( 'in serializeType: Add namespace for Apache SOAP type' );
|
6243 |
+
$tt_prefix = 'ns' . rand( 1000, 9999 );
|
6244 |
+
$this->namespaces[ $tt_prefix ] = 'http://xml.apache.org/xml-soap';
|
6245 |
+
// force this to be added to usedNamespaces
|
6246 |
+
$tt_prefix = $this->getPrefixFromNamespace( 'http://xml.apache.org/xml-soap' );
|
6247 |
+
}
|
6248 |
+
$contents = '';
|
6249 |
+
foreach ( $value as $k => $v ) {
|
6250 |
+
$this->debug( "serializing map element: key $k, value $v" );
|
6251 |
+
$contents .= '<item>';
|
6252 |
+
$contents .= $this->serialize_val( $k, 'key', false, false, false, false, $use );
|
6253 |
+
$contents .= $this->serialize_val( $v, 'value', false, false, false, false, $use );
|
6254 |
+
$contents .= '</item>';
|
6255 |
+
}
|
6256 |
+
if ( $use == 'literal' ) {
|
6257 |
+
if ( $forceType ) {
|
6258 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
|
6259 |
+
} else {
|
6260 |
+
$xml = "<$name>$contents</$name>";
|
6261 |
+
}
|
6262 |
+
} else {
|
6263 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
|
6264 |
+
}
|
6265 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6266 |
+
|
6267 |
+
return $xml;
|
6268 |
+
}
|
6269 |
+
$this->debug( 'in serializeType: Apache SOAP type, but only support Map' );
|
6270 |
+
}
|
6271 |
+
} else {
|
6272 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
6273 |
+
// set to XSD if the type matches?
|
6274 |
+
$this->debug( "in serializeType: No namespace for type $type" );
|
6275 |
+
$ns = '';
|
6276 |
+
$uqType = $type;
|
6277 |
+
}
|
6278 |
+
if ( ! $typeDef = $this->getTypeDef( $uqType, $ns ) ) {
|
6279 |
+
$this->setError( "$type ($uqType) is not a supported type." );
|
6280 |
+
$this->debug( "in serializeType: $type ($uqType) is not a supported type." );
|
6281 |
+
|
6282 |
+
return false;
|
6283 |
+
} else {
|
6284 |
+
$this->debug( "in serializeType: found typeDef" );
|
6285 |
+
$this->appendDebug( 'typeDef=' . $this->varDump( $typeDef ) );
|
6286 |
+
if ( substr( $uqType, - 1 ) == '^' ) {
|
6287 |
+
$uqType = substr( $uqType, 0, - 1 );
|
6288 |
+
}
|
6289 |
+
}
|
6290 |
+
if ( ! isset( $typeDef['phpType'] ) ) {
|
6291 |
+
$this->setError( "$type ($uqType) has no phpType." );
|
6292 |
+
$this->debug( "in serializeType: $type ($uqType) has no phpType." );
|
6293 |
+
|
6294 |
+
return false;
|
6295 |
+
}
|
6296 |
+
$phpType = $typeDef['phpType'];
|
6297 |
+
$this->debug( "in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . ( isset( $typeDef['arrayType'] ) ? $typeDef['arrayType'] : '' ) );
|
6298 |
+
// if php type == struct, map value to the <all> element names
|
6299 |
+
if ( $phpType == 'struct' ) {
|
6300 |
+
if ( isset( $typeDef['typeClass'] ) && $typeDef['typeClass'] == 'element' ) {
|
6301 |
+
$elementName = $uqType;
|
6302 |
+
if ( isset( $typeDef['form'] ) && ( $typeDef['form'] == 'qualified' ) ) {
|
6303 |
+
$elementNS = " xmlns=\"$ns\"";
|
6304 |
+
} else {
|
6305 |
+
$elementNS = " xmlns=\"\"";
|
6306 |
+
}
|
6307 |
+
} else {
|
6308 |
+
$elementName = $name;
|
6309 |
+
if ( $unqualified ) {
|
6310 |
+
$elementNS = " xmlns=\"\"";
|
6311 |
+
} else {
|
6312 |
+
$elementNS = '';
|
6313 |
+
}
|
6314 |
+
}
|
6315 |
+
if ( is_null( $value ) ) {
|
6316 |
+
if ( $use == 'literal' ) {
|
6317 |
+
// TODO: depends on minOccurs and nillable
|
6318 |
+
$xml = "<$elementName$elementNS/>";
|
6319 |
+
} else {
|
6320 |
+
$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\"/>";
|
6321 |
+
}
|
6322 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6323 |
+
|
6324 |
+
return $xml;
|
6325 |
+
}
|
6326 |
+
if ( is_object( $value ) ) {
|
6327 |
+
$value = get_object_vars( $value );
|
6328 |
+
}
|
6329 |
+
if ( is_array( $value ) ) {
|
6330 |
+
$elementAttrs = $this->serializeComplexTypeAttributes( $typeDef, $value, $ns, $uqType );
|
6331 |
+
if ( $use == 'literal' ) {
|
6332 |
+
if ( $forceType ) {
|
6333 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\">";
|
6334 |
+
} else {
|
6335 |
+
$xml = "<$elementName$elementNS$elementAttrs>";
|
6336 |
+
}
|
6337 |
+
} else {
|
6338 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\"$encodingStyle>";
|
6339 |
+
}
|
6340 |
+
|
6341 |
+
if ( isset( $typeDef['simpleContent'] ) && $typeDef['simpleContent'] == 'true' ) {
|
6342 |
+
if ( isset( $value['!'] ) ) {
|
6343 |
+
$xml .= $value['!'];
|
6344 |
+
$this->debug( "in serializeType: serialized simpleContent for type $type" );
|
6345 |
+
} else {
|
6346 |
+
$this->debug( "in serializeType: no simpleContent to serialize for type $type" );
|
6347 |
+
}
|
6348 |
+
} else {
|
6349 |
+
// complexContent
|
6350 |
+
$xml .= $this->serializeComplexTypeElements( $typeDef, $value, $ns, $uqType, $use, $encodingStyle );
|
6351 |
+
}
|
6352 |
+
$xml .= "</$elementName>";
|
6353 |
+
} else {
|
6354 |
+
$this->debug( "in serializeType: phpType is struct, but value is not an array" );
|
6355 |
+
$this->setError( "phpType is struct, but value is not an array: see debug output for details" );
|
6356 |
+
$xml = '';
|
6357 |
+
}
|
6358 |
+
} elseif ( $phpType == 'array' ) {
|
6359 |
+
if ( isset( $typeDef['form'] ) && ( $typeDef['form'] == 'qualified' ) ) {
|
6360 |
+
$elementNS = " xmlns=\"$ns\"";
|
6361 |
+
} else {
|
6362 |
+
if ( $unqualified ) {
|
6363 |
+
$elementNS = " xmlns=\"\"";
|
6364 |
+
} else {
|
6365 |
+
$elementNS = '';
|
6366 |
+
}
|
6367 |
+
}
|
6368 |
+
if ( is_null( $value ) ) {
|
6369 |
+
if ( $use == 'literal' ) {
|
6370 |
+
// TODO: depends on minOccurs
|
6371 |
+
$xml = "<$name$elementNS/>";
|
6372 |
+
} else {
|
6373 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
|
6374 |
+
$this->getPrefixFromNamespace( 'http://schemas.xmlsoap.org/soap/encoding/' ) .
|
6375 |
+
":Array\" " .
|
6376 |
+
$this->getPrefixFromNamespace( 'http://schemas.xmlsoap.org/soap/encoding/' ) .
|
6377 |
+
':arrayType="' .
|
6378 |
+
$this->getPrefixFromNamespace( $this->getPrefix( $typeDef['arrayType'] ) ) .
|
6379 |
+
':' .
|
6380 |
+
$this->getLocalPart( $typeDef['arrayType'] ) . "[0]\"/>";
|
6381 |
+
}
|
6382 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6383 |
+
|
6384 |
+
return $xml;
|
6385 |
+
}
|
6386 |
+
if ( isset( $typeDef['multidimensional'] ) ) {
|
6387 |
+
$nv = array();
|
6388 |
+
foreach ( $value as $v ) {
|
6389 |
+
$cols = ',' . sizeof( $v );
|
6390 |
+
$nv = array_merge( $nv, $v );
|
6391 |
+
}
|
6392 |
+
$value = $nv;
|
6393 |
+
} else {
|
6394 |
+
$cols = '';
|
6395 |
+
}
|
6396 |
+
if ( is_array( $value ) && sizeof( $value ) >= 1 ) {
|
6397 |
+
$rows = sizeof( $value );
|
6398 |
+
$contents = '';
|
6399 |
+
foreach ( $value as $k => $v ) {
|
6400 |
+
$this->debug( "serializing array element: $k, $v of type: $typeDef[arrayType]" );
|
6401 |
+
//if (strpos($typeDef['arrayType'], ':') ) {
|
6402 |
+
if ( ! in_array( $typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'] ) ) {
|
6403 |
+
$contents .= $this->serializeType( 'item', $typeDef['arrayType'], $v, $use );
|
6404 |
+
} else {
|
6405 |
+
$contents .= $this->serialize_val( $v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use );
|
6406 |
+
}
|
6407 |
+
}
|
6408 |
+
} else {
|
6409 |
+
$rows = 0;
|
6410 |
+
$contents = null;
|
6411 |
+
}
|
6412 |
+
// TODO: for now, an empty value will be serialized as a zero element
|
6413 |
+
// array. Revisit this when coding the handling of null/nil values.
|
6414 |
+
if ( $use == 'literal' ) {
|
6415 |
+
$xml = "<$name$elementNS>"
|
6416 |
+
. $contents
|
6417 |
+
. "</$name>";
|
6418 |
+
} else {
|
6419 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace( 'http://schemas.xmlsoap.org/soap/encoding/' ) . ':Array" ' .
|
6420 |
+
$this->getPrefixFromNamespace( 'http://schemas.xmlsoap.org/soap/encoding/' )
|
6421 |
+
. ':arrayType="'
|
6422 |
+
. $this->getPrefixFromNamespace( $this->getPrefix( $typeDef['arrayType'] ) )
|
6423 |
+
. ":" . $this->getLocalPart( $typeDef['arrayType'] ) . "[$rows$cols]\">"
|
6424 |
+
. $contents
|
6425 |
+
. "</$name>";
|
6426 |
+
}
|
6427 |
+
} elseif ( $phpType == 'scalar' ) {
|
6428 |
+
if ( isset( $typeDef['form'] ) && ( $typeDef['form'] == 'qualified' ) ) {
|
6429 |
+
$elementNS = " xmlns=\"$ns\"";
|
6430 |
+
} else {
|
6431 |
+
if ( $unqualified ) {
|
6432 |
+
$elementNS = " xmlns=\"\"";
|
6433 |
+
} else {
|
6434 |
+
$elementNS = '';
|
6435 |
+
}
|
6436 |
+
}
|
6437 |
+
if ( $use == 'literal' ) {
|
6438 |
+
if ( $forceType ) {
|
6439 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\">$value</$name>";
|
6440 |
+
} else {
|
6441 |
+
$xml = "<$name$elementNS>$value</$name>";
|
6442 |
+
}
|
6443 |
+
} else {
|
6444 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace( $ns ) . ":$uqType\"$encodingStyle>$value</$name>";
|
6445 |
+
}
|
6446 |
+
}
|
6447 |
+
$this->debug( "in serializeType: returning: $xml" );
|
6448 |
+
|
6449 |
+
return $xml;
|
6450 |
+
}
|
6451 |
+
|
6452 |
+
/**
|
6453 |
+
* serializes the attributes for a complexType
|
6454 |
+
*
|
6455 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6456 |
+
* @param mixed $value a native PHP value (parameter value)
|
6457 |
+
* @param string $ns the namespace of the type
|
6458 |
+
* @param string $uqType the local part of the type
|
6459 |
+
*
|
6460 |
+
* @return string value serialized as an XML string
|
6461 |
+
* @access private
|
6462 |
+
*/
|
6463 |
+
function serializeComplexTypeAttributes( $typeDef, $value, $ns, $uqType ) {
|
6464 |
+
$this->debug( "serializeComplexTypeAttributes for XML Schema type $ns:$uqType" );
|
6465 |
+
$xml = '';
|
6466 |
+
if ( isset( $typeDef['extensionBase'] ) ) {
|
6467 |
+
$nsx = $this->getPrefix( $typeDef['extensionBase'] );
|
6468 |
+
$uqTypex = $this->getLocalPart( $typeDef['extensionBase'] );
|
6469 |
+
if ( $this->getNamespaceFromPrefix( $nsx ) ) {
|
6470 |
+
$nsx = $this->getNamespaceFromPrefix( $nsx );
|
6471 |
+
}
|
6472 |
+
if ( $typeDefx = $this->getTypeDef( $uqTypex, $nsx ) ) {
|
6473 |
+
$this->debug( "serialize attributes for extension base $nsx:$uqTypex" );
|
6474 |
+
$xml .= $this->serializeComplexTypeAttributes( $typeDefx, $value, $nsx, $uqTypex );
|
6475 |
+
} else {
|
6476 |
+
$this->debug( "extension base $nsx:$uqTypex is not a supported type" );
|
6477 |
+
}
|
6478 |
+
}
|
6479 |
+
if ( isset( $typeDef['attrs'] ) && is_array( $typeDef['attrs'] ) ) {
|
6480 |
+
$this->debug( "serialize attributes for XML Schema type $ns:$uqType" );
|
6481 |
+
if ( is_array( $value ) ) {
|
6482 |
+
$xvalue = $value;
|
6483 |
+
} elseif ( is_object( $value ) ) {
|
6484 |
+
$xvalue = get_object_vars( $value );
|
6485 |
+
} else {
|
6486 |
+
$this->debug( "value is neither an array nor an object for XML Schema type $ns:$uqType" );
|
6487 |
+
$xvalue = array();
|
6488 |
+
}
|
6489 |
+
foreach ( $typeDef['attrs'] as $aName => $attrs ) {
|
6490 |
+
if ( isset( $xvalue[ '!' . $aName ] ) ) {
|
6491 |
+
$xname = '!' . $aName;
|
6492 |
+
$this->debug( "value provided for attribute $aName with key $xname" );
|
6493 |
+
} elseif ( isset( $xvalue[ $aName ] ) ) {
|
6494 |
+
$xname = $aName;
|
6495 |
+
$this->debug( "value provided for attribute $aName with key $xname" );
|
6496 |
+
} elseif ( isset( $attrs['default'] ) ) {
|
6497 |
+
$xname = '!' . $aName;
|
6498 |
+
$xvalue[ $xname ] = $attrs['default'];
|
6499 |
+
$this->debug( 'use default value of ' . $xvalue[ $aName ] . ' for attribute ' . $aName );
|
6500 |
+
} else {
|
6501 |
+
$xname = '';
|
6502 |
+
$this->debug( "no value provided for attribute $aName" );
|
6503 |
+
}
|
6504 |
+
if ( $xname ) {
|
6505 |
+
$xml .= " $aName=\"" . $this->expandEntities( $xvalue[ $xname ] ) . "\"";
|
6506 |
+
}
|
6507 |
+
}
|
6508 |
+
} else {
|
6509 |
+
$this->debug( "no attributes to serialize for XML Schema type $ns:$uqType" );
|
6510 |
+
}
|
6511 |
+
|
6512 |
+
return $xml;
|
6513 |
+
}
|
6514 |
+
|
6515 |
+
/**
|
6516 |
+
* serializes the elements for a complexType
|
6517 |
+
*
|
6518 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6519 |
+
* @param mixed $value a native PHP value (parameter value)
|
6520 |
+
* @param string $ns the namespace of the type
|
6521 |
+
* @param string $uqType the local part of the type
|
6522 |
+
* @param string $use use for part (encoded|literal)
|
6523 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
6524 |
+
*
|
6525 |
+
* @return string value serialized as an XML string
|
6526 |
+
* @access private
|
6527 |
+
*/
|
6528 |
+
function serializeComplexTypeElements( $typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false ) {
|
6529 |
+
$this->debug( "in serializeComplexTypeElements for XML Schema type $ns:$uqType" );
|
6530 |
+
$xml = '';
|
6531 |
+
if ( isset( $typeDef['extensionBase'] ) ) {
|
6532 |
+
$nsx = $this->getPrefix( $typeDef['extensionBase'] );
|
6533 |
+
$uqTypex = $this->getLocalPart( $typeDef['extensionBase'] );
|
6534 |
+
if ( $this->getNamespaceFromPrefix( $nsx ) ) {
|
6535 |
+
$nsx = $this->getNamespaceFromPrefix( $nsx );
|
6536 |
+
}
|
6537 |
+
if ( $typeDefx = $this->getTypeDef( $uqTypex, $nsx ) ) {
|
6538 |
+
$this->debug( "serialize elements for extension base $nsx:$uqTypex" );
|
6539 |
+
$xml .= $this->serializeComplexTypeElements( $typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle );
|
6540 |
+
} else {
|
6541 |
+
$this->debug( "extension base $nsx:$uqTypex is not a supported type" );
|
6542 |
+
}
|
6543 |
+
}
|
6544 |
+
if ( isset( $typeDef['elements'] ) && is_array( $typeDef['elements'] ) ) {
|
6545 |
+
$this->debug( "in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType" );
|
6546 |
+
if ( is_array( $value ) ) {
|
6547 |
+
$xvalue = $value;
|
6548 |
+
} elseif ( is_object( $value ) ) {
|
6549 |
+
$xvalue = get_object_vars( $value );
|
6550 |
+
} else {
|
6551 |
+
$this->debug( "value is neither an array nor an object for XML Schema type $ns:$uqType" );
|
6552 |
+
$xvalue = array();
|
6553 |
+
}
|
6554 |
+
// toggle whether all elements are present - ideally should validate against schema
|
6555 |
+
if ( count( $typeDef['elements'] ) != count( $xvalue ) ) {
|
6556 |
+
$optionals = true;
|
6557 |
+
}
|
6558 |
+
foreach ( $typeDef['elements'] as $eName => $attrs ) {
|
6559 |
+
if ( ! isset( $xvalue[ $eName ] ) ) {
|
6560 |
+
if ( isset( $attrs['default'] ) ) {
|
6561 |
+
$xvalue[ $eName ] = $attrs['default'];
|
6562 |
+
$this->debug( 'use default value of ' . $xvalue[ $eName ] . ' for element ' . $eName );
|
6563 |
+
}
|
6564 |
+
}
|
6565 |
+
// if user took advantage of a minOccurs=0, then only serialize named parameters
|
6566 |
+
if ( isset( $optionals )
|
6567 |
+
&& ( ! isset( $xvalue[ $eName ] ) )
|
6568 |
+
&& ( ( ! isset( $attrs['nillable'] ) ) || $attrs['nillable'] != 'true' )
|
6569 |
+
) {
|
6570 |
+
if ( isset( $attrs['minOccurs'] ) && $attrs['minOccurs'] <> '0' ) {
|
6571 |
+
$this->debug( "apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs'] );
|
6572 |
+
}
|
6573 |
+
// do nothing
|
6574 |
+
$this->debug( "no value provided for complexType element $eName and element is not nillable, so serialize nothing" );
|
6575 |
+
} else {
|
6576 |
+
// get value
|
6577 |
+
if ( isset( $xvalue[ $eName ] ) ) {
|
6578 |
+
$v = $xvalue[ $eName ];
|
6579 |
+
} else {
|
6580 |
+
$v = null;
|
6581 |
+
}
|
6582 |
+
if ( isset( $attrs['form'] ) ) {
|
6583 |
+
$unqualified = ( $attrs['form'] == 'unqualified' );
|
6584 |
+
} else {
|
6585 |
+
$unqualified = false;
|
6586 |
+
}
|
6587 |
+
if ( isset( $attrs['maxOccurs'] ) && ( $attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1 ) && isset( $v ) && is_array( $v ) && $this->isArraySimpleOrStruct( $v ) == 'arraySimple' ) {
|
6588 |
+
$vv = $v;
|
6589 |
+
foreach ( $vv as $k => $v ) {
|
6590 |
+
if ( isset( $attrs['type'] ) || isset( $attrs['ref'] ) ) {
|
6591 |
+
// serialize schema-defined type
|
6592 |
+
$xml .= $this->serializeType( $eName, isset( $attrs['type'] ) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified );
|
6593 |
+
} else {
|
6594 |
+
// serialize generic type (can this ever really happen?)
|
6595 |
+
$this->debug( "calling serialize_val() for $v, $eName, false, false, false, false, $use" );
|
6596 |
+
$xml .= $this->serialize_val( $v, $eName, false, false, false, false, $use );
|
6597 |
+
}
|
6598 |
+
}
|
6599 |
+
} else {
|
6600 |
+
if ( is_null( $v ) && isset( $attrs['minOccurs'] ) && $attrs['minOccurs'] == '0' ) {
|
6601 |
+
// do nothing
|
6602 |
+
} elseif ( is_null( $v ) && isset( $attrs['nillable'] ) && $attrs['nillable'] == 'true' ) {
|
6603 |
+
// TODO: serialize a nil correctly, but for now serialize schema-defined type
|
6604 |
+
$xml .= $this->serializeType( $eName, isset( $attrs['type'] ) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified );
|
6605 |
+
} elseif ( isset( $attrs['type'] ) || isset( $attrs['ref'] ) ) {
|
6606 |
+
// serialize schema-defined type
|
6607 |
+
$xml .= $this->serializeType( $eName, isset( $attrs['type'] ) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified );
|
6608 |
+
} else {
|
6609 |
+
// serialize generic type (can this ever really happen?)
|
6610 |
+
$this->debug( "calling serialize_val() for $v, $eName, false, false, false, false, $use" );
|
6611 |
+
$xml .= $this->serialize_val( $v, $eName, false, false, false, false, $use );
|
6612 |
+
}
|
6613 |
+
}
|
6614 |
+
}
|
6615 |
+
}
|
6616 |
+
} else {
|
6617 |
+
$this->debug( "no elements to serialize for XML Schema type $ns:$uqType" );
|
6618 |
+
}
|
6619 |
+
|
6620 |
+
return $xml;
|
6621 |
+
}
|
6622 |
+
|
6623 |
+
/**
|
6624 |
+
* adds an XML Schema complex type to the WSDL types
|
6625 |
+
*
|
6626 |
+
* @param string $name
|
6627 |
+
* @param string $typeClass (complexType|simpleType|attribute)
|
6628 |
+
* @param string $phpType currently supported are array and struct (php assoc array)
|
6629 |
+
* @param string $compositor (all|sequence|choice)
|
6630 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6631 |
+
* @param array $elements e.g. array ( name => array(name=>'',type=>'') )
|
6632 |
+
* @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
|
6633 |
+
* @param string $arrayType as namespace:name (xsd:string)
|
6634 |
+
*
|
6635 |
+
* @see nusoap_xmlschema
|
6636 |
+
* @access public
|
6637 |
+
*/
|
6638 |
+
function addComplexType( $name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '' ) {
|
6639 |
+
if ( count( $elements ) > 0 ) {
|
6640 |
+
$eElements = array();
|
6641 |
+
foreach ( $elements as $n => $e ) {
|
6642 |
+
// expand each element
|
6643 |
+
$ee = array();
|
6644 |
+
foreach ( $e as $k => $v ) {
|
6645 |
+
$k = strpos( $k, ':' ) ? $this->expandQname( $k ) : $k;
|
6646 |
+
$v = strpos( $v, ':' ) ? $this->expandQname( $v ) : $v;
|
6647 |
+
$ee[ $k ] = $v;
|
6648 |
+
}
|
6649 |
+
$eElements[ $n ] = $ee;
|
6650 |
+
}
|
6651 |
+
$elements = $eElements;
|
6652 |
+
}
|
6653 |
+
|
6654 |
+
if ( count( $attrs ) > 0 ) {
|
6655 |
+
foreach ( $attrs as $n => $a ) {
|
6656 |
+
// expand each attribute
|
6657 |
+
foreach ( $a as $k => $v ) {
|
6658 |
+
$k = strpos( $k, ':' ) ? $this->expandQname( $k ) : $k;
|
6659 |
+
$v = strpos( $v, ':' ) ? $this->expandQname( $v ) : $v;
|
6660 |
+
$aa[ $k ] = $v;
|
6661 |
+
}
|
6662 |
+
$eAttrs[ $n ] = $aa;
|
6663 |
+
}
|
6664 |
+
$attrs = $eAttrs;
|
6665 |
+
}
|
6666 |
+
|
6667 |
+
$restrictionBase = strpos( $restrictionBase, ':' ) ? $this->expandQname( $restrictionBase ) : $restrictionBase;
|
6668 |
+
$arrayType = strpos( $arrayType, ':' ) ? $this->expandQname( $arrayType ) : $arrayType;
|
6669 |
+
|
6670 |
+
$typens = isset( $this->namespaces['types'] ) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6671 |
+
$this->schemas[ $typens ][0]->addComplexType( $name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType );
|
6672 |
+
}
|
6673 |
+
|
6674 |
+
/**
|
6675 |
+
* adds an XML Schema simple type to the WSDL types
|
6676 |
+
*
|
6677 |
+
* @param string $name
|
6678 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6679 |
+
* @param string $typeClass (should always be simpleType)
|
6680 |
+
* @param string $phpType (should always be scalar)
|
6681 |
+
* @param array $enumeration array of values
|
6682 |
+
*
|
6683 |
+
* @see nusoap_xmlschema
|
6684 |
+
* @access public
|
6685 |
+
*/
|
6686 |
+
function addSimpleType( $name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array() ) {
|
6687 |
+
$restrictionBase = strpos( $restrictionBase, ':' ) ? $this->expandQname( $restrictionBase ) : $restrictionBase;
|
6688 |
+
|
6689 |
+
$typens = isset( $this->namespaces['types'] ) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6690 |
+
$this->schemas[ $typens ][0]->addSimpleType( $name, $restrictionBase, $typeClass, $phpType, $enumeration );
|
6691 |
+
}
|
6692 |
+
|
6693 |
+
/**
|
6694 |
+
* adds an element to the WSDL types
|
6695 |
+
*
|
6696 |
+
* @param array $attrs attributes that must include name and type
|
6697 |
+
*
|
6698 |
+
* @see nusoap_xmlschema
|
6699 |
+
* @access public
|
6700 |
+
*/
|
6701 |
+
function addElement( $attrs ) {
|
6702 |
+
$typens = isset( $this->namespaces['types'] ) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6703 |
+
$this->schemas[ $typens ][0]->addElement( $attrs );
|
6704 |
+
}
|
6705 |
+
|
6706 |
+
/**
|
6707 |
+
* register an operation with the server
|
6708 |
+
*
|
6709 |
+
* @param string $name operation (method) name
|
6710 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
6711 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
6712 |
+
* @param string $namespace optional The namespace for the operation
|
6713 |
+
* @param string $soapaction optional The soapaction for the operation
|
6714 |
+
* @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
|
6715 |
+
* @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
|
6716 |
+
* @param string $documentation optional The description to include in the WSDL
|
6717 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
6718 |
+
*
|
6719 |
+
* @access public
|
6720 |
+
*/
|
6721 |
+
function addOperation( $name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '' ) {
|
6722 |
+
if ( $use == 'encoded' && $encodingStyle == '' ) {
|
6723 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
6724 |
+
}
|
6725 |
+
|
6726 |
+
if ( $style == 'document' ) {
|
6727 |
+
$elements = array();
|
6728 |
+
foreach ( $in as $n => $t ) {
|
6729 |
+
$elements[ $n ] = array( 'name' => $n, 'type' => $t, 'form' => 'unqualified' );
|
6730 |
+
}
|
6731 |
+
$this->addComplexType( $name . 'RequestType', 'complexType', 'struct', 'all', '', $elements );
|
6732 |
+
$this->addElement( array( 'name' => $name, 'type' => $name . 'RequestType' ) );
|
6733 |
+
$in = array( 'parameters' => 'tns:' . $name . '^' );
|
6734 |
+
|
6735 |
+
$elements = array();
|
6736 |
+
foreach ( $out as $n => $t ) {
|
6737 |
+
$elements[ $n ] = array( 'name' => $n, 'type' => $t, 'form' => 'unqualified' );
|
6738 |
+
}
|
6739 |
+
$this->addComplexType( $name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements );
|
6740 |
+
$this->addElement( array(
|
6741 |
+
'name' => $name . 'Response',
|
6742 |
+
'type' => $name . 'ResponseType',
|
6743 |
+
'form' => 'qualified'
|
6744 |
+
) );
|
6745 |
+
$out = array( 'parameters' => 'tns:' . $name . 'Response' . '^' );
|
6746 |
+
}
|
6747 |
+
|
6748 |
+
// get binding
|
6749 |
+
$this->bindings[ $this->serviceName . 'Binding' ]['operations'][ $name ] =
|
6750 |
+
array(
|
6751 |
+
'name' => $name,
|
6752 |
+
'binding' => $this->serviceName . 'Binding',
|
6753 |
+
'endpoint' => $this->endpoint,
|
6754 |
+
'soapAction' => $soapaction,
|
6755 |
+
'style' => $style,
|
6756 |
+
'input' => array(
|
6757 |
+
'use' => $use,
|
6758 |
+
'namespace' => $namespace,
|
6759 |
+
'encodingStyle' => $encodingStyle,
|
6760 |
+
'message' => $name . 'Request',
|
6761 |
+
'parts' => $in
|
6762 |
+
),
|
6763 |
+
'output' => array(
|
6764 |
+
'use' => $use,
|
6765 |
+
'namespace' => $namespace,
|
6766 |
+
'encodingStyle' => $encodingStyle,
|
6767 |
+
'message' => $name . 'Response',
|
6768 |
+
'parts' => $out
|
6769 |
+
),
|
6770 |
+
'namespace' => $namespace,
|
6771 |
+
'transport' => 'http://schemas.xmlsoap.org/soap/http',
|
6772 |
+
'documentation' => $documentation
|
6773 |
+
);
|
6774 |
+
// add portTypes
|
6775 |
+
// add messages
|
6776 |
+
if ( $in ) {
|
6777 |
+
foreach ( $in as $pName => $pType ) {
|
6778 |
+
if ( strpos( $pType, ':' ) ) {
|
6779 |
+
$pType = $this->getNamespaceFromPrefix( $this->getPrefix( $pType ) ) . ":" . $this->getLocalPart( $pType );
|
6780 |
+
}
|
6781 |
+
$this->messages[ $name . 'Request' ][ $pName ] = $pType;
|
6782 |
+
}
|
6783 |
+
} else {
|
6784 |
+
$this->messages[ $name . 'Request' ] = '0';
|
6785 |
+
}
|
6786 |
+
if ( $out ) {
|
6787 |
+
foreach ( $out as $pName => $pType ) {
|
6788 |
+
if ( strpos( $pType, ':' ) ) {
|
6789 |
+
$pType = $this->getNamespaceFromPrefix( $this->getPrefix( $pType ) ) . ":" . $this->getLocalPart( $pType );
|
6790 |
+
}
|
6791 |
+
$this->messages[ $name . 'Response' ][ $pName ] = $pType;
|
6792 |
+
}
|
6793 |
+
} else {
|
6794 |
+
$this->messages[ $name . 'Response' ] = '0';
|
6795 |
+
}
|
6796 |
+
|
6797 |
+
return true;
|
6798 |
+
}
|
6799 |
+
}
|
6800 |
+
|
6801 |
+
?><?php
|
6802 |
+
|
6803 |
+
|
6804 |
+
/**
|
6805 |
+
*
|
6806 |
+
* nusoap_parser class parses SOAP XML messages into native PHP values
|
6807 |
+
*
|
6808 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
6809 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
6810 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
6811 |
+
* @access public
|
6812 |
+
*/
|
6813 |
+
class nusoap_parser extends nusoap_base {
|
6814 |
+
|
6815 |
+
var $xml = '';
|
6816 |
+
var $xml_encoding = '';
|
6817 |
+
var $method = '';
|
6818 |
+
var $root_struct = '';
|
6819 |
+
var $root_struct_name = '';
|
6820 |
+
var $root_struct_namespace = '';
|
6821 |
+
var $root_header = '';
|
6822 |
+
var $document = ''; // incoming SOAP body (text)
|
6823 |
+
// determines where in the message we are (envelope,header,body,method)
|
6824 |
+
var $status = '';
|
6825 |
+
var $position = 0;
|
6826 |
+
var $depth = 0;
|
6827 |
+
var $default_namespace = '';
|
6828 |
+
var $namespaces = array();
|
6829 |
+
var $message = array();
|
6830 |
+
var $parent = '';
|
6831 |
+
var $fault = false;
|
6832 |
+
var $fault_code = '';
|
6833 |
+
var $fault_str = '';
|
6834 |
+
var $fault_detail = '';
|
6835 |
+
var $depth_array = array();
|
6836 |
+
var $debug_flag = true;
|
6837 |
+
var $soapresponse = null; // parsed SOAP Body
|
6838 |
+
var $soapheader = null; // parsed SOAP Header
|
6839 |
+
var $responseHeaders = ''; // incoming SOAP headers (text)
|
6840 |
+
var $body_position = 0;
|
6841 |
+
// for multiref parsing:
|
6842 |
+
// array of id => pos
|
6843 |
+
var $ids = array();
|
6844 |
+
// array of id => hrefs => pos
|
6845 |
+
var $multirefs = array();
|
6846 |
+
// toggle for auto-decoding element content
|
6847 |
+
var $decode_utf8 = true;
|
6848 |
+
|
6849 |
+
/**
|
6850 |
+
* constructor that actually does the parsing
|
6851 |
+
*
|
6852 |
+
* @param string $xml SOAP message
|
6853 |
+
* @param string $encoding character encoding scheme of message
|
6854 |
+
* @param string $method method for which XML is parsed (unused?)
|
6855 |
+
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
|
6856 |
+
*
|
6857 |
+
* @access public
|
6858 |
+
*/
|
6859 |
+
function nusoap_parser( $xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true ) {
|
6860 |
+
parent::nusoap_base();
|
6861 |
+
$this->xml = $xml;
|
6862 |
+
$this->xml_encoding = $encoding;
|
6863 |
+
$this->method = $method;
|
6864 |
+
$this->decode_utf8 = $decode_utf8;
|
6865 |
+
|
6866 |
+
// Check whether content has been read.
|
6867 |
+
if ( ! empty( $xml ) ) {
|
6868 |
+
// Check XML encoding
|
6869 |
+
$pos_xml = strpos( $xml, '<?xml' );
|
6870 |
+
if ( $pos_xml !== false ) {
|
6871 |
+
$xml_decl = substr( $xml, $pos_xml, strpos( $xml, '?>', $pos_xml + 2 ) - $pos_xml + 1 );
|
6872 |
+
if ( preg_match( "/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res ) ) {
|
6873 |
+
$xml_encoding = $res[1];
|
6874 |
+
if ( strtoupper( $xml_encoding ) != $encoding ) {
|
6875 |
+
$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
|
6876 |
+
$this->debug( $err );
|
6877 |
+
if ( $encoding != 'ISO-8859-1' || strtoupper( $xml_encoding ) != 'UTF-8' ) {
|
6878 |
+
$this->setError( $err );
|
6879 |
+
|
6880 |
+
return;
|
6881 |
+
}
|
6882 |
+
// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
|
6883 |
+
} else {
|
6884 |
+
$this->debug( 'Charset from HTTP Content-Type matches encoding from XML declaration' );
|
6885 |
+
}
|
6886 |
+
} else {
|
6887 |
+
$this->debug( 'No encoding specified in XML declaration' );
|
6888 |
+
}
|
6889 |
+
} else {
|
6890 |
+
$this->debug( 'No XML declaration' );
|
6891 |
+
}
|
6892 |
+
$this->debug( 'Entering nusoap_parser(), length=' . strlen( $xml ) . ', encoding=' . $encoding );
|
6893 |
+
// Create an XML parser - why not xml_parser_create_ns?
|
6894 |
+
$this->parser = xml_parser_create( $this->xml_encoding );
|
6895 |
+
// Set the options for parsing the XML data.
|
6896 |
+
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
6897 |
+
xml_parser_set_option( $this->parser, XML_OPTION_CASE_FOLDING, 0 );
|
6898 |
+
xml_parser_set_option( $this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding );
|
6899 |
+
// Set the object for the parser.
|
6900 |
+
xml_set_object( $this->parser, $this );
|
6901 |
+
// Set the element handlers for the parser.
|
6902 |
+
xml_set_element_handler( $this->parser, 'start_element', 'end_element' );
|
6903 |
+
xml_set_character_data_handler( $this->parser, 'character_data' );
|
6904 |
+
|
6905 |
+
// Parse the XML file.
|
6906 |
+
if ( ! xml_parse( $this->parser, $xml, true ) ) {
|
6907 |
+
// Display an error message.
|
6908 |
+
$err = sprintf( 'XML error parsing SOAP payload on line %d: %s',
|
6909 |
+
xml_get_current_line_number( $this->parser ),
|
6910 |
+
xml_error_string( xml_get_error_code( $this->parser ) ) );
|
6911 |
+
$this->debug( $err );
|
6912 |
+
$this->debug( "XML payload:\n" . $xml );
|
6913 |
+
$this->setError( $err );
|
6914 |
+
} else {
|
6915 |
+
$this->debug( 'in nusoap_parser ctor, message:' );
|
6916 |
+
$this->appendDebug( $this->varDump( $this->message ) );
|
6917 |
+
$this->debug( 'parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name );
|
6918 |
+
// get final value
|
6919 |
+
$this->soapresponse = $this->message[ $this->root_struct ]['result'];
|
6920 |
+
// get header value
|
6921 |
+
if ( $this->root_header != '' && isset( $this->message[ $this->root_header ]['result'] ) ) {
|
6922 |
+
$this->soapheader = $this->message[ $this->root_header ]['result'];
|
6923 |
+
}
|
6924 |
+
// resolve hrefs/ids
|
6925 |
+
if ( sizeof( $this->multirefs ) > 0 ) {
|
6926 |
+
foreach ( $this->multirefs as $id => $hrefs ) {
|
6927 |
+
$this->debug( 'resolving multirefs for id: ' . $id );
|
6928 |
+
$idVal = $this->buildVal( $this->ids[ $id ] );
|
6929 |
+
if ( is_array( $idVal ) && isset( $idVal['!id'] ) ) {
|
6930 |
+
unset( $idVal['!id'] );
|
6931 |
+
}
|
6932 |
+
foreach ( $hrefs as $refPos => $ref ) {
|
6933 |
+
$this->debug( 'resolving href at pos ' . $refPos );
|
6934 |
+
$this->multirefs[ $id ][ $refPos ] = $idVal;
|
6935 |
+
}
|
6936 |
+
}
|
6937 |
+
}
|
6938 |
+
}
|
6939 |
+
xml_parser_free( $this->parser );
|
6940 |
+
} else {
|
6941 |
+
$this->debug( 'xml was empty, didn\'t parse!' );
|
6942 |
+
$this->setError( 'xml was empty, didn\'t parse!' );
|
6943 |
+
}
|
6944 |
+
}
|
6945 |
+
|
6946 |
+
/**
|
6947 |
+
* start-element handler
|
6948 |
+
*
|
6949 |
+
* @param resource $parser XML parser object
|
6950 |
+
* @param string $name element name
|
6951 |
+
* @param array $attrs associative array of attributes
|
6952 |
+
*
|
6953 |
+
* @access private
|
6954 |
+
*/
|
6955 |
+
function start_element( $parser, $name, $attrs ) {
|
6956 |
+
// position in a total number of elements, starting from 0
|
6957 |
+
// update class level pos
|
6958 |
+
$pos = $this->position ++;
|
6959 |
+
// and set mine
|
6960 |
+
$this->message[ $pos ] = array( 'pos' => $pos, 'children' => '', 'cdata' => '' );
|
6961 |
+
// depth = how many levels removed from root?
|
6962 |
+
// set mine as current global depth and increment global depth value
|
6963 |
+
$this->message[ $pos ]['depth'] = $this->depth ++;
|
6964 |
+
|
6965 |
+
// else add self as child to whoever the current parent is
|
6966 |
+
if ( $pos != 0 ) {
|
6967 |
+
$this->message[ $this->parent ]['children'] .= '|' . $pos;
|
6968 |
+
}
|
6969 |
+
// set my parent
|
6970 |
+
$this->message[ $pos ]['parent'] = $this->parent;
|
6971 |
+
// set self as current parent
|
6972 |
+
$this->parent = $pos;
|
6973 |
+
// set self as current value for this depth
|
6974 |
+
$this->depth_array[ $this->depth ] = $pos;
|
6975 |
+
// get element prefix
|
6976 |
+
if ( strpos( $name, ':' ) ) {
|
6977 |
+
// get ns prefix
|
6978 |
+
$prefix = substr( $name, 0, strpos( $name, ':' ) );
|
6979 |
+
// get unqualified name
|
6980 |
+
$name = substr( strstr( $name, ':' ), 1 );
|
6981 |
+
}
|
6982 |
+
// set status
|
6983 |
+
if ( $name == 'Envelope' && $this->status == '' ) {
|
6984 |
+
$this->status = 'envelope';
|
6985 |
+
} elseif ( $name == 'Header' && $this->status == 'envelope' ) {
|
6986 |
+
$this->root_header = $pos;
|
6987 |
+
$this->status = 'header';
|
6988 |
+
} elseif ( $name == 'Body' && $this->status == 'envelope' ) {
|
6989 |
+
$this->status = 'body';
|
6990 |
+
$this->body_position = $pos;
|
6991 |
+
// set method
|
6992 |
+
} elseif ( $this->status == 'body' && $pos == ( $this->body_position + 1 ) ) {
|
6993 |
+
$this->status = 'method';
|
6994 |
+
$this->root_struct_name = $name;
|
6995 |
+
$this->root_struct = $pos;
|
6996 |
+
$this->message[ $pos ]['type'] = 'struct';
|
6997 |
+
$this->debug( "found root struct $this->root_struct_name, pos $this->root_struct" );
|
6998 |
+
}
|
6999 |
+
// set my status
|
7000 |
+
$this->message[ $pos ]['status'] = $this->status;
|
7001 |
+
// set name
|
7002 |
+
$this->message[ $pos ]['name'] = htmlspecialchars( $name );
|
7003 |
+
// set attrs
|
7004 |
+
$this->message[ $pos ]['attrs'] = $attrs;
|
7005 |
+
|
7006 |
+
// loop through atts, logging ns and type declarations
|
7007 |
+
$attstr = '';
|
7008 |
+
foreach ( $attrs as $key => $value ) {
|
7009 |
+
$key_prefix = $this->getPrefix( $key );
|
7010 |
+
$key_localpart = $this->getLocalPart( $key );
|
7011 |
+
// if ns declarations, add to class level array of valid namespaces
|
7012 |
+
if ( $key_prefix == 'xmlns' ) {
|
7013 |
+
if ( preg_match( '/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value ) ) {
|
7014 |
+
$this->XMLSchemaVersion = $value;
|
7015 |
+
$this->namespaces['xsd'] = $this->XMLSchemaVersion;
|
7016 |
+
$this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
|
7017 |
+
}
|
7018 |
+
$this->namespaces[ $key_localpart ] = $value;
|
7019 |
+
// set method namespace
|
7020 |
+
if ( $name == $this->root_struct_name ) {
|
7021 |
+
$this->methodNamespace = $value;
|
7022 |
+
}
|
7023 |
+
// if it's a type declaration, set type
|
7024 |
+
} elseif ( $key_localpart == 'type' ) {
|
7025 |
+
if ( isset( $this->message[ $pos ]['type'] ) && $this->message[ $pos ]['type'] == 'array' ) {
|
7026 |
+
// do nothing: already processed arrayType
|
7027 |
+
} else {
|
7028 |
+
$value_prefix = $this->getPrefix( $value );
|
7029 |
+
$value_localpart = $this->getLocalPart( $value );
|
7030 |
+
$this->message[ $pos ]['type'] = $value_localpart;
|
7031 |
+
$this->message[ $pos ]['typePrefix'] = $value_prefix;
|
7032 |
+
if ( isset( $this->namespaces[ $value_prefix ] ) ) {
|
7033 |
+
$this->message[ $pos ]['type_namespace'] = $this->namespaces[ $value_prefix ];
|
7034 |
+
} else if ( isset( $attrs[ 'xmlns:' . $value_prefix ] ) ) {
|
7035 |
+
$this->message[ $pos ]['type_namespace'] = $attrs[ 'xmlns:' . $value_prefix ];
|
7036 |
+
}
|
7037 |
+
// should do something here with the namespace of specified type?
|
7038 |
+
}
|
7039 |
+
} elseif ( $key_localpart == 'arrayType' ) {
|
7040 |
+
$this->message[ $pos ]['type'] = 'array';
|
7041 |
+
/* do arrayType ereg here
|
7042 |
+
[1] arrayTypeValue ::= atype asize
|
7043 |
+
[2] atype ::= QName rank*
|
7044 |
+
[3] rank ::= '[' (',')* ']'
|
7045 |
+
[4] asize ::= '[' length~ ']'
|
7046 |
+
[5] length ::= nextDimension* Digit+
|
7047 |
+
[6] nextDimension ::= Digit+ ','
|
7048 |
+
*/
|
7049 |
+
$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
|
7050 |
+
if ( preg_match( $expr, $value, $regs ) ) {
|
7051 |
+
$this->message[ $pos ]['typePrefix'] = $regs[1];
|
7052 |
+
$this->message[ $pos ]['arrayTypePrefix'] = $regs[1];
|
7053 |
+
if ( isset( $this->namespaces[ $regs[1] ] ) ) {
|
7054 |
+
$this->message[ $pos ]['arrayTypeNamespace'] = $this->namespaces[ $regs[1] ];
|
7055 |
+
} else if ( isset( $attrs[ 'xmlns:' . $regs[1] ] ) ) {
|
7056 |
+
$this->message[ $pos ]['arrayTypeNamespace'] = $attrs[ 'xmlns:' . $regs[1] ];
|
7057 |
+
}
|
7058 |
+
$this->message[ $pos ]['arrayType'] = $regs[2];
|
7059 |
+
$this->message[ $pos ]['arraySize'] = $regs[3];
|
7060 |
+
$this->message[ $pos ]['arrayCols'] = $regs[4];
|
7061 |
+
}
|
7062 |
+
// specifies nil value (or not)
|
7063 |
+
} elseif ( $key_localpart == 'nil' ) {
|
7064 |
+
$this->message[ $pos ]['nil'] = ( $value == 'true' || $value == '1' );
|
7065 |
+
// some other attribute
|
7066 |
+
} elseif ( $key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root' ) {
|
7067 |
+
$this->message[ $pos ]['xattrs'][ '!' . $key ] = $value;
|
7068 |
+
}
|
7069 |
+
|
7070 |
+
if ( $key == 'xmlns' ) {
|
7071 |
+
$this->default_namespace = $value;
|
7072 |
+
}
|
7073 |
+
// log id
|
7074 |
+
if ( $key == 'id' ) {
|
7075 |
+
$this->ids[ $value ] = $pos;
|
7076 |
+
}
|
7077 |
+
// root
|
7078 |
+
if ( $key_localpart == 'root' && $value == 1 ) {
|
7079 |
+
$this->status = 'method';
|
7080 |
+
$this->root_struct_name = $name;
|
7081 |
+
$this->root_struct = $pos;
|
7082 |
+
$this->debug( "found root struct $this->root_struct_name, pos $pos" );
|
7083 |
+
}
|
7084 |
+
// for doclit
|
7085 |
+
$attstr .= " $key=\"$value\"";
|
7086 |
+
}
|
7087 |
+
// get namespace - must be done after namespace atts are processed
|
7088 |
+
if ( isset( $prefix ) ) {
|
7089 |
+
$this->message[ $pos ]['namespace'] = $this->namespaces[ $prefix ];
|
7090 |
+
$this->default_namespace = $this->namespaces[ $prefix ];
|
7091 |
+
} else {
|
7092 |
+
$this->message[ $pos ]['namespace'] = $this->default_namespace;
|
7093 |
+
}
|
7094 |
+
if ( $this->status == 'header' ) {
|
7095 |
+
if ( $this->root_header != $pos ) {
|
7096 |
+
$this->responseHeaders .= "<" . ( isset( $prefix ) ? $prefix . ':' : '' ) . "$name$attstr>";
|
7097 |
+
}
|
7098 |
+
} elseif ( $this->root_struct_name != '' ) {
|
7099 |
+
$this->document .= "<" . ( isset( $prefix ) ? $prefix . ':' : '' ) . "$name$attstr>";
|
7100 |
+
}
|
7101 |
+
}
|
7102 |
+
|
7103 |
+
/**
|
7104 |
+
* end-element handler
|
7105 |
+
*
|
7106 |
+
* @param resource $parser XML parser object
|
7107 |
+
* @param string $name element name
|
7108 |
+
*
|
7109 |
+
* @access private
|
7110 |
+
*/
|
7111 |
+
function end_element( $parser, $name ) {
|
7112 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
7113 |
+
$pos = $this->depth_array[ $this->depth -- ];
|
7114 |
+
|
7115 |
+
// get element prefix
|
7116 |
+
if ( strpos( $name, ':' ) ) {
|
7117 |
+
// get ns prefix
|
7118 |
+
$prefix = substr( $name, 0, strpos( $name, ':' ) );
|
7119 |
+
// get unqualified name
|
7120 |
+
$name = substr( strstr( $name, ':' ), 1 );
|
7121 |
+
}
|
7122 |
+
|
7123 |
+
// build to native type
|
7124 |
+
if ( isset( $this->body_position ) && $pos > $this->body_position ) {
|
7125 |
+
// deal w/ multirefs
|
7126 |
+
if ( isset( $this->message[ $pos ]['attrs']['href'] ) ) {
|
7127 |
+
// get id
|
7128 |
+
$id = substr( $this->message[ $pos ]['attrs']['href'], 1 );
|
7129 |
+
// add placeholder to href array
|
7130 |
+
$this->multirefs[ $id ][ $pos ] = 'placeholder';
|
7131 |
+
// add set a reference to it as the result value
|
7132 |
+
$this->message[ $pos ]['result'] =& $this->multirefs[ $id ][ $pos ];
|
7133 |
+
// build complexType values
|
7134 |
+
} elseif ( $this->message[ $pos ]['children'] != '' ) {
|
7135 |
+
// if result has already been generated (struct/array)
|
7136 |
+
if ( ! isset( $this->message[ $pos ]['result'] ) ) {
|
7137 |
+
$this->message[ $pos ]['result'] = $this->buildVal( $pos );
|
7138 |
+
}
|
7139 |
+
// build complexType values of attributes and possibly simpleContent
|
7140 |
+
} elseif ( isset( $this->message[ $pos ]['xattrs'] ) ) {
|
7141 |
+
if ( isset( $this->message[ $pos ]['nil'] ) && $this->message[ $pos ]['nil'] ) {
|
7142 |
+
$this->message[ $pos ]['xattrs']['!'] = null;
|
7143 |
+
} elseif ( isset( $this->message[ $pos ]['cdata'] ) && trim( $this->message[ $pos ]['cdata'] ) != '' ) {
|
7144 |
+
if ( isset( $this->message[ $pos ]['type'] ) ) {
|
7145 |
+
$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'] : '' );
|
7146 |
+
} else {
|
7147 |
+
$parent = $this->message[ $pos ]['parent'];
|
7148 |
+
if ( isset( $this->message[ $parent ]['type'] ) && ( $this->message[ $parent ]['type'] == 'array' ) && isset( $this->message[ $parent ]['arrayType'] ) ) {
|
7149 |
+
$this->message[ $pos ]['xattrs']['!'] = $this->decodeSimple( $this->message[ $pos ]['cdata'], $this->message[ $parent ]['arrayType'], isset( $this->message[ $parent ]['arrayTypeNamespace'] ) ? $this->message[ $parent ]['arrayTypeNamespace'] : '' );
|
7150 |
+
} else {
|
7151 |
+
$this->message[ $pos ]['xattrs']['!'] = $this->message[ $pos ]['cdata'];
|
7152 |
+
}
|
7153 |
+
}
|
7154 |
+
}
|
7155 |
+
$this->message[ $pos ]['result'] = $this->message[ $pos ]['xattrs'];
|
7156 |
+
// set value of simpleType (or nil complexType)
|
7157 |
+
} else {
|
7158 |
+
//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
|
7159 |
+
if ( isset( $this->message[ $pos ]['nil'] ) && $this->message[ $pos ]['nil'] ) {
|
7160 |
+
$this->message[ $pos ]['xattrs']['!'] = null;
|
7161 |
+
} elseif ( isset( $this->message[ $pos ]['type'] ) ) {
|
7162 |
+
$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'] : '' );
|
7163 |
+
} else {
|
7164 |
+
$parent = $this->message[ $pos ]['parent'];
|
7165 |
+
if ( isset( $this->message[ $parent ]['type'] ) && ( $this->message[ $parent ]['type'] == 'array' ) && isset( $this->message[ $parent ]['arrayType'] ) ) {
|
7166 |
+
$this->message[ $pos ]['result'] = $this->decodeSimple( $this->message[ $pos ]['cdata'], $this->message[ $parent ]['arrayType'], isset( $this->message[ $parent ]['arrayTypeNamespace'] ) ? $this->message[ $parent ]['arrayTypeNamespace'] : '' );
|
7167 |
+
} else {
|
7168 |
+
$this->message[ $pos ]['result'] = $this->message[ $pos ]['cdata'];
|
7169 |
+
}
|
7170 |
+
}
|
7171 |
+
|
7172 |
+
/* add value to parent's result, if parent is struct/array
|
7173 |
+
$parent = $this->message[$pos]['parent'];
|
7174 |
+
if($this->message[$parent]['type'] != 'map'){
|
7175 |
+
if(strtolower($this->message[$parent]['type']) == 'array'){
|
7176 |
+
$this->message[$parent]['result'][] = $this->message[$pos]['result'];
|
7177 |
+
} else {
|
7178 |
+
$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
|
7179 |
+
}
|
7180 |
+
}
|
7181 |
+
*/
|
7182 |
+
}
|
7183 |
+
}
|
7184 |
+
|
7185 |
+
// for doclit
|
7186 |
+
if ( $this->status == 'header' ) {
|
7187 |
+
if ( $this->root_header != $pos ) {
|
7188 |
+
$this->responseHeaders .= "</" . ( isset( $prefix ) ? $prefix . ':' : '' ) . "$name>";
|
7189 |
+
}
|
7190 |
+
} elseif ( $pos >= $this->root_struct ) {
|
7191 |
+
$this->document .= "</" . ( isset( $prefix ) ? $prefix . ':' : '' ) . "$name>";
|
7192 |
+
}
|
7193 |
+
// switch status
|
7194 |
+
if ( $pos == $this->root_struct ) {
|
7195 |
+
$this->status = 'body';
|
7196 |
+
$this->root_struct_namespace = $this->message[ $pos ]['namespace'];
|
7197 |
+
} elseif ( $pos == $this->root_header ) {
|
7198 |
+
$this->status = 'envelope';
|
7199 |
+
} elseif ( $name == 'Body' && $this->status == 'body' ) {
|
7200 |
+
$this->status = 'envelope';
|
7201 |
+
} elseif ( $name == 'Header' && $this->status == 'header' ) { // will never happen
|
7202 |
+
$this->status = 'envelope';
|
7203 |
+
} elseif ( $name == 'Envelope' && $this->status == 'envelope' ) {
|
7204 |
+
$this->status = '';
|
7205 |
+
}
|
7206 |
+
// set parent back to my parent
|
7207 |
+
$this->parent = $this->message[ $pos ]['parent'];
|
7208 |
+
}
|
7209 |
+
|
7210 |
+
/**
|
7211 |
+
* element content handler
|
7212 |
+
*
|
7213 |
+
* @param resource $parser XML parser object
|
7214 |
+
* @param string $data element content
|
7215 |
+
*
|
7216 |
+
* @access private
|
7217 |
+
*/
|
7218 |
+
function character_data( $parser, $data ) {
|
7219 |
+
$pos = $this->depth_array[ $this->depth ];
|
7220 |
+
if ( $this->xml_encoding == 'UTF-8' ) {
|
7221 |
+
// TODO: add an option to disable this for folks who want
|
7222 |
+
// raw UTF-8 that, e.g., might not map to iso-8859-1
|
7223 |
+
// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
|
7224 |
+
if ( $this->decode_utf8 ) {
|
7225 |
+
$data = utf8_decode( $data );
|
7226 |
+
}
|
7227 |
+
}
|
7228 |
+
$this->message[ $pos ]['cdata'] .= $data;
|
7229 |
+
// for doclit
|
7230 |
+
if ( $this->status == 'header' ) {
|
7231 |
+
$this->responseHeaders .= $data;
|
7232 |
+
} else {
|
7233 |
+
$this->document .= $data;
|
7234 |
+
}
|
7235 |
+
}
|
7236 |
+
|
7237 |
+
/**
|
7238 |
+
* get the parsed message (SOAP Body)
|
7239 |
+
*
|
7240 |
+
* @return mixed
|
7241 |
+
* @access public
|
7242 |
+
* @deprecated use get_soapbody instead
|
7243 |
+
*/
|
7244 |
+
function get_response() {
|
7245 |
+
return $this->soapresponse;
|
7246 |
+
}
|
7247 |
+
|
7248 |
+
/**
|
7249 |
+
* get the parsed SOAP Body (NULL if there was none)
|
7250 |
+
*
|
7251 |
+
* @return mixed
|
7252 |
+
* @access public
|
7253 |
+
*/
|
7254 |
+
function get_soapbody() {
|
7255 |
+
return $this->soapresponse;
|
7256 |
+
}
|
7257 |
+
|
7258 |
+
/**
|
7259 |
+
* get the parsed SOAP Header (NULL if there was none)
|
7260 |
+
*
|
7261 |
+
* @return mixed
|
7262 |
+
* @access public
|
7263 |
+
*/
|
7264 |
+
function get_soapheader() {
|
7265 |
+
return $this->soapheader;
|
7266 |
+
}
|
7267 |
+
|
7268 |
+
/**
|
7269 |
+
* get the unparsed SOAP Header
|
7270 |
+
*
|
7271 |
+
* @return string XML or empty if no Header
|
7272 |
+
* @access public
|
7273 |
+
*/
|
7274 |
+
function getHeaders() {
|
7275 |
+
return $this->responseHeaders;
|
7276 |
+
}
|
7277 |
+
|
7278 |
+
/**
|
7279 |
+
* decodes simple types into PHP variables
|
7280 |
+
*
|
7281 |
+
* @param string $value value to decode
|
7282 |
+
* @param string $type XML type to decode
|
7283 |
+
* @param string $typens XML type namespace to decode
|
7284 |
+
*
|
7285 |
+
* @return mixed PHP value
|
7286 |
+
* @access private
|
7287 |
+
*/
|
7288 |
+
function decodeSimple( $value, $type, $typens ) {
|
7289 |
+
// TODO: use the namespace!
|
7290 |
+
if ( ( ! isset( $type ) ) || $type == 'string' || $type == 'long' || $type == 'unsignedLong' ) {
|
7291 |
+
return (string) $value;
|
7292 |
+
}
|
7293 |
+
if ( $type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte' ) {
|
7294 |
+
return (int) $value;
|
7295 |
+
}
|
7296 |
+
if ( $type == 'float' || $type == 'double' || $type == 'decimal' ) {
|
7297 |
+
return (double) $value;
|
7298 |
+
}
|
7299 |
+
if ( $type == 'boolean' ) {
|
7300 |
+
if ( strtolower( $value ) == 'false' || strtolower( $value ) == 'f' ) {
|
7301 |
+
return false;
|
7302 |
+
}
|
7303 |
+
|
7304 |
+
return (boolean) $value;
|
7305 |
+
}
|
7306 |
+
if ( $type == 'base64' || $type == 'base64Binary' ) {
|
7307 |
+
$this->debug( 'Decode base64 value' );
|
7308 |
+
|
7309 |
+
return base64_decode( $value );
|
7310 |
+
}
|
7311 |
+
// obscure numeric types
|
7312 |
+
if ( $type == 'nonPositiveInteger' || $type == 'negativeInteger'
|
7313 |
+
|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
|
7314 |
+
|| $type == 'unsignedInt'
|
7315 |
+
|| $type == 'unsignedShort' || $type == 'unsignedByte' ) {
|
7316 |
+
return (int) $value;
|
7317 |
+
}
|
7318 |
+
// bogus: parser treats array with no elements as a simple type
|
7319 |
+
if ( $type == 'array' ) {
|
7320 |
+
return array();
|
7321 |
+
}
|
7322 |
+
|
7323 |
+
// everything else
|
7324 |
+
return (string) $value;
|
7325 |
+
}
|
7326 |
+
|
7327 |
+
/**
|
7328 |
+
* builds response structures for compound values (arrays/structs)
|
7329 |
+
* and scalars
|
7330 |
+
*
|
7331 |
+
* @param integer $pos position in node tree
|
7332 |
+
*
|
7333 |
+
* @return mixed PHP value
|
7334 |
+
* @access private
|
7335 |
+
*/
|
7336 |
+
function buildVal( $pos ) {
|
7337 |
+
if ( ! isset( $this->message[ $pos ]['type'] ) ) {
|
7338 |
+
$this->message[ $pos ]['type'] = '';
|
7339 |
+
}
|
7340 |
+
$this->debug( 'in buildVal() for ' . $this->message[ $pos ]['name'] . "(pos $pos) of type " . $this->message[ $pos ]['type'] );
|
7341 |
+
// if there are children...
|
7342 |
+
if ( $this->message[ $pos ]['children'] != '' ) {
|
7343 |
+
$this->debug( 'in buildVal, there are children' );
|
7344 |
+
$children = explode( '|', $this->message[ $pos ]['children'] );
|
7345 |
+
array_shift( $children ); // knock off empty
|
7346 |
+
// md array
|
7347 |
+
if ( isset( $this->message[ $pos ]['arrayCols'] ) && $this->message[ $pos ]['arrayCols'] != '' ) {
|
7348 |
+
$r = 0; // rowcount
|
7349 |
+
$c = 0; // colcount
|
7350 |
+
foreach ( $children as $child_pos ) {
|
7351 |
+
$this->debug( "in buildVal, got an MD array element: $r, $c" );
|
7352 |
+
$params[ $r ][] = $this->message[ $child_pos ]['result'];
|
7353 |
+
$c ++;
|
7354 |
+
if ( $c == $this->message[ $pos ]['arrayCols'] ) {
|
7355 |
+
$c = 0;
|
7356 |
+
$r ++;
|
7357 |
+
}
|
7358 |
+
}
|
7359 |
+
// array
|
7360 |
+
} elseif ( $this->message[ $pos ]['type'] == 'array' || $this->message[ $pos ]['type'] == 'Array' ) {
|
7361 |
+
$this->debug( 'in buildVal, adding array ' . $this->message[ $pos ]['name'] );
|
7362 |
+
foreach ( $children as $child_pos ) {
|
7363 |
+
$params[] = &$this->message[ $child_pos ]['result'];
|
7364 |
+
}
|
7365 |
+
// apache Map type: java hashtable
|
7366 |
+
} elseif ( $this->message[ $pos ]['type'] == 'Map' && $this->message[ $pos ]['type_namespace'] == 'http://xml.apache.org/xml-soap' ) {
|
7367 |
+
$this->debug( 'in buildVal, Java Map ' . $this->message[ $pos ]['name'] );
|
7368 |
+
foreach ( $children as $child_pos ) {
|
7369 |
+
$kv = explode( "|", $this->message[ $child_pos ]['children'] );
|
7370 |
+
$params[ $this->message[ $kv[1] ]['result'] ] = &$this->message[ $kv[2] ]['result'];
|
7371 |
+
}
|
7372 |
+
// generic compound type
|
7373 |
+
//} elseif($this->message[$pos]['type'] == 'SOAPStruct' || $this->message[$pos]['type'] == 'struct') {
|
7374 |
+
} else {
|
7375 |
+
// Apache Vector type: treat as an array
|
7376 |
+
$this->debug( 'in buildVal, adding Java Vector or generic compound type ' . $this->message[ $pos ]['name'] );
|
7377 |
+
if ( $this->message[ $pos ]['type'] == 'Vector' && $this->message[ $pos ]['type_namespace'] == 'http://xml.apache.org/xml-soap' ) {
|
7378 |
+
$notstruct = 1;
|
7379 |
+
} else {
|
7380 |
+
$notstruct = 0;
|
7381 |
+
}
|
7382 |
+
//
|
7383 |
+
foreach ( $children as $child_pos ) {
|
7384 |
+
if ( $notstruct ) {
|
7385 |
+
$params[] = &$this->message[ $child_pos ]['result'];
|
7386 |
+
} else {
|
7387 |
+
if ( isset( $params[ $this->message[ $child_pos ]['name'] ] ) ) {
|
7388 |
+
// de-serialize repeated element name into an array
|
7389 |
+
if ( ( ! is_array( $params[ $this->message[ $child_pos ]['name'] ] ) ) || ( ! isset( $params[ $this->message[ $child_pos ]['name'] ][0] ) ) ) {
|
7390 |
+
$params[ $this->message[ $child_pos ]['name'] ] = array( $params[ $this->message[ $child_pos ]['name'] ] );
|
7391 |
+
}
|
7392 |
+
$params[ $this->message[ $child_pos ]['name'] ][] = &$this->message[ $child_pos ]['result'];
|
7393 |
+
} else {
|
7394 |
+
$params[ $this->message[ $child_pos ]['name'] ] = &$this->message[ $child_pos ]['result'];
|
7395 |
+
}
|
7396 |
+
}
|
7397 |
+
}
|
7398 |
+
}
|
7399 |
+
if ( isset( $this->message[ $pos ]['xattrs'] ) ) {
|
7400 |
+
$this->debug( 'in buildVal, handling attributes' );
|
7401 |
+
foreach ( $this->message[ $pos ]['xattrs'] as $n => $v ) {
|
7402 |
+
$params[ $n ] = $v;
|
7403 |
+
}
|
7404 |
+
}
|
7405 |
+
// handle simpleContent
|
7406 |
+
if ( isset( $this->message[ $pos ]['cdata'] ) && trim( $this->message[ $pos ]['cdata'] ) != '' ) {
|
7407 |
+
$this->debug( 'in buildVal, handling simpleContent' );
|
7408 |
+
if ( isset( $this->message[ $pos ]['type'] ) ) {
|
7409 |
+
$params['!'] = $this->decodeSimple( $this->message[ $pos ]['cdata'], $this->message[ $pos ]['type'], isset( $this->message[ $pos ]['type_namespace'] ) ? $this->message[ $pos ]['type_namespace'] : '' );
|
7410 |
+
} else {
|
7411 |
+
$parent = $this->message[ $pos ]['parent'];
|
7412 |
+
if ( isset( $this->message[ $parent ]['type'] ) && ( $this->message[ $parent ]['type'] == 'array' ) && isset( $this->message[ $parent ]['arrayType'] ) ) {
|
7413 |
+
$params['!'] = $this->decodeSimple( $this->message[ $pos ]['cdata'], $this->message[ $parent ]['arrayType'], isset( $this->message[ $parent ]['arrayTypeNamespace'] ) ? $this->message[ $parent ]['arrayTypeNamespace'] : '' );
|
7414 |
+
} else {
|
7415 |
+
$params['!'] = $this->message[ $pos ]['cdata'];
|
7416 |
+
}
|
7417 |
+
}
|
7418 |
+
}
|
7419 |
+
$ret = is_array( $params ) ? $params : array();
|
7420 |
+
$this->debug( 'in buildVal, return:' );
|
7421 |
+
$this->appendDebug( $this->varDump( $ret ) );
|
7422 |
+
|
7423 |
+
return $ret;
|
7424 |
+
} else {
|
7425 |
+
$this->debug( 'in buildVal, no children, building scalar' );
|
7426 |
+
$cdata = isset( $this->message[ $pos ]['cdata'] ) ? $this->message[ $pos ]['cdata'] : '';
|
7427 |
+
if ( isset( $this->message[ $pos ]['type'] ) ) {
|
7428 |
+
$ret = $this->decodeSimple( $cdata, $this->message[ $pos ]['type'], isset( $this->message[ $pos ]['type_namespace'] ) ? $this->message[ $pos ]['type_namespace'] : '' );
|
7429 |
+
$this->debug( "in buildVal, return: $ret" );
|
7430 |
+
|
7431 |
+
return $ret;
|
7432 |
+
}
|
7433 |
+
$parent = $this->message[ $pos ]['parent'];
|
7434 |
+
if ( isset( $this->message[ $parent ]['type'] ) && ( $this->message[ $parent ]['type'] == 'array' ) && isset( $this->message[ $parent ]['arrayType'] ) ) {
|
7435 |
+
$ret = $this->decodeSimple( $cdata, $this->message[ $parent ]['arrayType'], isset( $this->message[ $parent ]['arrayTypeNamespace'] ) ? $this->message[ $parent ]['arrayTypeNamespace'] : '' );
|
7436 |
+
$this->debug( "in buildVal, return: $ret" );
|
7437 |
+
|
7438 |
+
return $ret;
|
7439 |
+
}
|
7440 |
+
$ret = $this->message[ $pos ]['cdata'];
|
7441 |
+
$this->debug( "in buildVal, return: $ret" );
|
7442 |
+
|
7443 |
+
return $ret;
|
7444 |
+
}
|
7445 |
+
}
|
7446 |
+
}
|
7447 |
+
|
7448 |
+
/**
|
7449 |
+
* Backward compatibility
|
7450 |
+
*/
|
7451 |
+
class soap_parser extends nusoap_parser {
|
7452 |
+
}
|
7453 |
+
|
7454 |
+
?><?php
|
7455 |
+
|
7456 |
+
|
7457 |
+
/**
|
7458 |
+
*
|
7459 |
+
* [nu]soapclient higher level class for easy usage.
|
7460 |
+
*
|
7461 |
+
* usage:
|
7462 |
+
*
|
7463 |
+
* // instantiate client with server info
|
7464 |
+
* $soapclient = new nusoap_client( string path [ ,mixed wsdl] );
|
7465 |
+
*
|
7466 |
+
* // call method, get results
|
7467 |
+
* echo $soapclient->call( string methodname [ ,array parameters] );
|
7468 |
+
*
|
7469 |
+
* // bye bye client
|
7470 |
+
* unset($soapclient);
|
7471 |
+
*
|
7472 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
7473 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
7474 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
7475 |
+
* @access public
|
7476 |
+
*/
|
7477 |
+
class nusoap_client extends nusoap_base {
|
7478 |
+
|
7479 |
+
var $username = ''; // Username for HTTP authentication
|
7480 |
+
var $password = ''; // Password for HTTP authentication
|
7481 |
+
var $authtype = ''; // Type of HTTP authentication
|
7482 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
7483 |
+
var $requestHeaders = false; // SOAP headers in request (text)
|
7484 |
+
var $responseHeaders = ''; // SOAP headers from response (incomplete namespace resolution) (text)
|
7485 |
+
var $responseHeader = null; // SOAP Header from response (parsed)
|
7486 |
+
var $document = ''; // SOAP body response portion (incomplete namespace resolution) (text)
|
7487 |
+
var $endpoint;
|
7488 |
+
var $forceEndpoint = ''; // overrides WSDL endpoint
|
7489 |
+
var $proxyhost = '';
|
7490 |
+
var $proxyport = '';
|
7491 |
+
var $proxyusername = '';
|
7492 |
+
var $proxypassword = '';
|
7493 |
+
var $portName = ''; // port name to use in WSDL
|
7494 |
+
var $xml_encoding = ''; // character set encoding of incoming (response) messages
|
7495 |
+
var $http_encoding = false;
|
7496 |
+
var $timeout = 0; // HTTP connection timeout
|
7497 |
+
var $response_timeout = 30; // HTTP response timeout
|
7498 |
+
var $endpointType = ''; // soap|wsdl, empty for WSDL initialization error
|
7499 |
+
var $persistentConnection = false;
|
7500 |
+
var $defaultRpcParams = false; // This is no longer used
|
7501 |
+
var $request = ''; // HTTP request
|
7502 |
+
var $response = ''; // HTTP response
|
7503 |
+
var $responseData = ''; // SOAP payload of response
|
7504 |
+
var $cookies = array(); // Cookies from response or for request
|
7505 |
+
var $decode_utf8 = true; // toggles whether the parser decodes element content w/ utf8_decode()
|
7506 |
+
var $operations = array(); // WSDL operations, empty for WSDL initialization error
|
7507 |
+
var $curl_options = array(); // User-specified cURL options
|
7508 |
+
var $bindingType = ''; // WSDL operation binding type
|
7509 |
+
var $use_curl = false; // whether to always try to use cURL
|
7510 |
+
|
7511 |
+
/*
|
7512 |
+
* fault related variables
|
7513 |
+
*/
|
7514 |
+
/**
|
7515 |
+
* @var fault
|
7516 |
+
* @access public
|
7517 |
+
*/
|
7518 |
+
var $fault;
|
7519 |
+
/**
|
7520 |
+
* @var faultcode
|
7521 |
+
* @access public
|
7522 |
+
*/
|
7523 |
+
var $faultcode;
|
7524 |
+
/**
|
7525 |
+
* @var faultstring
|
7526 |
+
* @access public
|
7527 |
+
*/
|
7528 |
+
var $faultstring;
|
7529 |
+
/**
|
7530 |
+
* @var faultdetail
|
7531 |
+
* @access public
|
7532 |
+
*/
|
7533 |
+
var $faultdetail;
|
7534 |
+
|
7535 |
+
/**
|
7536 |
+
* constructor
|
7537 |
+
*
|
7538 |
+
* @param mixed $endpoint SOAP server or WSDL URL (string), or wsdl instance (object)
|
7539 |
+
* @param mixed $wsdl optional, set to 'wsdl' or true if using WSDL
|
7540 |
+
* @param string $proxyhost optional
|
7541 |
+
* @param string $proxyport optional
|
7542 |
+
* @param string $proxyusername optional
|
7543 |
+
* @param string $proxypassword optional
|
7544 |
+
* @param integer $timeout set the connection timeout
|
7545 |
+
* @param integer $response_timeout set the response timeout
|
7546 |
+
* @param string $portName optional portName in WSDL document
|
7547 |
+
*
|
7548 |
+
* @access public
|
7549 |
+
*/
|
7550 |
+
function nusoap_client( $endpoint, $wsdl = false, $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $portName = '' ) {
|
7551 |
+
parent::nusoap_base();
|
7552 |
+
$this->endpoint = $endpoint;
|
7553 |
+
$this->proxyhost = $proxyhost;
|
7554 |
+
$this->proxyport = $proxyport;
|
7555 |
+
$this->proxyusername = $proxyusername;
|
7556 |
+
$this->proxypassword = $proxypassword;
|
7557 |
+
$this->timeout = $timeout;
|
7558 |
+
$this->response_timeout = $response_timeout;
|
7559 |
+
$this->portName = $portName;
|
7560 |
+
|
7561 |
+
$this->debug( "ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout" );
|
7562 |
+
$this->appendDebug( 'endpoint=' . $this->varDump( $endpoint ) );
|
7563 |
+
|
7564 |
+
// make values
|
7565 |
+
if ( $wsdl ) {
|
7566 |
+
if ( is_object( $endpoint ) && ( get_class( $endpoint ) == 'wsdl' ) ) {
|
7567 |
+
$this->wsdl = $endpoint;
|
7568 |
+
$this->endpoint = $this->wsdl->wsdl;
|
7569 |
+
$this->wsdlFile = $this->endpoint;
|
7570 |
+
$this->debug( 'existing wsdl instance created from ' . $this->endpoint );
|
7571 |
+
$this->checkWSDL();
|
7572 |
+
} else {
|
7573 |
+
$this->wsdlFile = $this->endpoint;
|
7574 |
+
$this->wsdl = null;
|
7575 |
+
$this->debug( 'will use lazy evaluation of wsdl from ' . $this->endpoint );
|
7576 |
+
}
|
7577 |
+
$this->endpointType = 'wsdl';
|
7578 |
+
} else {
|
7579 |
+
$this->debug( "instantiate SOAP with endpoint at $endpoint" );
|
7580 |
+
$this->endpointType = 'soap';
|
7581 |
+
}
|
7582 |
+
}
|
7583 |
+
|
7584 |
+
/**
|
7585 |
+
* calls method, returns PHP native type
|
7586 |
+
*
|
7587 |
+
* @param string $operation SOAP server URL or path
|
7588 |
+
* @param mixed $params An array, associative or simple, of the parameters
|
7589 |
+
* for the method call, or a string that is the XML
|
7590 |
+
* for the call. For rpc style, this call will
|
7591 |
+
* wrap the XML in a tag named after the method, as
|
7592 |
+
* well as the SOAP Envelope and Body. For document
|
7593 |
+
* style, this will only wrap with the Envelope and Body.
|
7594 |
+
* IMPORTANT: when using an array with document style,
|
7595 |
+
* in which case there
|
7596 |
+
* is really one parameter, the root of the fragment
|
7597 |
+
* used in the call, which encloses what programmers
|
7598 |
+
* normally think of parameters. A parameter array
|
7599 |
+
* *must* include the wrapper.
|
7600 |
+
* @param string $namespace optional method namespace (WSDL can override)
|
7601 |
+
* @param string $soapAction optional SOAPAction value (WSDL can override)
|
7602 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
7603 |
+
* @param boolean $rpcParams optional (no longer used)
|
7604 |
+
* @param string $style optional (rpc|document) the style to use when serializing parameters (WSDL can override)
|
7605 |
+
* @param string $use optional (encoded|literal) the use when serializing parameters (WSDL can override)
|
7606 |
+
*
|
7607 |
+
* @return mixed response from SOAP call, normally an associative array mirroring the structure of the XML response, false for certain fatal errors
|
7608 |
+
* @access public
|
7609 |
+
*/
|
7610 |
+
function call( $operation, $params = array(), $namespace = 'http://tempuri.org', $soapAction = '', $headers = false, $rpcParams = null, $style = 'rpc', $use = 'encoded' ) {
|
7611 |
+
$this->operation = $operation;
|
7612 |
+
$this->fault = false;
|
7613 |
+
$this->setError( '' );
|
7614 |
+
$this->request = '';
|
7615 |
+
$this->response = '';
|
7616 |
+
$this->responseData = '';
|
7617 |
+
$this->faultstring = '';
|
7618 |
+
$this->faultcode = '';
|
7619 |
+
$this->opData = array();
|
7620 |
+
|
7621 |
+
$this->debug( "call: operation=$operation, namespace=$namespace, soapAction=$soapAction, rpcParams=$rpcParams, style=$style, use=$use, endpointType=$this->endpointType" );
|
7622 |
+
$this->appendDebug( 'params=' . $this->varDump( $params ) );
|
7623 |
+
$this->appendDebug( 'headers=' . $this->varDump( $headers ) );
|
7624 |
+
if ( $headers ) {
|
7625 |
+
$this->requestHeaders = $headers;
|
7626 |
+
}
|
7627 |
+
if ( $this->endpointType == 'wsdl' && is_null( $this->wsdl ) ) {
|
7628 |
+
$this->loadWSDL();
|
7629 |
+
if ( $this->getError() ) {
|
7630 |
+
return false;
|
7631 |
+
}
|
7632 |
+
}
|
7633 |
+
// serialize parameters
|
7634 |
+
if ( $this->endpointType == 'wsdl' && $opData = $this->getOperationData( $operation ) ) {
|
7635 |
+
// use WSDL for operation
|
7636 |
+
$this->opData = $opData;
|
7637 |
+
$this->debug( "found operation" );
|
7638 |
+
$this->appendDebug( 'opData=' . $this->varDump( $opData ) );
|
7639 |
+
if ( isset( $opData['soapAction'] ) ) {
|
7640 |
+
$soapAction = $opData['soapAction'];
|
7641 |
+
}
|
7642 |
+
if ( ! $this->forceEndpoint ) {
|
7643 |
+
$this->endpoint = $opData['endpoint'];
|
7644 |
+
} else {
|
7645 |
+
$this->endpoint = $this->forceEndpoint;
|
7646 |
+
}
|
7647 |
+
$namespace = isset( $opData['input']['namespace'] ) ? $opData['input']['namespace'] : $namespace;
|
7648 |
+
$style = $opData['style'];
|
7649 |
+
$use = $opData['input']['use'];
|
7650 |
+
// add ns to ns array
|
7651 |
+
if ( $namespace != '' && ! isset( $this->wsdl->namespaces[ $namespace ] ) ) {
|
7652 |
+
$nsPrefix = 'ns' . rand( 1000, 9999 );
|
7653 |
+
$this->wsdl->namespaces[ $nsPrefix ] = $namespace;
|
7654 |
+
}
|
7655 |
+
$nsPrefix = $this->wsdl->getPrefixFromNamespace( $namespace );
|
7656 |
+
// serialize payload
|
7657 |
+
if ( is_string( $params ) ) {
|
7658 |
+
$this->debug( "serializing param string for WSDL operation $operation" );
|
7659 |
+
$payload = $params;
|
7660 |
+
} elseif ( is_array( $params ) ) {
|
7661 |
+
$this->debug( "serializing param array for WSDL operation $operation" );
|
7662 |
+
$payload = $this->wsdl->serializeRPCParameters( $operation, 'input', $params, $this->bindingType );
|
7663 |
+
} else {
|
7664 |
+
$this->debug( 'params must be array or string' );
|
7665 |
+
$this->setError( 'params must be array or string' );
|
7666 |
+
|
7667 |
+
return false;
|
7668 |
+
}
|
7669 |
+
$usedNamespaces = $this->wsdl->usedNamespaces;
|
7670 |
+
if ( isset( $opData['input']['encodingStyle'] ) ) {
|
7671 |
+
$encodingStyle = $opData['input']['encodingStyle'];
|
7672 |
+
} else {
|
7673 |
+
$encodingStyle = '';
|
7674 |
+
}
|
7675 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7676 |
+
$this->wsdl->clearDebug();
|
7677 |
+
if ( $errstr = $this->wsdl->getError() ) {
|
7678 |
+
$this->debug( 'got wsdl error: ' . $errstr );
|
7679 |
+
$this->setError( 'wsdl error: ' . $errstr );
|
7680 |
+
|
7681 |
+
return false;
|
7682 |
+
}
|
7683 |
+
} elseif ( $this->endpointType == 'wsdl' ) {
|
7684 |
+
// operation not in WSDL
|
7685 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7686 |
+
$this->wsdl->clearDebug();
|
7687 |
+
$this->setError( 'operation ' . $operation . ' not present in WSDL.' );
|
7688 |
+
$this->debug( "operation '$operation' not present in WSDL." );
|
7689 |
+
|
7690 |
+
return false;
|
7691 |
+
} else {
|
7692 |
+
// no WSDL
|
7693 |
+
//$this->namespaces['ns1'] = $namespace;
|
7694 |
+
$nsPrefix = 'ns' . rand( 1000, 9999 );
|
7695 |
+
// serialize
|
7696 |
+
$payload = '';
|
7697 |
+
if ( is_string( $params ) ) {
|
7698 |
+
$this->debug( "serializing param string for operation $operation" );
|
7699 |
+
$payload = $params;
|
7700 |
+
} elseif ( is_array( $params ) ) {
|
7701 |
+
$this->debug( "serializing param array for operation $operation" );
|
7702 |
+
foreach ( $params as $k => $v ) {
|
7703 |
+
$payload .= $this->serialize_val( $v, $k, false, false, false, false, $use );
|
7704 |
+
}
|
7705 |
+
} else {
|
7706 |
+
$this->debug( 'params must be array or string' );
|
7707 |
+
$this->setError( 'params must be array or string' );
|
7708 |
+
|
7709 |
+
return false;
|
7710 |
+
}
|
7711 |
+
$usedNamespaces = array();
|
7712 |
+
if ( $use == 'encoded' ) {
|
7713 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
7714 |
+
} else {
|
7715 |
+
$encodingStyle = '';
|
7716 |
+
}
|
7717 |
+
}
|
7718 |
+
// wrap RPC calls with method element
|
7719 |
+
if ( $style == 'rpc' ) {
|
7720 |
+
if ( $use == 'literal' ) {
|
7721 |
+
$this->debug( "wrapping RPC request with literal method element" );
|
7722 |
+
if ( $namespace ) {
|
7723 |
+
// 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
|
7724 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
7725 |
+
$payload .
|
7726 |
+
"</$nsPrefix:$operation>";
|
7727 |
+
} else {
|
7728 |
+
$payload = "<$operation>" . $payload . "</$operation>";
|
7729 |
+
}
|
7730 |
+
} else {
|
7731 |
+
$this->debug( "wrapping RPC request with encoded method element" );
|
7732 |
+
if ( $namespace ) {
|
7733 |
+
$payload = "<$nsPrefix:$operation xmlns:$nsPrefix=\"$namespace\">" .
|
7734 |
+
$payload .
|
7735 |
+
"</$nsPrefix:$operation>";
|
7736 |
+
} else {
|
7737 |
+
$payload = "<$operation>" .
|
7738 |
+
$payload .
|
7739 |
+
"</$operation>";
|
7740 |
+
}
|
7741 |
+
}
|
7742 |
+
}
|
7743 |
+
// serialize envelope
|
7744 |
+
$soapmsg = $this->serializeEnvelope( $payload, $this->requestHeaders, $usedNamespaces, $style, $use, $encodingStyle );
|
7745 |
+
$this->debug( "endpoint=$this->endpoint, soapAction=$soapAction, namespace=$namespace, style=$style, use=$use, encodingStyle=$encodingStyle" );
|
7746 |
+
$this->debug( 'SOAP message length=' . strlen( $soapmsg ) . ' contents (max 1000 bytes)=' . substr( $soapmsg, 0, 1000 ) );
|
7747 |
+
// send
|
7748 |
+
$return = $this->send( $this->getHTTPBody( $soapmsg ), $soapAction, $this->timeout, $this->response_timeout );
|
7749 |
+
if ( $errstr = $this->getError() ) {
|
7750 |
+
$this->debug( 'Error: ' . $errstr );
|
7751 |
+
|
7752 |
+
return false;
|
7753 |
+
} else {
|
7754 |
+
$this->return = $return;
|
7755 |
+
$this->debug( 'sent message successfully and got a(n) ' . gettype( $return ) );
|
7756 |
+
$this->appendDebug( 'return=' . $this->varDump( $return ) );
|
7757 |
+
|
7758 |
+
// fault?
|
7759 |
+
if ( is_array( $return ) && isset( $return['faultcode'] ) ) {
|
7760 |
+
$this->debug( 'got fault' );
|
7761 |
+
$this->setError( $return['faultcode'] . ': ' . $return['faultstring'] );
|
7762 |
+
$this->fault = true;
|
7763 |
+
foreach ( $return as $k => $v ) {
|
7764 |
+
$this->$k = $v;
|
7765 |
+
$this->debug( "$k = $v<br>" );
|
7766 |
+
}
|
7767 |
+
|
7768 |
+
return $return;
|
7769 |
+
} elseif ( $style == 'document' ) {
|
7770 |
+
// NOTE: if the response is defined to have multiple parts (i.e. unwrapped),
|
7771 |
+
// we are only going to return the first part here...sorry about that
|
7772 |
+
return $return;
|
7773 |
+
} else {
|
7774 |
+
// array of return values
|
7775 |
+
if ( is_array( $return ) ) {
|
7776 |
+
// multiple 'out' parameters, which we return wrapped up
|
7777 |
+
// in the array
|
7778 |
+
if ( sizeof( $return ) > 1 ) {
|
7779 |
+
return $return;
|
7780 |
+
}
|
7781 |
+
// single 'out' parameter (normally the return value)
|
7782 |
+
$return = array_shift( $return );
|
7783 |
+
$this->debug( 'return shifted value: ' );
|
7784 |
+
$this->appendDebug( $this->varDump( $return ) );
|
7785 |
+
|
7786 |
+
return $return;
|
7787 |
+
// nothing returned (ie, echoVoid)
|
7788 |
+
} else {
|
7789 |
+
return "";
|
7790 |
+
}
|
7791 |
+
}
|
7792 |
+
}
|
7793 |
+
}
|
7794 |
+
|
7795 |
+
/**
|
7796 |
+
* check WSDL passed as an instance or pulled from an endpoint
|
7797 |
+
*
|
7798 |
+
* @access private
|
7799 |
+
*/
|
7800 |
+
function checkWSDL() {
|
7801 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7802 |
+
$this->wsdl->clearDebug();
|
7803 |
+
$this->debug( 'checkWSDL' );
|
7804 |
+
// catch errors
|
7805 |
+
if ( $errstr = $this->wsdl->getError() ) {
|
7806 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7807 |
+
$this->wsdl->clearDebug();
|
7808 |
+
$this->debug( 'got wsdl error: ' . $errstr );
|
7809 |
+
$this->setError( 'wsdl error: ' . $errstr );
|
7810 |
+
} elseif ( $this->operations = $this->wsdl->getOperations( $this->portName, 'soap' ) ) {
|
7811 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7812 |
+
$this->wsdl->clearDebug();
|
7813 |
+
$this->bindingType = 'soap';
|
7814 |
+
$this->debug( 'got ' . count( $this->operations ) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType );
|
7815 |
+
} elseif ( $this->operations = $this->wsdl->getOperations( $this->portName, 'soap12' ) ) {
|
7816 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7817 |
+
$this->wsdl->clearDebug();
|
7818 |
+
$this->bindingType = 'soap12';
|
7819 |
+
$this->debug( 'got ' . count( $this->operations ) . ' operations from wsdl ' . $this->wsdlFile . ' for binding type ' . $this->bindingType );
|
7820 |
+
$this->debug( '**************** WARNING: SOAP 1.2 BINDING *****************' );
|
7821 |
+
} else {
|
7822 |
+
$this->appendDebug( $this->wsdl->getDebug() );
|
7823 |
+
$this->wsdl->clearDebug();
|
7824 |
+
$this->debug( 'getOperations returned false' );
|
7825 |
+
$this->setError( 'no operations defined in the WSDL document!' );
|
7826 |
+
}
|
7827 |
+
}
|
7828 |
+
|
7829 |
+
/**
|
7830 |
+
* instantiate wsdl object and parse wsdl file
|
7831 |
+
*
|
7832 |
+
* @access public
|
7833 |
+
*/
|
7834 |
+
function loadWSDL() {
|
7835 |
+
$this->debug( 'instantiating wsdl class with doc: ' . $this->wsdlFile );
|
7836 |
+
$this->wsdl = new wsdl( '', $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword, $this->timeout, $this->response_timeout, $this->curl_options, $this->use_curl );
|
7837 |
+
$this->wsdl->setCredentials( $this->username, $this->password, $this->authtype, $this->certRequest );
|
7838 |
+
$this->wsdl->fetchWSDL( $this->wsdlFile );
|
7839 |
+
$this->checkWSDL();
|
7840 |
+
}
|
7841 |
+
|
7842 |
+
/**
|
7843 |
+
* get available data pertaining to an operation
|
7844 |
+
*
|
7845 |
+
* @param string $operation operation name
|
7846 |
+
*
|
7847 |
+
* @return array array of data pertaining to the operation
|
7848 |
+
* @access public
|
7849 |
+
*/
|
7850 |
+
function getOperationData( $operation ) {
|
7851 |
+
if ( $this->endpointType == 'wsdl' && is_null( $this->wsdl ) ) {
|
7852 |
+
$this->loadWSDL();
|
7853 |
+
if ( $this->getError() ) {
|
7854 |
+
return false;
|
7855 |
+
}
|
7856 |
+
}
|
7857 |
+
if ( isset( $this->operations[ $operation ] ) ) {
|
7858 |
+
return $this->operations[ $operation ];
|
7859 |
+
}
|
7860 |
+
$this->debug( "No data for operation: $operation" );
|
7861 |
+
}
|
7862 |
+
|
7863 |
+
/**
|
7864 |
+
* send the SOAP message
|
7865 |
+
*
|
7866 |
+
* Note: if the operation has multiple return values
|
7867 |
+
* the return value of this method will be an array
|
7868 |
+
* of those values.
|
7869 |
+
*
|
7870 |
+
* @param string $msg a SOAPx4 soapmsg object
|
7871 |
+
* @param string $soapaction SOAPAction value
|
7872 |
+
* @param integer $timeout set connection timeout in seconds
|
7873 |
+
* @param integer $response_timeout set response timeout in seconds
|
7874 |
+
*
|
7875 |
+
* @return mixed native PHP types.
|
7876 |
+
* @access private
|
7877 |
+
*/
|
7878 |
+
function send( $msg, $soapaction = '', $timeout = 0, $response_timeout = 30 ) {
|
7879 |
+
$this->checkCookies();
|
7880 |
+
// detect transport
|
7881 |
+
switch ( true ) {
|
7882 |
+
// http(s)
|
7883 |
+
case preg_match( '/^http/', $this->endpoint ):
|
7884 |
+
$this->debug( 'transporting via HTTP' );
|
7885 |
+
if ( $this->persistentConnection == true && is_object( $this->persistentConnection ) ) {
|
7886 |
+
$http =& $this->persistentConnection;
|
7887 |
+
} else {
|
7888 |
+
$http = new soap_transport_http( $this->endpoint, $this->curl_options, $this->use_curl );
|
7889 |
+
if ( $this->persistentConnection ) {
|
7890 |
+
$http->usePersistentConnection();
|
7891 |
+
}
|
7892 |
+
}
|
7893 |
+
$http->setContentType( $this->getHTTPContentType(), $this->getHTTPContentTypeCharset() );
|
7894 |
+
$http->setSOAPAction( $soapaction );
|
7895 |
+
if ( $this->proxyhost && $this->proxyport ) {
|
7896 |
+
$http->setProxy( $this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword );
|
7897 |
+
}
|
7898 |
+
if ( $this->authtype != '' ) {
|
7899 |
+
$http->setCredentials( $this->username, $this->password, $this->authtype, array(), $this->certRequest );
|
7900 |
+
}
|
7901 |
+
if ( $this->http_encoding != '' ) {
|
7902 |
+
$http->setEncoding( $this->http_encoding );
|
7903 |
+
}
|
7904 |
+
$this->debug( 'sending message, length=' . strlen( $msg ) );
|
7905 |
+
if ( preg_match( '/^http:/', $this->endpoint ) ) {
|
7906 |
+
//if(strpos($this->endpoint,'http:')){
|
7907 |
+
$this->responseData = $http->send( $msg, $timeout, $response_timeout, $this->cookies );
|
7908 |
+
} elseif ( preg_match( '/^https/', $this->endpoint ) ) {
|
7909 |
+
//} elseif(strpos($this->endpoint,'https:')){
|
7910 |
+
//if(phpversion() == '4.3.0-dev'){
|
7911 |
+
//$response = $http->send($msg,$timeout,$response_timeout);
|
7912 |
+
//$this->request = $http->outgoing_payload;
|
7913 |
+
//$this->response = $http->incoming_payload;
|
7914 |
+
//} else
|
7915 |
+
$this->responseData = $http->sendHTTPS( $msg, $timeout, $response_timeout, $this->cookies );
|
7916 |
+
} else {
|
7917 |
+
$this->setError( 'no http/s in endpoint url' );
|
7918 |
+
}
|
7919 |
+
$this->request = $http->outgoing_payload;
|
7920 |
+
$this->response = $http->incoming_payload;
|
7921 |
+
$this->appendDebug( $http->getDebug() );
|
7922 |
+
$this->UpdateCookies( $http->incoming_cookies );
|
7923 |
+
|
7924 |
+
// save transport object if using persistent connections
|
7925 |
+
if ( $this->persistentConnection ) {
|
7926 |
+
$http->clearDebug();
|
7927 |
+
if ( ! is_object( $this->persistentConnection ) ) {
|
7928 |
+
$this->persistentConnection = $http;
|
7929 |
+
}
|
7930 |
+
}
|
7931 |
+
|
7932 |
+
if ( $err = $http->getError() ) {
|
7933 |
+
$this->setError( 'HTTP Error: ' . $err );
|
7934 |
+
|
7935 |
+
return false;
|
7936 |
+
} elseif ( $this->getError() ) {
|
7937 |
+
return false;
|
7938 |
+
} else {
|
7939 |
+
$this->debug( 'got response, length=' . strlen( $this->responseData ) . ' type=' . $http->incoming_headers['content-type'] );
|
7940 |
+
|
7941 |
+
return $this->parseResponse( $http->incoming_headers, $this->responseData );
|
7942 |
+
}
|
7943 |
+
break;
|
7944 |
+
default:
|
7945 |
+
$this->setError( 'no transport found, or selected transport is not yet supported!' );
|
7946 |
+
|
7947 |
+
return false;
|
7948 |
+
break;
|
7949 |
+
}
|
7950 |
+
}
|
7951 |
+
|
7952 |
+
/**
|
7953 |
+
* processes SOAP message returned from server
|
7954 |
+
*
|
7955 |
+
* @param array $headers The HTTP headers
|
7956 |
+
* @param string $data unprocessed response data from server
|
7957 |
+
*
|
7958 |
+
* @return mixed value of the message, decoded into a PHP type
|
7959 |
+
* @access private
|
7960 |
+
*/
|
7961 |
+
function parseResponse( $headers, $data ) {
|
7962 |
+
$this->debug( 'Entering parseResponse() for data of length ' . strlen( $data ) . ' headers:' );
|
7963 |
+
$this->appendDebug( $this->varDump( $headers ) );
|
7964 |
+
if ( ! isset( $headers['content-type'] ) ) {
|
7965 |
+
$this->setError( 'Response not of type text/xml (no content-type header)' );
|
7966 |
+
|
7967 |
+
return false;
|
7968 |
+
}
|
7969 |
+
if ( ! strstr( $headers['content-type'], 'text/xml' ) ) {
|
7970 |
+
$this->setError( 'Response not of type text/xml: ' . $headers['content-type'] );
|
7971 |
+
|
7972 |
+
return false;
|
7973 |
+
}
|
7974 |
+
if ( strpos( $headers['content-type'], '=' ) ) {
|
7975 |
+
$enc = str_replace( '"', '', substr( strstr( $headers["content-type"], '=' ), 1 ) );
|
7976 |
+
$this->debug( 'Got response encoding: ' . $enc );
|
7977 |
+
if ( preg_match( '/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc ) ) {
|
7978 |
+
$this->xml_encoding = strtoupper( $enc );
|
7979 |
+
} else {
|
7980 |
+
$this->xml_encoding = 'US-ASCII';
|
7981 |
+
}
|
7982 |
+
} else {
|
7983 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
7984 |
+
$this->xml_encoding = 'ISO-8859-1';
|
7985 |
+
}
|
7986 |
+
$this->debug( 'Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser' );
|
7987 |
+
$parser = new nusoap_parser( $data, $this->xml_encoding, $this->operation, $this->decode_utf8 );
|
7988 |
+
// add parser debug data to our debug
|
7989 |
+
$this->appendDebug( $parser->getDebug() );
|
7990 |
+
// if parse errors
|
7991 |
+
if ( $errstr = $parser->getError() ) {
|
7992 |
+
$this->setError( $errstr );
|
7993 |
+
// destroy the parser object
|
7994 |
+
unset( $parser );
|
7995 |
+
|
7996 |
+
return false;
|
7997 |
+
} else {
|
7998 |
+
// get SOAP headers
|
7999 |
+
$this->responseHeaders = $parser->getHeaders();
|
8000 |
+
// get SOAP headers
|
8001 |
+
$this->responseHeader = $parser->get_soapheader();
|
8002 |
+
// get decoded message
|
8003 |
+
$return = $parser->get_soapbody();
|
8004 |
+
// add document for doclit support
|
8005 |
+
$this->document = $parser->document;
|
8006 |
+
// destroy the parser object
|
8007 |
+
unset( $parser );
|
8008 |
+
|
8009 |
+
// return decode message
|
8010 |
+
return $return;
|
8011 |
+
}
|
8012 |
+
}
|
8013 |
+
|
8014 |
+
/**
|
8015 |
+
* sets user-specified cURL options
|
8016 |
+
*
|
8017 |
+
* @param mixed $option The cURL option (always integer?)
|
8018 |
+
* @param mixed $value The cURL option value
|
8019 |
+
*
|
8020 |
+
* @access public
|
8021 |
+
*/
|
8022 |
+
function setCurlOption( $option, $value ) {
|
8023 |
+
$this->debug( "setCurlOption option=$option, value=" );
|
8024 |
+
$this->appendDebug( $this->varDump( $value ) );
|
8025 |
+
$this->curl_options[ $option ] = $value;
|
8026 |
+
}
|
8027 |
+
|
8028 |
+
/**
|
8029 |
+
* sets the SOAP endpoint, which can override WSDL
|
8030 |
+
*
|
8031 |
+
* @param string $endpoint The endpoint URL to use, or empty string or false to prevent override
|
8032 |
+
*
|
8033 |
+
* @access public
|
8034 |
+
*/
|
8035 |
+
function setEndpoint( $endpoint ) {
|
8036 |
+
$this->debug( "setEndpoint(\"$endpoint\")" );
|
8037 |
+
$this->forceEndpoint = $endpoint;
|
8038 |
+
}
|
8039 |
+
|
8040 |
+
/**
|
8041 |
+
* set the SOAP headers
|
8042 |
+
*
|
8043 |
+
* @param mixed $headers String of XML with SOAP header content, or array of soapval objects for SOAP headers
|
8044 |
+
*
|
8045 |
+
* @access public
|
8046 |
+
*/
|
8047 |
+
function setHeaders( $headers ) {
|
8048 |
+
$this->debug( "setHeaders headers=" );
|
8049 |
+
$this->appendDebug( $this->varDump( $headers ) );
|
8050 |
+
$this->requestHeaders = $headers;
|
8051 |
+
}
|
8052 |
+
|
8053 |
+
/**
|
8054 |
+
* get the SOAP response headers (namespace resolution incomplete)
|
8055 |
+
*
|
8056 |
+
* @return string
|
8057 |
+
* @access public
|
8058 |
+
*/
|
8059 |
+
function getHeaders() {
|
8060 |
+
return $this->responseHeaders;
|
8061 |
+
}
|
8062 |
+
|
8063 |
+
/**
|
8064 |
+
* get the SOAP response Header (parsed)
|
8065 |
+
*
|
8066 |
+
* @return mixed
|
8067 |
+
* @access public
|
8068 |
+
*/
|
8069 |
+
function getHeader() {
|
8070 |
+
return $this->responseHeader;
|
8071 |
+
}
|
8072 |
+
|
8073 |
+
/**
|
8074 |
+
* set proxy info here
|
8075 |
+
*
|
8076 |
+
* @param string $proxyhost
|
8077 |
+
* @param string $proxyport
|
8078 |
+
* @param string $proxyusername
|
8079 |
+
* @param string $proxypassword
|
8080 |
+
*
|
8081 |
+
* @access public
|
8082 |
+
*/
|
8083 |
+
function setHTTPProxy( $proxyhost, $proxyport, $proxyusername = '', $proxypassword = '' ) {
|
8084 |
+
$this->proxyhost = $proxyhost;
|
8085 |
+
$this->proxyport = $proxyport;
|
8086 |
+
$this->proxyusername = $proxyusername;
|
8087 |
+
$this->proxypassword = $proxypassword;
|
8088 |
+
}
|
8089 |
+
|
8090 |
+
/**
|
8091 |
+
* if authenticating, set user credentials here
|
8092 |
+
*
|
8093 |
+
* @param string $username
|
8094 |
+
* @param string $password
|
8095 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
8096 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
8097 |
+
*
|
8098 |
+
* @access public
|
8099 |
+
*/
|
8100 |
+
function setCredentials( $username, $password, $authtype = 'basic', $certRequest = array() ) {
|
8101 |
+
$this->debug( "setCredentials username=$username authtype=$authtype certRequest=" );
|
8102 |
+
$this->appendDebug( $this->varDump( $certRequest ) );
|
8103 |
+
$this->username = $username;
|
8104 |
+
$this->password = $password;
|
8105 |
+
$this->authtype = $authtype;
|
8106 |
+
$this->certRequest = $certRequest;
|
8107 |
+
}
|
8108 |
+
|
8109 |
+
/**
|
8110 |
+
* use HTTP encoding
|
8111 |
+
*
|
8112 |
+
* @param string $enc HTTP encoding
|
8113 |
+
*
|
8114 |
+
* @access public
|
8115 |
+
*/
|
8116 |
+
function setHTTPEncoding( $enc = 'gzip, deflate' ) {
|
8117 |
+
$this->debug( "setHTTPEncoding(\"$enc\")" );
|
8118 |
+
$this->http_encoding = $enc;
|
8119 |
+
}
|
8120 |
+
|
8121 |
+
/**
|
8122 |
+
* Set whether to try to use cURL connections if possible
|
8123 |
+
*
|
8124 |
+
* @param boolean $use Whether to try to use cURL
|
8125 |
+
*
|
8126 |
+
* @access public
|
8127 |
+
*/
|
8128 |
+
function setUseCURL( $use ) {
|
8129 |
+
$this->debug( "setUseCURL($use)" );
|
8130 |
+
$this->use_curl = $use;
|
8131 |
+
}
|
8132 |
+
|
8133 |
+
/**
|
8134 |
+
* use HTTP persistent connections if possible
|
8135 |
+
*
|
8136 |
+
* @access public
|
8137 |
+
*/
|
8138 |
+
function useHTTPPersistentConnection() {
|
8139 |
+
$this->debug( "useHTTPPersistentConnection" );
|
8140 |
+
$this->persistentConnection = true;
|
8141 |
+
}
|
8142 |
+
|
8143 |
+
/**
|
8144 |
+
* gets the default RPC parameter setting.
|
8145 |
+
* If true, default is that call params are like RPC even for document style.
|
8146 |
+
* Each call() can override this value.
|
8147 |
+
*
|
8148 |
+
* This is no longer used.
|
8149 |
+
*
|
8150 |
+
* @return boolean
|
8151 |
+
* @access public
|
8152 |
+
* @deprecated
|
8153 |
+
*/
|
8154 |
+
function getDefaultRpcParams() {
|
8155 |
+
return $this->defaultRpcParams;
|
8156 |
+
}
|
8157 |
+
|
8158 |
+
/**
|
8159 |
+
* sets the default RPC parameter setting.
|
8160 |
+
* If true, default is that call params are like RPC even for document style
|
8161 |
+
* Each call() can override this value.
|
8162 |
+
*
|
8163 |
+
* This is no longer used.
|
8164 |
+
*
|
8165 |
+
* @param boolean $rpcParams
|
8166 |
+
*
|
8167 |
+
* @access public
|
8168 |
+
* @deprecated
|
8169 |
+
*/
|
8170 |
+
function setDefaultRpcParams( $rpcParams ) {
|
8171 |
+
$this->defaultRpcParams = $rpcParams;
|
8172 |
+
}
|
8173 |
+
|
8174 |
+
/**
|
8175 |
+
* dynamically creates an instance of a proxy class,
|
8176 |
+
* allowing user to directly call methods from wsdl
|
8177 |
+
*
|
8178 |
+
* @return object soap_proxy object
|
8179 |
+
* @access public
|
8180 |
+
*/
|
8181 |
+
function getProxy() {
|
8182 |
+
$r = rand();
|
8183 |
+
$evalStr = $this->_getProxyClassCode( $r );
|
8184 |
+
//$this->debug("proxy class: $evalStr");
|
8185 |
+
if ( $this->getError() ) {
|
8186 |
+
$this->debug( "Error from _getProxyClassCode, so return NULL" );
|
8187 |
+
|
8188 |
+
return null;
|
8189 |
+
}
|
8190 |
+
// eval the class
|
8191 |
+
eval( $evalStr );
|
8192 |
+
// instantiate proxy object
|
8193 |
+
eval( "\$proxy = new nusoap_proxy_$r('');" );
|
8194 |
+
// transfer current wsdl data to the proxy thereby avoiding parsing the wsdl twice
|
8195 |
+
$proxy->endpointType = 'wsdl';
|
8196 |
+
$proxy->wsdlFile = $this->wsdlFile;
|
8197 |
+
$proxy->wsdl = $this->wsdl;
|
8198 |
+
$proxy->operations = $this->operations;
|
8199 |
+
$proxy->defaultRpcParams = $this->defaultRpcParams;
|
8200 |
+
// transfer other state
|
8201 |
+
$proxy->soap_defencoding = $this->soap_defencoding;
|
8202 |
+
$proxy->username = $this->username;
|
8203 |
+
$proxy->password = $this->password;
|
8204 |
+
$proxy->authtype = $this->authtype;
|
8205 |
+
$proxy->certRequest = $this->certRequest;
|
8206 |
+
$proxy->requestHeaders = $this->requestHeaders;
|
8207 |
+
$proxy->endpoint = $this->endpoint;
|
8208 |
+
$proxy->forceEndpoint = $this->forceEndpoint;
|
8209 |
+
$proxy->proxyhost = $this->proxyhost;
|
8210 |
+
$proxy->proxyport = $this->proxyport;
|
8211 |
+
$proxy->proxyusername = $this->proxyusername;
|
8212 |
+
$proxy->proxypassword = $this->proxypassword;
|
8213 |
+
$proxy->http_encoding = $this->http_encoding;
|
8214 |
+
$proxy->timeout = $this->timeout;
|
8215 |
+
$proxy->response_timeout = $this->response_timeout;
|
8216 |
+
$proxy->persistentConnection = &$this->persistentConnection;
|
8217 |
+
$proxy->decode_utf8 = $this->decode_utf8;
|
8218 |
+
$proxy->curl_options = $this->curl_options;
|
8219 |
+
$proxy->bindingType = $this->bindingType;
|
8220 |
+
$proxy->use_curl = $this->use_curl;
|
8221 |
+
|
8222 |
+
return $proxy;
|
8223 |
+
}
|
8224 |
+
|
8225 |
+
/**
|
8226 |
+
* dynamically creates proxy class code
|
8227 |
+
*
|
8228 |
+
* @return string PHP/NuSOAP code for the proxy class
|
8229 |
+
* @access private
|
8230 |
+
*/
|
8231 |
+
function _getProxyClassCode( $r ) {
|
8232 |
+
$this->debug( "in getProxy endpointType=$this->endpointType" );
|
8233 |
+
$this->appendDebug( "wsdl=" . $this->varDump( $this->wsdl ) );
|
8234 |
+
if ( $this->endpointType != 'wsdl' ) {
|
8235 |
+
$evalStr = 'A proxy can only be created for a WSDL client';
|
8236 |
+
$this->setError( $evalStr );
|
8237 |
+
$evalStr = "echo \"$evalStr\";";
|
8238 |
+
|
8239 |
+
return $evalStr;
|
8240 |
+
}
|
8241 |
+
if ( $this->endpointType == 'wsdl' && is_null( $this->wsdl ) ) {
|
8242 |
+
$this->loadWSDL();
|
8243 |
+
if ( $this->getError() ) {
|
8244 |
+
return "echo \"" . $this->getError() . "\";";
|
8245 |
+
}
|
8246 |
+
}
|
8247 |
+
$evalStr = '';
|
8248 |
+
foreach ( $this->operations as $operation => $opData ) {
|
8249 |
+
if ( $operation != '' ) {
|
8250 |
+
// create param string and param comment string
|
8251 |
+
if ( sizeof( $opData['input']['parts'] ) > 0 ) {
|
8252 |
+
$paramStr = '';
|
8253 |
+
$paramArrayStr = '';
|
8254 |
+
$paramCommentStr = '';
|
8255 |
+
foreach ( $opData['input']['parts'] as $name => $type ) {
|
8256 |
+
$paramStr .= "\$$name, ";
|
8257 |
+
$paramArrayStr .= "'$name' => \$$name, ";
|
8258 |
+
$paramCommentStr .= "$type \$$name, ";
|
8259 |
+
}
|
8260 |
+
$paramStr = substr( $paramStr, 0, strlen( $paramStr ) - 2 );
|
8261 |
+
$paramArrayStr = substr( $paramArrayStr, 0, strlen( $paramArrayStr ) - 2 );
|
8262 |
+
$paramCommentStr = substr( $paramCommentStr, 0, strlen( $paramCommentStr ) - 2 );
|
8263 |
+
} else {
|
8264 |
+
$paramStr = '';
|
8265 |
+
$paramArrayStr = '';
|
8266 |
+
$paramCommentStr = 'void';
|
8267 |
+
}
|
8268 |
+
$opData['namespace'] = ! isset( $opData['namespace'] ) ? 'http://testuri.com' : $opData['namespace'];
|
8269 |
+
$evalStr .= "// $paramCommentStr
|
8270 |
+
function " . str_replace( '.', '__', $operation ) . "($paramStr) {
|
8271 |
+
\$params = array($paramArrayStr);
|
8272 |
+
return \$this->call('$operation', \$params, '" . $opData['namespace'] . "', '" . ( isset( $opData['soapAction'] ) ? $opData['soapAction'] : '' ) . "');
|
8273 |
+
}
|
8274 |
+
";
|
8275 |
+
unset( $paramStr );
|
8276 |
+
unset( $paramCommentStr );
|
8277 |
+
}
|
8278 |
+
}
|
8279 |
+
$evalStr = 'class nusoap_proxy_' . $r . ' extends nusoap_client {
|
8280 |
+
' . $evalStr . '
|
8281 |
+
}';
|
8282 |
+
|
8283 |
+
return $evalStr;
|
8284 |
+
}
|
8285 |
+
|
8286 |
+
/**
|
8287 |
+
* dynamically creates proxy class code
|
8288 |
+
*
|
8289 |
+
* @return string PHP/NuSOAP code for the proxy class
|
8290 |
+
* @access public
|
8291 |
+
*/
|
8292 |
+
function getProxyClassCode() {
|
8293 |
+
$r = rand();
|
8294 |
+
|
8295 |
+
return $this->_getProxyClassCode( $r );
|
8296 |
+
}
|
8297 |
+
|
8298 |
+
/**
|
8299 |
+
* gets the HTTP body for the current request.
|
8300 |
+
*
|
8301 |
+
* @param string $soapmsg The SOAP payload
|
8302 |
+
*
|
8303 |
+
* @return string The HTTP body, which includes the SOAP payload
|
8304 |
+
* @access private
|
8305 |
+
*/
|
8306 |
+
function getHTTPBody( $soapmsg ) {
|
8307 |
+
return $soapmsg;
|
8308 |
+
}
|
8309 |
+
|
8310 |
+
/**
|
8311 |
+
* gets the HTTP content type for the current request.
|
8312 |
+
*
|
8313 |
+
* Note: getHTTPBody must be called before this.
|
8314 |
+
*
|
8315 |
+
* @return string the HTTP content type for the current request.
|
8316 |
+
* @access private
|
8317 |
+
*/
|
8318 |
+
function getHTTPContentType() {
|
8319 |
+
return 'text/xml';
|
8320 |
+
}
|
8321 |
+
|
8322 |
+
/**
|
8323 |
+
* gets the HTTP content type charset for the current request.
|
8324 |
+
* returns false for non-text content types.
|
8325 |
+
*
|
8326 |
+
* Note: getHTTPBody must be called before this.
|
8327 |
+
*
|
8328 |
+
* @return string the HTTP content type charset for the current request.
|
8329 |
+
* @access private
|
8330 |
+
*/
|
8331 |
+
function getHTTPContentTypeCharset() {
|
8332 |
+
return $this->soap_defencoding;
|
8333 |
+
}
|
8334 |
+
|
8335 |
+
/*
|
8336 |
+
* whether or not parser should decode utf8 element content
|
8337 |
+
*
|
8338 |
+
* @return always returns true
|
8339 |
+
* @access public
|
8340 |
+
*/
|
8341 |
+
function decodeUTF8( $bool ) {
|
8342 |
+
$this->decode_utf8 = $bool;
|
8343 |
+
|
8344 |
+
return true;
|
8345 |
+
}
|
8346 |
+
|
8347 |
+
/**
|
8348 |
+
* adds a new Cookie into $this->cookies array
|
8349 |
+
*
|
8350 |
+
* @param string $name Cookie Name
|
8351 |
+
* @param string $value Cookie Value
|
8352 |
+
*
|
8353 |
+
* @return boolean if cookie-set was successful returns true, else false
|
8354 |
+
* @access public
|
8355 |
+
*/
|
8356 |
+
function setCookie( $name, $value ) {
|
8357 |
+
if ( strlen( $name ) == 0 ) {
|
8358 |
+
return false;
|
8359 |
+
}
|
8360 |
+
$this->cookies[] = array( 'name' => $name, 'value' => $value );
|
8361 |
+
|
8362 |
+
return true;
|
8363 |
+
}
|
8364 |
+
|
8365 |
+
/**
|
8366 |
+
* gets all Cookies
|
8367 |
+
*
|
8368 |
+
* @return array with all internal cookies
|
8369 |
+
* @access public
|
8370 |
+
*/
|
8371 |
+
function getCookies() {
|
8372 |
+
return $this->cookies;
|
8373 |
+
}
|
8374 |
+
|
8375 |
+
/**
|
8376 |
+
* checks all Cookies and delete those which are expired
|
8377 |
+
*
|
8378 |
+
* @return boolean always return true
|
8379 |
+
* @access private
|
8380 |
+
*/
|
8381 |
+
function checkCookies() {
|
8382 |
+
if ( sizeof( $this->cookies ) == 0 ) {
|
8383 |
+
return true;
|
8384 |
+
}
|
8385 |
+
$this->debug( 'checkCookie: check ' . sizeof( $this->cookies ) . ' cookies' );
|
8386 |
+
$curr_cookies = $this->cookies;
|
8387 |
+
$this->cookies = array();
|
8388 |
+
foreach ( $curr_cookies as $cookie ) {
|
8389 |
+
if ( ! is_array( $cookie ) ) {
|
8390 |
+
$this->debug( 'Remove cookie that is not an array' );
|
8391 |
+
continue;
|
8392 |
+
}
|
8393 |
+
if ( ( isset( $cookie['expires'] ) ) && ( ! empty( $cookie['expires'] ) ) ) {
|
8394 |
+
if ( strtotime( $cookie['expires'] ) > time() ) {
|
8395 |
+
$this->cookies[] = $cookie;
|
8396 |
+
} else {
|
8397 |
+
$this->debug( 'Remove expired cookie ' . $cookie['name'] );
|
8398 |
+
}
|
8399 |
+
} else {
|
8400 |
+
$this->cookies[] = $cookie;
|
8401 |
+
}
|
8402 |
+
}
|
8403 |
+
$this->debug( 'checkCookie: ' . sizeof( $this->cookies ) . ' cookies left in array' );
|
8404 |
+
|
8405 |
+
return true;
|
8406 |
+
}
|
8407 |
+
|
8408 |
+
/**
|
8409 |
+
* updates the current cookies with a new set
|
8410 |
+
*
|
8411 |
+
* @param array $cookies new cookies with which to update current ones
|
8412 |
+
*
|
8413 |
+
* @return boolean always return true
|
8414 |
+
* @access private
|
8415 |
+
*/
|
8416 |
+
function UpdateCookies( $cookies ) {
|
8417 |
+
if ( sizeof( $this->cookies ) == 0 ) {
|
8418 |
+
// no existing cookies: take whatever is new
|
8419 |
+
if ( sizeof( $cookies ) > 0 ) {
|
8420 |
+
$this->debug( 'Setting new cookie(s)' );
|
8421 |
+
$this->cookies = $cookies;
|
8422 |
+
}
|
8423 |
+
|
8424 |
+
return true;
|
8425 |
+
}
|
8426 |
+
if ( sizeof( $cookies ) == 0 ) {
|
8427 |
+
// no new cookies: keep what we've got
|
8428 |
+
return true;
|
8429 |
+
}
|
8430 |
+
// merge
|
8431 |
+
foreach ( $cookies as $newCookie ) {
|
8432 |
+
if ( ! is_array( $newCookie ) ) {
|
8433 |
+
continue;
|
8434 |
+
}
|
8435 |
+
if ( ( ! isset( $newCookie['name'] ) ) || ( ! isset( $newCookie['value'] ) ) ) {
|
8436 |
+
continue;
|
8437 |
+
}
|
8438 |
+
$newName = $newCookie['name'];
|
8439 |
+
|
8440 |
+
$found = false;
|
8441 |
+
for ( $i = 0; $i < count( $this->cookies ); $i ++ ) {
|
8442 |
+
$cookie = $this->cookies[ $i ];
|
8443 |
+
if ( ! is_array( $cookie ) ) {
|
8444 |
+
continue;
|
8445 |
+
}
|
8446 |
+
if ( ! isset( $cookie['name'] ) ) {
|
8447 |
+
continue;
|
8448 |
+
}
|
8449 |
+
if ( $newName != $cookie['name'] ) {
|
8450 |
+
continue;
|
8451 |
+
}
|
8452 |
+
$newDomain = isset( $newCookie['domain'] ) ? $newCookie['domain'] : 'NODOMAIN';
|
8453 |
+
$domain = isset( $cookie['domain'] ) ? $cookie['domain'] : 'NODOMAIN';
|
8454 |
+
if ( $newDomain != $domain ) {
|
8455 |
+
continue;
|
8456 |
+
}
|
8457 |
+
$newPath = isset( $newCookie['path'] ) ? $newCookie['path'] : 'NOPATH';
|
8458 |
+
$path = isset( $cookie['path'] ) ? $cookie['path'] : 'NOPATH';
|
8459 |
+
if ( $newPath != $path ) {
|
8460 |
+
continue;
|
8461 |
+
}
|
8462 |
+
$this->cookies[ $i ] = $newCookie;
|
8463 |
+
$found = true;
|
8464 |
+
$this->debug( 'Update cookie ' . $newName . '=' . $newCookie['value'] );
|
8465 |
+
break;
|
8466 |
+
}
|
8467 |
+
if ( ! $found ) {
|
8468 |
+
$this->debug( 'Add cookie ' . $newName . '=' . $newCookie['value'] );
|
8469 |
+
$this->cookies[] = $newCookie;
|
8470 |
+
}
|
8471 |
+
}
|
8472 |
+
|
8473 |
+
return true;
|
8474 |
+
}
|
8475 |
+
}
|
8476 |
+
|
8477 |
+
if ( ! extension_loaded( 'soap' ) ) {
|
8478 |
+
/**
|
8479 |
+
* For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.
|
8480 |
+
*/
|
8481 |
+
class soapclient extends nusoap_client {
|
8482 |
+
}
|
8483 |
+
}
|
8484 |
+
?>
|
includes/lib/nusoap-php7.php
ADDED
@@ -0,0 +1,8339 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/*
|
4 |
+
$Id: nusoap.php,v 1.123 2010/04/26 20:15:08 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 Help forum on the project home page.
|
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 |
+
/*
|
41 |
+
* Some of the standards implmented in whole or part by NuSOAP:
|
42 |
+
*
|
43 |
+
* SOAP 1.1 (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/)
|
44 |
+
* WSDL 1.1 (http://www.w3.org/TR/2001/NOTE-wsdl-20010315)
|
45 |
+
* SOAP Messages With Attachments (http://www.w3.org/TR/SOAP-attachments)
|
46 |
+
* XML 1.0 (http://www.w3.org/TR/2006/REC-xml-20060816/)
|
47 |
+
* Namespaces in XML 1.0 (http://www.w3.org/TR/2006/REC-xml-names-20060816/)
|
48 |
+
* XML Schema 1.0 (http://www.w3.org/TR/xmlschema-0/)
|
49 |
+
* RFC 2045 Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies
|
50 |
+
* RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1
|
51 |
+
* RFC 2617 HTTP Authentication: Basic and Digest Access Authentication
|
52 |
+
*/
|
53 |
+
|
54 |
+
/* load classes
|
55 |
+
|
56 |
+
// necessary classes
|
57 |
+
require_once('class.soapclient.php');
|
58 |
+
require_once('class.soap_val.php');
|
59 |
+
require_once('class.soap_parser.php');
|
60 |
+
require_once('class.soap_fault.php');
|
61 |
+
|
62 |
+
// transport classes
|
63 |
+
require_once('class.soap_transport_http.php');
|
64 |
+
|
65 |
+
// optional add-on classes
|
66 |
+
require_once('class.xmlschema.php');
|
67 |
+
require_once('class.wsdl.php');
|
68 |
+
|
69 |
+
// server class
|
70 |
+
require_once('class.soap_server.php');*/
|
71 |
+
|
72 |
+
// class variable emulation
|
73 |
+
// cf. http://www.webkreator.com/php/techniques/php-static-class-variables.html
|
74 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = 9;
|
75 |
+
|
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.123 2010/04/26 20:15:08 snichol Exp $
|
84 |
+
* @access public
|
85 |
+
*/
|
86 |
+
class nusoap_base
|
87 |
+
{
|
88 |
+
/**
|
89 |
+
* Identification for HTTP headers.
|
90 |
+
*
|
91 |
+
* @var string
|
92 |
+
* @access private
|
93 |
+
*/
|
94 |
+
var $title = 'NuSOAP';
|
95 |
+
/**
|
96 |
+
* Version for HTTP headers.
|
97 |
+
*
|
98 |
+
* @var string
|
99 |
+
* @access private
|
100 |
+
*/
|
101 |
+
var $version = '0.9.5';
|
102 |
+
/**
|
103 |
+
* CVS revision for HTTP headers.
|
104 |
+
*
|
105 |
+
* @var string
|
106 |
+
* @access private
|
107 |
+
*/
|
108 |
+
var $revision = '$Revision: 1.123 $';
|
109 |
+
/**
|
110 |
+
* Current error string (manipulated by getError/setError)
|
111 |
+
*
|
112 |
+
* @var string
|
113 |
+
* @access private
|
114 |
+
*/
|
115 |
+
var $error_str = '';
|
116 |
+
/**
|
117 |
+
* Current debug string (manipulated by debug/appendDebug/clearDebug/getDebug/getDebugAsXMLComment)
|
118 |
+
*
|
119 |
+
* @var string
|
120 |
+
* @access private
|
121 |
+
*/
|
122 |
+
var $debug_str = '';
|
123 |
+
/**
|
124 |
+
* toggles automatic encoding of special characters as entities
|
125 |
+
* (should always be true, I think)
|
126 |
+
*
|
127 |
+
* @var boolean
|
128 |
+
* @access private
|
129 |
+
*/
|
130 |
+
var $charencoding = true;
|
131 |
+
/**
|
132 |
+
* the debug level for this instance
|
133 |
+
*
|
134 |
+
* @var integer
|
135 |
+
* @access private
|
136 |
+
*/
|
137 |
+
var $debugLevel;
|
138 |
+
|
139 |
+
/**
|
140 |
+
* set schema version
|
141 |
+
*
|
142 |
+
* @var string
|
143 |
+
* @access public
|
144 |
+
*/
|
145 |
+
var $XMLSchemaVersion = 'http://www.w3.org/2001/XMLSchema';
|
146 |
+
|
147 |
+
/**
|
148 |
+
* charset encoding for outgoing messages
|
149 |
+
*
|
150 |
+
* @var string
|
151 |
+
* @access public
|
152 |
+
*/
|
153 |
+
var $soap_defencoding = 'ISO-8859-1';
|
154 |
+
//var $soap_defencoding = 'UTF-8';
|
155 |
+
|
156 |
+
/**
|
157 |
+
* namespaces in an array of prefix => uri
|
158 |
+
*
|
159 |
+
* this is "seeded" by a set of constants, but it may be altered by code
|
160 |
+
*
|
161 |
+
* @var array
|
162 |
+
* @access public
|
163 |
+
*/
|
164 |
+
var $namespaces = array(
|
165 |
+
'SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
|
166 |
+
'xsd' => 'http://www.w3.org/2001/XMLSchema',
|
167 |
+
'xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
168 |
+
'SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/'
|
169 |
+
);
|
170 |
+
|
171 |
+
/**
|
172 |
+
* namespaces used in the current context, e.g. during serialization
|
173 |
+
*
|
174 |
+
* @var array
|
175 |
+
* @access private
|
176 |
+
*/
|
177 |
+
var $usedNamespaces = array();
|
178 |
+
|
179 |
+
/**
|
180 |
+
* XML Schema types in an array of uri => (array of xml type => php type)
|
181 |
+
* is this legacy yet?
|
182 |
+
* no, this is used by the nusoap_xmlschema class to verify type => namespace mappings.
|
183 |
+
*
|
184 |
+
* @var array
|
185 |
+
* @access public
|
186 |
+
*/
|
187 |
+
var $typemap = array(
|
188 |
+
'http://www.w3.org/2001/XMLSchema' => array(
|
189 |
+
'string' => 'string', 'boolean' => 'boolean', 'float' => 'double', 'double' => 'double', 'decimal' => 'double',
|
190 |
+
'duration' => '', 'dateTime' => 'string', 'time' => 'string', 'date' => 'string', 'gYearMonth' => '',
|
191 |
+
'gYear' => '', 'gMonthDay' => '', 'gDay' => '', 'gMonth' => '', 'hexBinary' => 'string', 'base64Binary' => 'string',
|
192 |
+
// abstract "any" types
|
193 |
+
'anyType' => 'string', 'anySimpleType' => 'string',
|
194 |
+
// derived datatypes
|
195 |
+
'normalizedString' => 'string', 'token' => 'string', 'language' => '', 'NMTOKEN' => '', 'NMTOKENS' => '', 'Name' => '', 'NCName' => '', 'ID' => '',
|
196 |
+
'IDREF' => '', 'IDREFS' => '', 'ENTITY' => '', 'ENTITIES' => '', 'integer' => 'integer', 'nonPositiveInteger' => 'integer',
|
197 |
+
'negativeInteger' => 'integer', 'long' => 'integer', 'int' => 'integer', 'short' => 'integer', 'byte' => 'integer', 'nonNegativeInteger' => 'integer',
|
198 |
+
'unsignedLong' => '', 'unsignedInt' => '', 'unsignedShort' => '', 'unsignedByte' => '', 'positiveInteger' => ''),
|
199 |
+
'http://www.w3.org/2000/10/XMLSchema' => array(
|
200 |
+
'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double',
|
201 |
+
'float' => 'double', 'dateTime' => 'string',
|
202 |
+
'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array'),
|
203 |
+
'http://www.w3.org/1999/XMLSchema' => array(
|
204 |
+
'i4' => '', 'int' => 'integer', 'boolean' => 'boolean', 'string' => 'string', 'double' => 'double',
|
205 |
+
'float' => 'double', 'dateTime' => 'string',
|
206 |
+
'timeInstant' => 'string', 'base64Binary' => 'string', 'base64' => 'string', 'ur-type' => 'array'),
|
207 |
+
'http://soapinterop.org/xsd' => array('SOAPStruct' => 'struct'),
|
208 |
+
'http://schemas.xmlsoap.org/soap/encoding/' => array('base64' => 'string', 'array' => 'array', 'Array' => 'array'),
|
209 |
+
'http://xml.apache.org/xml-soap' => array('Map')
|
210 |
+
);
|
211 |
+
|
212 |
+
/**
|
213 |
+
* XML entities to convert
|
214 |
+
*
|
215 |
+
* @var array
|
216 |
+
* @access public
|
217 |
+
* @deprecated
|
218 |
+
* @see expandEntities
|
219 |
+
*/
|
220 |
+
var $xmlEntities = array('quot' => '"', 'amp' => '&',
|
221 |
+
'lt' => '<', 'gt' => '>', 'apos' => "'");
|
222 |
+
|
223 |
+
/**
|
224 |
+
* constructor
|
225 |
+
*
|
226 |
+
* @access public
|
227 |
+
*/
|
228 |
+
function __construct()
|
229 |
+
{
|
230 |
+
$this->debugLevel = $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* gets the global debug level, which applies to future instances
|
235 |
+
*
|
236 |
+
* @return integer Debug level 0-9, where 0 turns off
|
237 |
+
* @access public
|
238 |
+
*/
|
239 |
+
function getGlobalDebugLevel()
|
240 |
+
{
|
241 |
+
return $GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'];
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* sets the global debug level, which applies to future instances
|
246 |
+
*
|
247 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
248 |
+
* @access public
|
249 |
+
*/
|
250 |
+
function setGlobalDebugLevel($level)
|
251 |
+
{
|
252 |
+
$GLOBALS['_transient']['static']['nusoap_base']['globalDebugLevel'] = $level;
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* gets the debug level for this instance
|
257 |
+
*
|
258 |
+
* @return int Debug level 0-9, where 0 turns off
|
259 |
+
* @access public
|
260 |
+
*/
|
261 |
+
function getDebugLevel()
|
262 |
+
{
|
263 |
+
return $this->debugLevel;
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* sets the debug level for this instance
|
268 |
+
*
|
269 |
+
* @param int $level Debug level 0-9, where 0 turns off
|
270 |
+
* @access public
|
271 |
+
*/
|
272 |
+
function setDebugLevel($level)
|
273 |
+
{
|
274 |
+
$this->debugLevel = $level;
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* adds debug data to the instance debug string with formatting
|
279 |
+
*
|
280 |
+
* @param string $string debug data
|
281 |
+
* @access private
|
282 |
+
*/
|
283 |
+
function debug($string)
|
284 |
+
{
|
285 |
+
if ($this->debugLevel > 0) {
|
286 |
+
$this->appendDebug($this->getmicrotime() . ' ' . get_class($this) . ": $string\n");
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* adds debug data to the instance debug string without formatting
|
292 |
+
*
|
293 |
+
* @param string $string debug data
|
294 |
+
* @access public
|
295 |
+
*/
|
296 |
+
function appendDebug($string)
|
297 |
+
{
|
298 |
+
if ($this->debugLevel > 0) {
|
299 |
+
// it would be nice to use a memory stream here to use
|
300 |
+
// memory more efficiently
|
301 |
+
$this->debug_str .= $string;
|
302 |
+
}
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* clears the current debug data for this instance
|
307 |
+
*
|
308 |
+
* @access public
|
309 |
+
*/
|
310 |
+
function clearDebug()
|
311 |
+
{
|
312 |
+
// it would be nice to use a memory stream here to use
|
313 |
+
// memory more efficiently
|
314 |
+
$this->debug_str = '';
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* gets the current debug data for this instance
|
319 |
+
*
|
320 |
+
* @return debug data
|
321 |
+
* @access public
|
322 |
+
*/
|
323 |
+
function &getDebug()
|
324 |
+
{
|
325 |
+
// it would be nice to use a memory stream here to use
|
326 |
+
// memory more efficiently
|
327 |
+
return $this->debug_str;
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* gets the current debug data for this instance as an XML comment
|
332 |
+
* this may change the contents of the debug data
|
333 |
+
*
|
334 |
+
* @return debug data as an XML comment
|
335 |
+
* @access public
|
336 |
+
*/
|
337 |
+
function &getDebugAsXMLComment()
|
338 |
+
{
|
339 |
+
// it would be nice to use a memory stream here to use
|
340 |
+
// memory more efficiently
|
341 |
+
while (strpos($this->debug_str, '--')) {
|
342 |
+
$this->debug_str = str_replace('--', '- -', $this->debug_str);
|
343 |
+
}
|
344 |
+
$ret = "<!--\n" . $this->debug_str . "\n-->";
|
345 |
+
return $ret;
|
346 |
+
}
|
347 |
+
|
348 |
+
/**
|
349 |
+
* expands entities, e.g. changes '<' to '<'.
|
350 |
+
*
|
351 |
+
* @param string $val The string in which to expand entities.
|
352 |
+
* @access private
|
353 |
+
*/
|
354 |
+
function expandEntities($val)
|
355 |
+
{
|
356 |
+
if ($this->charencoding) {
|
357 |
+
$val = str_replace('&', '&', $val);
|
358 |
+
$val = str_replace("'", ''', $val);
|
359 |
+
$val = str_replace('"', '"', $val);
|
360 |
+
$val = str_replace('<', '<', $val);
|
361 |
+
$val = str_replace('>', '>', $val);
|
362 |
+
}
|
363 |
+
return $val;
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* returns error string if present
|
368 |
+
*
|
369 |
+
* @return mixed error string or false
|
370 |
+
* @access public
|
371 |
+
*/
|
372 |
+
function getError()
|
373 |
+
{
|
374 |
+
if ($this->error_str != '') {
|
375 |
+
return $this->error_str;
|
376 |
+
}
|
377 |
+
return false;
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* sets error string
|
382 |
+
*
|
383 |
+
* @return boolean $string error string
|
384 |
+
* @access private
|
385 |
+
*/
|
386 |
+
function setError($str)
|
387 |
+
{
|
388 |
+
$this->error_str = $str;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* detect if array is a simple array or a struct (associative array)
|
393 |
+
*
|
394 |
+
* @param mixed $val The PHP array
|
395 |
+
* @return string (arraySimple|arrayStruct)
|
396 |
+
* @access private
|
397 |
+
*/
|
398 |
+
function isArraySimpleOrStruct($val)
|
399 |
+
{
|
400 |
+
$keyList = array_keys($val);
|
401 |
+
foreach ($keyList as $keyListValue) {
|
402 |
+
if (!is_int($keyListValue)) {
|
403 |
+
return 'arrayStruct';
|
404 |
+
}
|
405 |
+
}
|
406 |
+
return 'arraySimple';
|
407 |
+
}
|
408 |
+
|
409 |
+
/**
|
410 |
+
* serializes PHP values in accordance w/ section 5. Type information is
|
411 |
+
* not serialized if $use == 'literal'.
|
412 |
+
*
|
413 |
+
* @param mixed $val The value to serialize
|
414 |
+
* @param string $name The name (local part) of the XML element
|
415 |
+
* @param string $type The XML schema type (local part) for the element
|
416 |
+
* @param string $name_ns The namespace for the name of the XML element
|
417 |
+
* @param string $type_ns The namespace for the type of the element
|
418 |
+
* @param array $attributes The attributes to serialize as name=>value pairs
|
419 |
+
* @param string $use The WSDL "use" (encoded|literal)
|
420 |
+
* @param boolean $soapval Whether this is called from soapval.
|
421 |
+
* @return string The serialized element, possibly with child elements
|
422 |
+
* @access public
|
423 |
+
*/
|
424 |
+
function serialize_val($val, $name = false, $type = false, $name_ns = false, $type_ns = false, $attributes = false, $use = 'encoded', $soapval = false)
|
425 |
+
{
|
426 |
+
$this->debug("in serialize_val: name=$name, type=$type, name_ns=$name_ns, type_ns=$type_ns, use=$use, soapval=$soapval");
|
427 |
+
$this->appendDebug('value=' . $this->varDump($val));
|
428 |
+
$this->appendDebug('attributes=' . $this->varDump($attributes));
|
429 |
+
|
430 |
+
if (is_object($val) && get_class($val) == 'soapval' && (!$soapval)) {
|
431 |
+
$this->debug("serialize_val: serialize soapval");
|
432 |
+
$xml = $val->serialize($use);
|
433 |
+
$this->appendDebug($val->getDebug());
|
434 |
+
$val->clearDebug();
|
435 |
+
$this->debug("serialize_val of soapval returning $xml");
|
436 |
+
return $xml;
|
437 |
+
}
|
438 |
+
// force valid name if necessary
|
439 |
+
if (is_numeric($name)) {
|
440 |
+
$name = '__numeric_' . $name;
|
441 |
+
} elseif (!$name) {
|
442 |
+
$name = 'noname';
|
443 |
+
}
|
444 |
+
// if name has ns, add ns prefix to name
|
445 |
+
$xmlns = '';
|
446 |
+
if ($name_ns) {
|
447 |
+
$prefix = 'nu' . rand(1000, 9999);
|
448 |
+
$name = $prefix . ':' . $name;
|
449 |
+
$xmlns .= " xmlns:$prefix=\"$name_ns\"";
|
450 |
+
}
|
451 |
+
// if type is prefixed, create type prefix
|
452 |
+
if ($type_ns != '' && $type_ns == $this->namespaces['xsd']) {
|
453 |
+
// need to fix this. shouldn't default to xsd if no ns specified
|
454 |
+
// w/o checking against typemap
|
455 |
+
$type_prefix = 'xsd';
|
456 |
+
} elseif ($type_ns) {
|
457 |
+
$type_prefix = 'ns' . rand(1000, 9999);
|
458 |
+
$xmlns .= " xmlns:$type_prefix=\"$type_ns\"";
|
459 |
+
}
|
460 |
+
// serialize attributes if present
|
461 |
+
$atts = '';
|
462 |
+
if ($attributes) {
|
463 |
+
foreach ($attributes as $k => $v) {
|
464 |
+
$atts .= " $k=\"" . $this->expandEntities($v) . '"';
|
465 |
+
}
|
466 |
+
}
|
467 |
+
// serialize null value
|
468 |
+
if (is_null($val)) {
|
469 |
+
$this->debug("serialize_val: serialize null");
|
470 |
+
if ($use == 'literal') {
|
471 |
+
// TODO: depends on minOccurs
|
472 |
+
$xml = "<$name$xmlns$atts/>";
|
473 |
+
$this->debug("serialize_val returning $xml");
|
474 |
+
return $xml;
|
475 |
+
} else {
|
476 |
+
if (isset($type) && isset($type_prefix)) {
|
477 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
478 |
+
} else {
|
479 |
+
$type_str = '';
|
480 |
+
}
|
481 |
+
$xml = "<$name$xmlns$type_str$atts xsi:nil=\"true\"/>";
|
482 |
+
$this->debug("serialize_val returning $xml");
|
483 |
+
return $xml;
|
484 |
+
}
|
485 |
+
}
|
486 |
+
// serialize if an xsd built-in primitive type
|
487 |
+
if ($type != '' && isset($this->typemap[$this->XMLSchemaVersion][$type])) {
|
488 |
+
$this->debug("serialize_val: serialize xsd built-in primitive type");
|
489 |
+
if (is_bool($val)) {
|
490 |
+
if ($type == 'boolean') {
|
491 |
+
$val = $val ? 'true' : 'false';
|
492 |
+
} elseif (!$val) {
|
493 |
+
$val = 0;
|
494 |
+
}
|
495 |
+
} elseif (is_string($val)) {
|
496 |
+
$val = $this->expandEntities($val);
|
497 |
+
}
|
498 |
+
if ($use == 'literal') {
|
499 |
+
$xml = "<$name$xmlns$atts>$val</$name>";
|
500 |
+
$this->debug("serialize_val returning $xml");
|
501 |
+
return $xml;
|
502 |
+
} else {
|
503 |
+
$xml = "<$name$xmlns xsi:type=\"xsd:$type\"$atts>$val</$name>";
|
504 |
+
$this->debug("serialize_val returning $xml");
|
505 |
+
return $xml;
|
506 |
+
}
|
507 |
+
}
|
508 |
+
// detect type and serialize
|
509 |
+
$xml = '';
|
510 |
+
switch (true) {
|
511 |
+
case (is_bool($val) || $type == 'boolean'):
|
512 |
+
$this->debug("serialize_val: serialize boolean");
|
513 |
+
if ($type == 'boolean') {
|
514 |
+
$val = $val ? 'true' : 'false';
|
515 |
+
} elseif (!$val) {
|
516 |
+
$val = 0;
|
517 |
+
}
|
518 |
+
if ($use == 'literal') {
|
519 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
520 |
+
} else {
|
521 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:boolean\"$atts>$val</$name>";
|
522 |
+
}
|
523 |
+
break;
|
524 |
+
case (is_int($val) || is_long($val) || $type == 'int'):
|
525 |
+
$this->debug("serialize_val: serialize int");
|
526 |
+
if ($use == 'literal') {
|
527 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
528 |
+
} else {
|
529 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:int\"$atts>$val</$name>";
|
530 |
+
}
|
531 |
+
break;
|
532 |
+
case (is_float($val) || is_double($val) || $type == 'float'):
|
533 |
+
$this->debug("serialize_val: serialize float");
|
534 |
+
if ($use == 'literal') {
|
535 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
536 |
+
} else {
|
537 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:float\"$atts>$val</$name>";
|
538 |
+
}
|
539 |
+
break;
|
540 |
+
case (is_string($val) || $type == 'string'):
|
541 |
+
$this->debug("serialize_val: serialize string");
|
542 |
+
$val = $this->expandEntities($val);
|
543 |
+
if ($use == 'literal') {
|
544 |
+
$xml .= "<$name$xmlns$atts>$val</$name>";
|
545 |
+
} else {
|
546 |
+
$xml .= "<$name$xmlns xsi:type=\"xsd:string\"$atts>$val</$name>";
|
547 |
+
}
|
548 |
+
break;
|
549 |
+
case is_object($val):
|
550 |
+
$this->debug("serialize_val: serialize object");
|
551 |
+
if (get_class($val) == 'soapval') {
|
552 |
+
$this->debug("serialize_val: serialize soapval object");
|
553 |
+
$pXml = $val->serialize($use);
|
554 |
+
$this->appendDebug($val->getDebug());
|
555 |
+
$val->clearDebug();
|
556 |
+
} else {
|
557 |
+
if (!$name) {
|
558 |
+
$name = get_class($val);
|
559 |
+
$this->debug("In serialize_val, used class name $name as element name");
|
560 |
+
} else {
|
561 |
+
$this->debug("In serialize_val, do not override name $name for element name for class " . get_class($val));
|
562 |
+
}
|
563 |
+
foreach (get_object_vars($val) as $k => $v) {
|
564 |
+
$pXml = isset($pXml) ? $pXml . $this->serialize_val($v, $k, false, false, false, false, $use) : $this->serialize_val($v, $k, false, false, false, false, $use);
|
565 |
+
}
|
566 |
+
}
|
567 |
+
if (isset($type) && isset($type_prefix)) {
|
568 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
569 |
+
} else {
|
570 |
+
$type_str = '';
|
571 |
+
}
|
572 |
+
if ($use == 'literal') {
|
573 |
+
$xml .= "<$name$xmlns$atts>$pXml</$name>";
|
574 |
+
} else {
|
575 |
+
$xml .= "<$name$xmlns$type_str$atts>$pXml</$name>";
|
576 |
+
}
|
577 |
+
break;
|
578 |
+
break;
|
579 |
+
case (is_array($val) || $type):
|
580 |
+
// detect if struct or array
|
581 |
+
$valueType = $this->isArraySimpleOrStruct($val);
|
582 |
+
if ($valueType == 'arraySimple' || preg_match('/^ArrayOf/', $type)) {
|
583 |
+
$this->debug("serialize_val: serialize array");
|
584 |
+
$i = 0;
|
585 |
+
if (is_array($val) && count($val) > 0) {
|
586 |
+
foreach ($val as $v) {
|
587 |
+
if (is_object($v) && get_class($v) == 'soapval') {
|
588 |
+
$tt_ns = $v->type_ns;
|
589 |
+
$tt = $v->type;
|
590 |
+
} elseif (is_array($v)) {
|
591 |
+
$tt = $this->isArraySimpleOrStruct($v);
|
592 |
+
} else {
|
593 |
+
$tt = gettype($v);
|
594 |
+
}
|
595 |
+
$array_types[$tt] = 1;
|
596 |
+
// TODO: for literal, the name should be $name
|
597 |
+
$xml .= $this->serialize_val($v, 'item', false, false, false, false, $use);
|
598 |
+
++$i;
|
599 |
+
}
|
600 |
+
if (count($array_types) > 1) {
|
601 |
+
$array_typename = 'xsd:anyType';
|
602 |
+
} elseif (isset($tt) && isset($this->typemap[$this->XMLSchemaVersion][$tt])) {
|
603 |
+
if ($tt == 'integer') {
|
604 |
+
$tt = 'int';
|
605 |
+
}
|
606 |
+
$array_typename = 'xsd:' . $tt;
|
607 |
+
} elseif (isset($tt) && $tt == 'arraySimple') {
|
608 |
+
$array_typename = 'SOAP-ENC:Array';
|
609 |
+
} elseif (isset($tt) && $tt == 'arrayStruct') {
|
610 |
+
$array_typename = 'unnamed_struct_use_soapval';
|
611 |
+
} else {
|
612 |
+
// if type is prefixed, create type prefix
|
613 |
+
if ($tt_ns != '' && $tt_ns == $this->namespaces['xsd']) {
|
614 |
+
$array_typename = 'xsd:' . $tt;
|
615 |
+
} elseif ($tt_ns) {
|
616 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
617 |
+
$array_typename = "$tt_prefix:$tt";
|
618 |
+
$xmlns .= " xmlns:$tt_prefix=\"$tt_ns\"";
|
619 |
+
} else {
|
620 |
+
$array_typename = $tt;
|
621 |
+
}
|
622 |
+
}
|
623 |
+
$array_type = $i;
|
624 |
+
if ($use == 'literal') {
|
625 |
+
$type_str = '';
|
626 |
+
} elseif (isset($type) && isset($type_prefix)) {
|
627 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
628 |
+
} else {
|
629 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"" . $array_typename . "[$array_type]\"";
|
630 |
+
}
|
631 |
+
// empty array
|
632 |
+
} else {
|
633 |
+
if ($use == 'literal') {
|
634 |
+
$type_str = '';
|
635 |
+
} elseif (isset($type) && isset($type_prefix)) {
|
636 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
637 |
+
} else {
|
638 |
+
$type_str = " xsi:type=\"SOAP-ENC:Array\" SOAP-ENC:arrayType=\"xsd:anyType[0]\"";
|
639 |
+
}
|
640 |
+
}
|
641 |
+
// TODO: for array in literal, there is no wrapper here
|
642 |
+
$xml = "<$name$xmlns$type_str$atts>" . $xml . "</$name>";
|
643 |
+
} else {
|
644 |
+
// got a struct
|
645 |
+
$this->debug("serialize_val: serialize struct");
|
646 |
+
if (isset($type) && isset($type_prefix)) {
|
647 |
+
$type_str = " xsi:type=\"$type_prefix:$type\"";
|
648 |
+
} else {
|
649 |
+
$type_str = '';
|
650 |
+
}
|
651 |
+
if ($use == 'literal') {
|
652 |
+
$xml .= "<$name$xmlns$atts>";
|
653 |
+
} else {
|
654 |
+
$xml .= "<$name$xmlns$type_str$atts>";
|
655 |
+
}
|
656 |
+
foreach ($val as $k => $v) {
|
657 |
+
// Apache Map
|
658 |
+
if ($type == 'Map' && $type_ns == 'http://xml.apache.org/xml-soap') {
|
659 |
+
$xml .= '<item>';
|
660 |
+
$xml .= $this->serialize_val($k, 'key', false, false, false, false, $use);
|
661 |
+
$xml .= $this->serialize_val($v, 'value', false, false, false, false, $use);
|
662 |
+
$xml .= '</item>';
|
663 |
+
} else {
|
664 |
+
$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
|
665 |
+
}
|
666 |
+
}
|
667 |
+
$xml .= "</$name>";
|
668 |
+
}
|
669 |
+
break;
|
670 |
+
default:
|
671 |
+
$this->debug("serialize_val: serialize unknown");
|
672 |
+
$xml .= 'not detected, got ' . gettype($val) . ' for ' . $val;
|
673 |
+
break;
|
674 |
+
}
|
675 |
+
$this->debug("serialize_val returning $xml");
|
676 |
+
return $xml;
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* serializes a message
|
681 |
+
*
|
682 |
+
* @param string $body the XML of the SOAP body
|
683 |
+
* @param mixed $headers optional string of XML with SOAP header content, or array of soapval objects for SOAP headers, or associative array
|
684 |
+
* @param array $namespaces optional the namespaces used in generating the body and headers
|
685 |
+
* @param string $style optional (rpc|document)
|
686 |
+
* @param string $use optional (encoded|literal)
|
687 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
688 |
+
* @return string the message
|
689 |
+
* @access public
|
690 |
+
*/
|
691 |
+
function serializeEnvelope($body, $headers = false, $namespaces = array(), $style = 'rpc', $use = 'encoded', $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/')
|
692 |
+
{
|
693 |
+
// TODO: add an option to automatically run utf8_encode on $body and $headers
|
694 |
+
// if $this->soap_defencoding is UTF-8. Not doing this automatically allows
|
695 |
+
// one to send arbitrary UTF-8 characters, not just characters that map to ISO-8859-1
|
696 |
+
|
697 |
+
$this->debug("In serializeEnvelope length=" . strlen($body) . " body (max 1000 characters)=" . substr($body, 0, 1000) . " style=$style use=$use encodingStyle=$encodingStyle");
|
698 |
+
$this->debug("headers:");
|
699 |
+
$this->appendDebug($this->varDump($headers));
|
700 |
+
$this->debug("namespaces:");
|
701 |
+
$this->appendDebug($this->varDump($namespaces));
|
702 |
+
|
703 |
+
// serialize namespaces
|
704 |
+
$ns_string = '';
|
705 |
+
foreach (array_merge($this->namespaces, $namespaces) as $k => $v) {
|
706 |
+
$ns_string .= " xmlns:$k=\"$v\"";
|
707 |
+
}
|
708 |
+
if ($encodingStyle) {
|
709 |
+
$ns_string = " SOAP-ENV:encodingStyle=\"$encodingStyle\"$ns_string";
|
710 |
+
}
|
711 |
+
|
712 |
+
// serialize headers
|
713 |
+
if ($headers) {
|
714 |
+
if (is_array($headers)) {
|
715 |
+
$xml = '';
|
716 |
+
foreach ($headers as $k => $v) {
|
717 |
+
if (is_object($v) && get_class($v) == 'soapval') {
|
718 |
+
$xml .= $this->serialize_val($v, false, false, false, false, false, $use);
|
719 |
+
} else {
|
720 |
+
$xml .= $this->serialize_val($v, $k, false, false, false, false, $use);
|
721 |
+
}
|
722 |
+
}
|
723 |
+
$headers = $xml;
|
724 |
+
$this->debug("In serializeEnvelope, serialized array of headers to $headers");
|
725 |
+
}
|
726 |
+
$headers = "<SOAP-ENV:Header>" . $headers . "</SOAP-ENV:Header>";
|
727 |
+
}
|
728 |
+
// serialize envelope
|
729 |
+
return
|
730 |
+
'<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?' . ">" .
|
731 |
+
'<SOAP-ENV:Envelope' . $ns_string . ">" .
|
732 |
+
$headers .
|
733 |
+
"<SOAP-ENV:Body>" .
|
734 |
+
$body .
|
735 |
+
"</SOAP-ENV:Body>" .
|
736 |
+
"</SOAP-ENV:Envelope>";
|
737 |
+
}
|
738 |
+
|
739 |
+
/**
|
740 |
+
* formats a string to be inserted into an HTML stream
|
741 |
+
*
|
742 |
+
* @param string $str The string to format
|
743 |
+
* @return string The formatted string
|
744 |
+
* @access public
|
745 |
+
* @deprecated
|
746 |
+
*/
|
747 |
+
function formatDump($str)
|
748 |
+
{
|
749 |
+
$str = htmlspecialchars($str);
|
750 |
+
return nl2br($str);
|
751 |
+
}
|
752 |
+
|
753 |
+
/**
|
754 |
+
* contracts (changes namespace to prefix) a qualified name
|
755 |
+
*
|
756 |
+
* @param string $qname qname
|
757 |
+
* @return string contracted qname
|
758 |
+
* @access private
|
759 |
+
*/
|
760 |
+
function contractQname($qname)
|
761 |
+
{
|
762 |
+
// get element namespace
|
763 |
+
//$this->xdebug("Contract $qname");
|
764 |
+
if (strrpos($qname, ':')) {
|
765 |
+
// get unqualified name
|
766 |
+
$name = substr($qname, strrpos($qname, ':') + 1);
|
767 |
+
// get ns
|
768 |
+
$ns = substr($qname, 0, strrpos($qname, ':'));
|
769 |
+
$p = $this->getPrefixFromNamespace($ns);
|
770 |
+
if ($p) {
|
771 |
+
return $p . ':' . $name;
|
772 |
+
}
|
773 |
+
return $qname;
|
774 |
+
} else {
|
775 |
+
return $qname;
|
776 |
+
}
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* expands (changes prefix to namespace) a qualified name
|
781 |
+
*
|
782 |
+
* @param string $qname qname
|
783 |
+
* @return string expanded qname
|
784 |
+
* @access private
|
785 |
+
*/
|
786 |
+
function expandQname($qname)
|
787 |
+
{
|
788 |
+
// get element prefix
|
789 |
+
if (strpos($qname, ':') && !preg_match('/^http:\/\//', $qname)) {
|
790 |
+
// get unqualified name
|
791 |
+
$name = substr(strstr($qname, ':'), 1);
|
792 |
+
// get ns prefix
|
793 |
+
$prefix = substr($qname, 0, strpos($qname, ':'));
|
794 |
+
if (isset($this->namespaces[$prefix])) {
|
795 |
+
return $this->namespaces[$prefix] . ':' . $name;
|
796 |
+
} else {
|
797 |
+
return $qname;
|
798 |
+
}
|
799 |
+
} else {
|
800 |
+
return $qname;
|
801 |
+
}
|
802 |
+
}
|
803 |
+
|
804 |
+
/**
|
805 |
+
* returns the local part of a prefixed string
|
806 |
+
* returns the original string, if not prefixed
|
807 |
+
*
|
808 |
+
* @param string $str The prefixed string
|
809 |
+
* @return string The local part
|
810 |
+
* @access public
|
811 |
+
*/
|
812 |
+
function getLocalPart($str)
|
813 |
+
{
|
814 |
+
if ($sstr = strrchr($str, ':')) {
|
815 |
+
// get unqualified name
|
816 |
+
return substr($sstr, 1);
|
817 |
+
} else {
|
818 |
+
return $str;
|
819 |
+
}
|
820 |
+
}
|
821 |
+
|
822 |
+
/**
|
823 |
+
* returns the prefix part of a prefixed string
|
824 |
+
* returns false, if not prefixed
|
825 |
+
*
|
826 |
+
* @param string $str The prefixed string
|
827 |
+
* @return mixed The prefix or false if there is no prefix
|
828 |
+
* @access public
|
829 |
+
*/
|
830 |
+
function getPrefix($str)
|
831 |
+
{
|
832 |
+
if ($pos = strrpos($str, ':')) {
|
833 |
+
// get prefix
|
834 |
+
return substr($str, 0, $pos);
|
835 |
+
}
|
836 |
+
return false;
|
837 |
+
}
|
838 |
+
|
839 |
+
/**
|
840 |
+
* pass it a prefix, it returns a namespace
|
841 |
+
*
|
842 |
+
* @param string $prefix The prefix
|
843 |
+
* @return mixed The namespace, false if no namespace has the specified prefix
|
844 |
+
* @access public
|
845 |
+
*/
|
846 |
+
function getNamespaceFromPrefix($prefix)
|
847 |
+
{
|
848 |
+
if (isset($this->namespaces[$prefix])) {
|
849 |
+
return $this->namespaces[$prefix];
|
850 |
+
}
|
851 |
+
//$this->setError("No namespace registered for prefix '$prefix'");
|
852 |
+
return false;
|
853 |
+
}
|
854 |
+
|
855 |
+
/**
|
856 |
+
* returns the prefix for a given namespace (or prefix)
|
857 |
+
* or false if no prefixes registered for the given namespace
|
858 |
+
*
|
859 |
+
* @param string $ns The namespace
|
860 |
+
* @return mixed The prefix, false if the namespace has no prefixes
|
861 |
+
* @access public
|
862 |
+
*/
|
863 |
+
function getPrefixFromNamespace($ns)
|
864 |
+
{
|
865 |
+
foreach ($this->namespaces as $p => $n) {
|
866 |
+
if ($ns == $n || $ns == $p) {
|
867 |
+
$this->usedNamespaces[$p] = $n;
|
868 |
+
return $p;
|
869 |
+
}
|
870 |
+
}
|
871 |
+
return false;
|
872 |
+
}
|
873 |
+
|
874 |
+
/**
|
875 |
+
* returns the time in ODBC canonical form with microseconds
|
876 |
+
*
|
877 |
+
* @return string The time in ODBC canonical form with microseconds
|
878 |
+
* @access public
|
879 |
+
*/
|
880 |
+
function getmicrotime()
|
881 |
+
{
|
882 |
+
if (function_exists('gettimeofday')) {
|
883 |
+
$tod = gettimeofday();
|
884 |
+
$sec = $tod['sec'];
|
885 |
+
$usec = $tod['usec'];
|
886 |
+
} else {
|
887 |
+
$sec = time();
|
888 |
+
$usec = 0;
|
889 |
+
}
|
890 |
+
return strftime('%Y-%m-%d %H:%M:%S', $sec) . '.' . sprintf('%06d', $usec);
|
891 |
+
}
|
892 |
+
|
893 |
+
/**
|
894 |
+
* Returns a string with the output of var_dump
|
895 |
+
*
|
896 |
+
* @param mixed $data The variable to var_dump
|
897 |
+
* @return string The output of var_dump
|
898 |
+
* @access public
|
899 |
+
*/
|
900 |
+
function varDump($data)
|
901 |
+
{
|
902 |
+
ob_start();
|
903 |
+
var_dump($data);
|
904 |
+
$ret_val = ob_get_contents();
|
905 |
+
ob_end_clean();
|
906 |
+
return $ret_val;
|
907 |
+
}
|
908 |
+
|
909 |
+
/**
|
910 |
+
* represents the object as a string
|
911 |
+
*
|
912 |
+
* @return string
|
913 |
+
* @access public
|
914 |
+
*/
|
915 |
+
function __toString()
|
916 |
+
{
|
917 |
+
return $this->varDump($this);
|
918 |
+
}
|
919 |
+
}
|
920 |
+
|
921 |
+
// XML Schema Datatype Helper Functions
|
922 |
+
|
923 |
+
//xsd:dateTime helpers
|
924 |
+
|
925 |
+
/**
|
926 |
+
* convert unix timestamp to ISO 8601 compliant date string
|
927 |
+
*
|
928 |
+
* @param int $timestamp Unix time stamp
|
929 |
+
* @param boolean $utc Whether the time stamp is UTC or local
|
930 |
+
* @return mixed ISO 8601 date string or false
|
931 |
+
* @access public
|
932 |
+
*/
|
933 |
+
function timestamp_to_iso8601($timestamp, $utc = true)
|
934 |
+
{
|
935 |
+
$datestr = date('Y-m-d\TH:i:sO', $timestamp);
|
936 |
+
$pos = strrpos($datestr, "+");
|
937 |
+
if ($pos === false) {
|
938 |
+
$pos = strrpos($datestr, "-");
|
939 |
+
}
|
940 |
+
if ($pos !== false) {
|
941 |
+
if (strlen($datestr) == $pos + 5) {
|
942 |
+
$datestr = substr($datestr, 0, $pos + 3) . ':' . substr($datestr, -2);
|
943 |
+
}
|
944 |
+
}
|
945 |
+
if ($utc) {
|
946 |
+
$pattern = '/' .
|
947 |
+
'([0-9]{4})-' . // centuries & years CCYY-
|
948 |
+
'([0-9]{2})-' . // months MM-
|
949 |
+
'([0-9]{2})' . // days DD
|
950 |
+
'T' . // separator T
|
951 |
+
'([0-9]{2}):' . // hours hh:
|
952 |
+
'([0-9]{2}):' . // minutes mm:
|
953 |
+
'([0-9]{2})(\.[0-9]*)?' . // seconds ss.ss...
|
954 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
955 |
+
'/';
|
956 |
+
|
957 |
+
if (preg_match($pattern, $datestr, $regs)) {
|
958 |
+
return sprintf('%04d-%02d-%02dT%02d:%02d:%02dZ', $regs[1], $regs[2], $regs[3], $regs[4], $regs[5], $regs[6]);
|
959 |
+
}
|
960 |
+
return false;
|
961 |
+
} else {
|
962 |
+
return $datestr;
|
963 |
+
}
|
964 |
+
}
|
965 |
+
|
966 |
+
/**
|
967 |
+
* convert ISO 8601 compliant date string to unix timestamp
|
968 |
+
*
|
969 |
+
* @param string $datestr ISO 8601 compliant date string
|
970 |
+
* @return mixed Unix timestamp (int) or false
|
971 |
+
* @access public
|
972 |
+
*/
|
973 |
+
function iso8601_to_timestamp($datestr)
|
974 |
+
{
|
975 |
+
$pattern = '/' .
|
976 |
+
'([0-9]{4})-' . // centuries & years CCYY-
|
977 |
+
'([0-9]{2})-' . // months MM-
|
978 |
+
'([0-9]{2})' . // days DD
|
979 |
+
'T' . // separator T
|
980 |
+
'([0-9]{2}):' . // hours hh:
|
981 |
+
'([0-9]{2}):' . // minutes mm:
|
982 |
+
'([0-9]{2})(\.[0-9]+)?' . // seconds ss.ss...
|
983 |
+
'(Z|[+\-][0-9]{2}:?[0-9]{2})?' . // Z to indicate UTC, -/+HH:MM:SS.SS... for local tz's
|
984 |
+
'/';
|
985 |
+
if (preg_match($pattern, $datestr, $regs)) {
|
986 |
+
// not utc
|
987 |
+
if ($regs[8] != 'Z') {
|
988 |
+
$op = substr($regs[8], 0, 1);
|
989 |
+
$h = substr($regs[8], 1, 2);
|
990 |
+
$m = substr($regs[8], strlen($regs[8]) - 2, 2);
|
991 |
+
if ($op == '-') {
|
992 |
+
$regs[4] = $regs[4] + $h;
|
993 |
+
$regs[5] = $regs[5] + $m;
|
994 |
+
} elseif ($op == '+') {
|
995 |
+
$regs[4] = $regs[4] - $h;
|
996 |
+
$regs[5] = $regs[5] - $m;
|
997 |
+
}
|
998 |
+
}
|
999 |
+
return gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
|
1000 |
+
// return strtotime("$regs[1]-$regs[2]-$regs[3] $regs[4]:$regs[5]:$regs[6]Z");
|
1001 |
+
} else {
|
1002 |
+
return false;
|
1003 |
+
}
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
/**
|
1007 |
+
* sleeps some number of microseconds
|
1008 |
+
*
|
1009 |
+
* @param string $usec the number of microseconds to sleep
|
1010 |
+
* @access public
|
1011 |
+
* @deprecated
|
1012 |
+
*/
|
1013 |
+
function usleepWindows($usec)
|
1014 |
+
{
|
1015 |
+
$start = gettimeofday();
|
1016 |
+
|
1017 |
+
do {
|
1018 |
+
$stop = gettimeofday();
|
1019 |
+
$timePassed = 1000000 * ($stop['sec'] - $start['sec'])
|
1020 |
+
+ $stop['usec'] - $start['usec'];
|
1021 |
+
} while ($timePassed < $usec);
|
1022 |
+
}
|
1023 |
+
|
1024 |
+
|
1025 |
+
/**
|
1026 |
+
* Contains information for a SOAP fault.
|
1027 |
+
* Mainly used for returning faults from deployed functions
|
1028 |
+
* in a server instance.
|
1029 |
+
*
|
1030 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1031 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1032 |
+
* @access public
|
1033 |
+
*/
|
1034 |
+
class nusoap_fault extends nusoap_base
|
1035 |
+
{
|
1036 |
+
/**
|
1037 |
+
* The fault code (client|server)
|
1038 |
+
*
|
1039 |
+
* @var string
|
1040 |
+
* @access private
|
1041 |
+
*/
|
1042 |
+
var $faultcode;
|
1043 |
+
/**
|
1044 |
+
* The fault actor
|
1045 |
+
*
|
1046 |
+
* @var string
|
1047 |
+
* @access private
|
1048 |
+
*/
|
1049 |
+
var $faultactor;
|
1050 |
+
/**
|
1051 |
+
* The fault string, a description of the fault
|
1052 |
+
*
|
1053 |
+
* @var string
|
1054 |
+
* @access private
|
1055 |
+
*/
|
1056 |
+
var $faultstring;
|
1057 |
+
/**
|
1058 |
+
* The fault detail, typically a string or array of string
|
1059 |
+
*
|
1060 |
+
* @var mixed
|
1061 |
+
* @access private
|
1062 |
+
*/
|
1063 |
+
var $faultdetail;
|
1064 |
+
|
1065 |
+
/**
|
1066 |
+
* constructor
|
1067 |
+
*
|
1068 |
+
* @param string $faultcode (SOAP-ENV:Client | SOAP-ENV:Server)
|
1069 |
+
* @param string $faultactor only used when msg routed between multiple actors
|
1070 |
+
* @param string $faultstring human readable error message
|
1071 |
+
* @param mixed $faultdetail detail, typically a string or array of string
|
1072 |
+
*/
|
1073 |
+
function __construct($faultcode, $faultactor = '', $faultstring = '', $faultdetail = '')
|
1074 |
+
{
|
1075 |
+
parent::__construct();
|
1076 |
+
$this->faultcode = $faultcode;
|
1077 |
+
$this->faultactor = $faultactor;
|
1078 |
+
$this->faultstring = $faultstring;
|
1079 |
+
$this->faultdetail = $faultdetail;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
/**
|
1083 |
+
* serialize a fault
|
1084 |
+
*
|
1085 |
+
* @return string The serialization of the fault instance.
|
1086 |
+
* @access public
|
1087 |
+
*/
|
1088 |
+
function serialize()
|
1089 |
+
{
|
1090 |
+
$ns_string = '';
|
1091 |
+
foreach ($this->namespaces as $k => $v) {
|
1092 |
+
$ns_string .= "\n xmlns:$k=\"$v\"";
|
1093 |
+
}
|
1094 |
+
$return_msg =
|
1095 |
+
'<?xml version="1.0" encoding="' . $this->soap_defencoding . '"?>' .
|
1096 |
+
'<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"' . $ns_string . ">\n" .
|
1097 |
+
'<SOAP-ENV:Body>' .
|
1098 |
+
'<SOAP-ENV:Fault>' .
|
1099 |
+
$this->serialize_val($this->faultcode, 'faultcode') .
|
1100 |
+
$this->serialize_val($this->faultactor, 'faultactor') .
|
1101 |
+
$this->serialize_val($this->faultstring, 'faultstring') .
|
1102 |
+
$this->serialize_val($this->faultdetail, 'detail') .
|
1103 |
+
'</SOAP-ENV:Fault>' .
|
1104 |
+
'</SOAP-ENV:Body>' .
|
1105 |
+
'</SOAP-ENV:Envelope>';
|
1106 |
+
return $return_msg;
|
1107 |
+
}
|
1108 |
+
}
|
1109 |
+
|
1110 |
+
|
1111 |
+
/**
|
1112 |
+
* Backward compatibility
|
1113 |
+
*/
|
1114 |
+
class soap_fault extends nusoap_fault
|
1115 |
+
{
|
1116 |
+
}
|
1117 |
+
|
1118 |
+
|
1119 |
+
/**
|
1120 |
+
* parses an XML Schema, allows access to it's data, other utility methods.
|
1121 |
+
* imperfect, no validation... yet, but quite functional.
|
1122 |
+
*
|
1123 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
1124 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
1125 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
1126 |
+
* @access public
|
1127 |
+
*/
|
1128 |
+
class nusoap_xmlschema extends nusoap_base
|
1129 |
+
{
|
1130 |
+
|
1131 |
+
// files
|
1132 |
+
var $schema = '';
|
1133 |
+
var $xml = '';
|
1134 |
+
// namespaces
|
1135 |
+
var $enclosingNamespaces;
|
1136 |
+
// schema info
|
1137 |
+
var $schemaInfo = array();
|
1138 |
+
var $schemaTargetNamespace = '';
|
1139 |
+
// types, elements, attributes defined by the schema
|
1140 |
+
var $attributes = array();
|
1141 |
+
var $complexTypes = array();
|
1142 |
+
var $complexTypeStack = array();
|
1143 |
+
var $currentComplexType = null;
|
1144 |
+
var $elements = array();
|
1145 |
+
var $elementStack = array();
|
1146 |
+
var $currentElement = null;
|
1147 |
+
var $simpleTypes = array();
|
1148 |
+
var $simpleTypeStack = array();
|
1149 |
+
var $currentSimpleType = null;
|
1150 |
+
// imports
|
1151 |
+
var $imports = array();
|
1152 |
+
// parser vars
|
1153 |
+
var $parser;
|
1154 |
+
var $position = 0;
|
1155 |
+
var $depth = 0;
|
1156 |
+
var $depth_array = array();
|
1157 |
+
var $message = array();
|
1158 |
+
var $defaultNamespace = array();
|
1159 |
+
|
1160 |
+
/**
|
1161 |
+
* constructor
|
1162 |
+
*
|
1163 |
+
* @param string $schema schema document URI
|
1164 |
+
* @param string $xml xml document URI
|
1165 |
+
* @param string $namespaces namespaces defined in enclosing XML
|
1166 |
+
* @access public
|
1167 |
+
*/
|
1168 |
+
function __construct($schema = '', $xml = '', $namespaces = array())
|
1169 |
+
{
|
1170 |
+
parent::__construct();
|
1171 |
+
$this->debug('nusoap_xmlschema class instantiated, inside constructor');
|
1172 |
+
// files
|
1173 |
+
$this->schema = $schema;
|
1174 |
+
$this->xml = $xml;
|
1175 |
+
|
1176 |
+
// namespaces
|
1177 |
+
$this->enclosingNamespaces = $namespaces;
|
1178 |
+
$this->namespaces = array_merge($this->namespaces, $namespaces);
|
1179 |
+
|
1180 |
+
// parse schema file
|
1181 |
+
if ($schema != '') {
|
1182 |
+
$this->debug('initial schema file: ' . $schema);
|
1183 |
+
$this->parseFile($schema, 'schema');
|
1184 |
+
}
|
1185 |
+
|
1186 |
+
// parse xml file
|
1187 |
+
if ($xml != '') {
|
1188 |
+
$this->debug('initial xml file: ' . $xml);
|
1189 |
+
$this->parseFile($xml, 'xml');
|
1190 |
+
}
|
1191 |
+
|
1192 |
+
}
|
1193 |
+
|
1194 |
+
/**
|
1195 |
+
* parse an XML file
|
1196 |
+
*
|
1197 |
+
* @param string $xml path/URL to XML file
|
1198 |
+
* @param string $type (schema | xml)
|
1199 |
+
* @return boolean
|
1200 |
+
* @access public
|
1201 |
+
*/
|
1202 |
+
function parseFile($xml, $type)
|
1203 |
+
{
|
1204 |
+
// parse xml file
|
1205 |
+
if ($xml != "") {
|
1206 |
+
$xmlStr = @join("", @file($xml));
|
1207 |
+
if ($xmlStr == "") {
|
1208 |
+
$msg = 'Error reading XML from ' . $xml;
|
1209 |
+
$this->setError($msg);
|
1210 |
+
$this->debug($msg);
|
1211 |
+
return false;
|
1212 |
+
} else {
|
1213 |
+
$this->debug("parsing $xml");
|
1214 |
+
$this->parseString($xmlStr, $type);
|
1215 |
+
$this->debug("done parsing $xml");
|
1216 |
+
return true;
|
1217 |
+
}
|
1218 |
+
}
|
1219 |
+
return false;
|
1220 |
+
}
|
1221 |
+
|
1222 |
+
/**
|
1223 |
+
* parse an XML string
|
1224 |
+
*
|
1225 |
+
* @param string $xml path or URL
|
1226 |
+
* @param string $type (schema|xml)
|
1227 |
+
* @access private
|
1228 |
+
*/
|
1229 |
+
function parseString($xml, $type)
|
1230 |
+
{
|
1231 |
+
// parse xml string
|
1232 |
+
if ($xml != "") {
|
1233 |
+
|
1234 |
+
// Create an XML parser.
|
1235 |
+
$this->parser = xml_parser_create();
|
1236 |
+
// Set the options for parsing the XML data.
|
1237 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
1238 |
+
|
1239 |
+
// Set the object for the parser.
|
1240 |
+
xml_set_object($this->parser, $this);
|
1241 |
+
|
1242 |
+
// Set the element handlers for the parser.
|
1243 |
+
if ($type == "schema") {
|
1244 |
+
xml_set_element_handler($this->parser, 'schemaStartElement', 'schemaEndElement');
|
1245 |
+
xml_set_character_data_handler($this->parser, 'schemaCharacterData');
|
1246 |
+
} elseif ($type == "xml") {
|
1247 |
+
xml_set_element_handler($this->parser, 'xmlStartElement', 'xmlEndElement');
|
1248 |
+
xml_set_character_data_handler($this->parser, 'xmlCharacterData');
|
1249 |
+
}
|
1250 |
+
|
1251 |
+
// Parse the XML file.
|
1252 |
+
if (!xml_parse($this->parser, $xml, true)) {
|
1253 |
+
// Display an error message.
|
1254 |
+
$errstr = sprintf('XML error parsing XML schema on line %d: %s',
|
1255 |
+
xml_get_current_line_number($this->parser),
|
1256 |
+
xml_error_string(xml_get_error_code($this->parser))
|
1257 |
+
);
|
1258 |
+
$this->debug($errstr);
|
1259 |
+
$this->debug("XML payload:\n" . $xml);
|
1260 |
+
$this->setError($errstr);
|
1261 |
+
}
|
1262 |
+
|
1263 |
+
xml_parser_free($this->parser);
|
1264 |
+
unset($this->parser);
|
1265 |
+
} else {
|
1266 |
+
$this->debug('no xml passed to parseString()!!');
|
1267 |
+
$this->setError('no xml passed to parseString()!!');
|
1268 |
+
}
|
1269 |
+
}
|
1270 |
+
|
1271 |
+
/**
|
1272 |
+
* gets a type name for an unnamed type
|
1273 |
+
*
|
1274 |
+
* @param string Element name
|
1275 |
+
* @return string A type name for an unnamed type
|
1276 |
+
* @access private
|
1277 |
+
*/
|
1278 |
+
function CreateTypeName($ename)
|
1279 |
+
{
|
1280 |
+
$scope = '';
|
1281 |
+
for ($i = 0; $i < count($this->complexTypeStack); $i++) {
|
1282 |
+
$scope .= $this->complexTypeStack[$i] . '_';
|
1283 |
+
}
|
1284 |
+
return $scope . $ename . '_ContainedType';
|
1285 |
+
}
|
1286 |
+
|
1287 |
+
/**
|
1288 |
+
* start-element handler
|
1289 |
+
*
|
1290 |
+
* @param string $parser XML parser object
|
1291 |
+
* @param string $name element name
|
1292 |
+
* @param string $attrs associative array of attributes
|
1293 |
+
* @access private
|
1294 |
+
*/
|
1295 |
+
function schemaStartElement($parser, $name, $attrs)
|
1296 |
+
{
|
1297 |
+
|
1298 |
+
// position in the total number of elements, starting from 0
|
1299 |
+
$pos = $this->position++;
|
1300 |
+
$depth = $this->depth++;
|
1301 |
+
// set self as current value for this depth
|
1302 |
+
$this->depth_array[$depth] = $pos;
|
1303 |
+
$this->message[$pos] = array('cdata' => '');
|
1304 |
+
if ($depth > 0) {
|
1305 |
+
$this->defaultNamespace[$pos] = $this->defaultNamespace[$this->depth_array[$depth - 1]];
|
1306 |
+
} else {
|
1307 |
+
$this->defaultNamespace[$pos] = false;
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
// get element prefix
|
1311 |
+
if ($prefix = $this->getPrefix($name)) {
|
1312 |
+
// get unqualified name
|
1313 |
+
$name = $this->getLocalPart($name);
|
1314 |
+
} else {
|
1315 |
+
$prefix = '';
|
1316 |
+
}
|
1317 |
+
|
1318 |
+
// loop thru attributes, expanding, and registering namespace declarations
|
1319 |
+
if (count($attrs) > 0) {
|
1320 |
+
foreach ($attrs as $k => $v) {
|
1321 |
+
// if ns declarations, add to class level array of valid namespaces
|
1322 |
+
if (preg_match('/^xmlns/', $k)) {
|
1323 |
+
//$this->xdebug("$k: $v");
|
1324 |
+
//$this->xdebug('ns_prefix: '.$this->getPrefix($k));
|
1325 |
+
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
|
1326 |
+
//$this->xdebug("Add namespace[$ns_prefix] = $v");
|
1327 |
+
$this->namespaces[$ns_prefix] = $v;
|
1328 |
+
} else {
|
1329 |
+
$this->defaultNamespace[$pos] = $v;
|
1330 |
+
if (!$this->getPrefixFromNamespace($v)) {
|
1331 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
|
1332 |
+
}
|
1333 |
+
}
|
1334 |
+
if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
|
1335 |
+
$this->XMLSchemaVersion = $v;
|
1336 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
1337 |
+
}
|
1338 |
+
}
|
1339 |
+
}
|
1340 |
+
foreach ($attrs as $k => $v) {
|
1341 |
+
// expand each attribute
|
1342 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
1343 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
1344 |
+
$eAttrs[$k] = $v;
|
1345 |
+
}
|
1346 |
+
$attrs = $eAttrs;
|
1347 |
+
} else {
|
1348 |
+
$attrs = array();
|
1349 |
+
}
|
1350 |
+
// find status, register data
|
1351 |
+
switch ($name) {
|
1352 |
+
case 'all': // (optional) compositor content for a complexType
|
1353 |
+
case 'choice':
|
1354 |
+
case 'group':
|
1355 |
+
case 'sequence':
|
1356 |
+
//$this->xdebug("compositor $name for currentComplexType: $this->currentComplexType and currentElement: $this->currentElement");
|
1357 |
+
$this->complexTypes[$this->currentComplexType]['compositor'] = $name;
|
1358 |
+
//if($name == 'all' || $name == 'sequence'){
|
1359 |
+
// $this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1360 |
+
//}
|
1361 |
+
break;
|
1362 |
+
case 'attribute': // complexType attribute
|
1363 |
+
//$this->xdebug("parsing attribute $attrs[name] $attrs[ref] of value: ".$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']);
|
1364 |
+
$this->xdebug("parsing attribute:");
|
1365 |
+
$this->appendDebug($this->varDump($attrs));
|
1366 |
+
if (!isset($attrs['form'])) {
|
1367 |
+
// TODO: handle globals
|
1368 |
+
$attrs['form'] = $this->schemaInfo['attributeFormDefault'];
|
1369 |
+
}
|
1370 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
1371 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1372 |
+
if (!strpos($v, ':')) {
|
1373 |
+
// no namespace in arrayType attribute value...
|
1374 |
+
if ($this->defaultNamespace[$pos]) {
|
1375 |
+
// ...so use the default
|
1376 |
+
$attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'] = $this->defaultNamespace[$pos] . ':' . $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1377 |
+
}
|
1378 |
+
}
|
1379 |
+
}
|
1380 |
+
if (isset($attrs['name'])) {
|
1381 |
+
$this->attributes[$attrs['name']] = $attrs;
|
1382 |
+
$aname = $attrs['name'];
|
1383 |
+
} elseif (isset($attrs['ref']) && $attrs['ref'] == 'http://schemas.xmlsoap.org/soap/encoding/:arrayType') {
|
1384 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
1385 |
+
$aname = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1386 |
+
} else {
|
1387 |
+
$aname = '';
|
1388 |
+
}
|
1389 |
+
} elseif (isset($attrs['ref'])) {
|
1390 |
+
$aname = $attrs['ref'];
|
1391 |
+
$this->attributes[$attrs['ref']] = $attrs;
|
1392 |
+
}
|
1393 |
+
|
1394 |
+
if ($this->currentComplexType) { // This should *always* be
|
1395 |
+
$this->complexTypes[$this->currentComplexType]['attrs'][$aname] = $attrs;
|
1396 |
+
}
|
1397 |
+
// arrayType attribute
|
1398 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType']) || $this->getLocalPart($aname) == 'arrayType') {
|
1399 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1400 |
+
$prefix = $this->getPrefix($aname);
|
1401 |
+
if (isset($attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'])) {
|
1402 |
+
$v = $attrs['http://schemas.xmlsoap.org/wsdl/:arrayType'];
|
1403 |
+
} else {
|
1404 |
+
$v = '';
|
1405 |
+
}
|
1406 |
+
if (strpos($v, '[,]')) {
|
1407 |
+
$this->complexTypes[$this->currentComplexType]['multidimensional'] = true;
|
1408 |
+
}
|
1409 |
+
$v = substr($v, 0, strpos($v, '[')); // clip the []
|
1410 |
+
if (!strpos($v, ':') && isset($this->typemap[$this->XMLSchemaVersion][$v])) {
|
1411 |
+
$v = $this->XMLSchemaVersion . ':' . $v;
|
1412 |
+
}
|
1413 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $v;
|
1414 |
+
}
|
1415 |
+
break;
|
1416 |
+
case 'complexContent': // (optional) content for a complexType
|
1417 |
+
$this->xdebug("do nothing for element $name");
|
1418 |
+
break;
|
1419 |
+
case 'complexType':
|
1420 |
+
array_push($this->complexTypeStack, $this->currentComplexType);
|
1421 |
+
if (isset($attrs['name'])) {
|
1422 |
+
// TODO: what is the scope of named complexTypes that appear
|
1423 |
+
// nested within other c complexTypes?
|
1424 |
+
$this->xdebug('processing named complexType ' . $attrs['name']);
|
1425 |
+
//$this->currentElement = false;
|
1426 |
+
$this->currentComplexType = $attrs['name'];
|
1427 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
1428 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
1429 |
+
// This is for constructs like
|
1430 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1431 |
+
// <sequence>
|
1432 |
+
// <element name="string" type="xsd:string"
|
1433 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1434 |
+
// </sequence>
|
1435 |
+
// </complexType>
|
1436 |
+
if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
|
1437 |
+
$this->xdebug('complexType is unusual array');
|
1438 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1439 |
+
} else {
|
1440 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1441 |
+
}
|
1442 |
+
} else {
|
1443 |
+
$name = $this->CreateTypeName($this->currentElement);
|
1444 |
+
$this->xdebug('processing unnamed complexType for element ' . $this->currentElement . ' named ' . $name);
|
1445 |
+
$this->currentComplexType = $name;
|
1446 |
+
//$this->currentElement = false;
|
1447 |
+
$this->complexTypes[$this->currentComplexType] = $attrs;
|
1448 |
+
$this->complexTypes[$this->currentComplexType]['typeClass'] = 'complexType';
|
1449 |
+
// This is for constructs like
|
1450 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1451 |
+
// <sequence>
|
1452 |
+
// <element name="string" type="xsd:string"
|
1453 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1454 |
+
// </sequence>
|
1455 |
+
// </complexType>
|
1456 |
+
if (isset($attrs['base']) && preg_match('/:Array$/', $attrs['base'])) {
|
1457 |
+
$this->xdebug('complexType is unusual array');
|
1458 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1459 |
+
} else {
|
1460 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'struct';
|
1461 |
+
}
|
1462 |
+
}
|
1463 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'false';
|
1464 |
+
break;
|
1465 |
+
case 'element':
|
1466 |
+
array_push($this->elementStack, $this->currentElement);
|
1467 |
+
if (!isset($attrs['form'])) {
|
1468 |
+
if ($this->currentComplexType) {
|
1469 |
+
$attrs['form'] = $this->schemaInfo['elementFormDefault'];
|
1470 |
+
} else {
|
1471 |
+
// global
|
1472 |
+
$attrs['form'] = 'qualified';
|
1473 |
+
}
|
1474 |
+
}
|
1475 |
+
if (isset($attrs['type'])) {
|
1476 |
+
$this->xdebug("processing typed element " . $attrs['name'] . " of type " . $attrs['type']);
|
1477 |
+
if (!$this->getPrefix($attrs['type'])) {
|
1478 |
+
if ($this->defaultNamespace[$pos]) {
|
1479 |
+
$attrs['type'] = $this->defaultNamespace[$pos] . ':' . $attrs['type'];
|
1480 |
+
$this->xdebug('used default namespace to make type ' . $attrs['type']);
|
1481 |
+
}
|
1482 |
+
}
|
1483 |
+
// This is for constructs like
|
1484 |
+
// <complexType name="ListOfString" base="soap:Array">
|
1485 |
+
// <sequence>
|
1486 |
+
// <element name="string" type="xsd:string"
|
1487 |
+
// minOccurs="0" maxOccurs="unbounded" />
|
1488 |
+
// </sequence>
|
1489 |
+
// </complexType>
|
1490 |
+
if ($this->currentComplexType && $this->complexTypes[$this->currentComplexType]['phpType'] == 'array') {
|
1491 |
+
$this->xdebug('arrayType for unusual array is ' . $attrs['type']);
|
1492 |
+
$this->complexTypes[$this->currentComplexType]['arrayType'] = $attrs['type'];
|
1493 |
+
}
|
1494 |
+
$this->currentElement = $attrs['name'];
|
1495 |
+
$ename = $attrs['name'];
|
1496 |
+
} elseif (isset($attrs['ref'])) {
|
1497 |
+
$this->xdebug("processing element as ref to " . $attrs['ref']);
|
1498 |
+
$this->currentElement = "ref to " . $attrs['ref'];
|
1499 |
+
$ename = $this->getLocalPart($attrs['ref']);
|
1500 |
+
} else {
|
1501 |
+
$type = $this->CreateTypeName($this->currentComplexType . '_' . $attrs['name']);
|
1502 |
+
$this->xdebug("processing untyped element " . $attrs['name'] . ' type ' . $type);
|
1503 |
+
$this->currentElement = $attrs['name'];
|
1504 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $type;
|
1505 |
+
$ename = $attrs['name'];
|
1506 |
+
}
|
1507 |
+
if (isset($ename) && $this->currentComplexType) {
|
1508 |
+
$this->xdebug("add element $ename to complexType $this->currentComplexType");
|
1509 |
+
$this->complexTypes[$this->currentComplexType]['elements'][$ename] = $attrs;
|
1510 |
+
} elseif (!isset($attrs['ref'])) {
|
1511 |
+
$this->xdebug("add element $ename to elements array");
|
1512 |
+
$this->elements[$attrs['name']] = $attrs;
|
1513 |
+
$this->elements[$attrs['name']]['typeClass'] = 'element';
|
1514 |
+
}
|
1515 |
+
break;
|
1516 |
+
case 'enumeration': // restriction value list member
|
1517 |
+
$this->xdebug('enumeration ' . $attrs['value']);
|
1518 |
+
if ($this->currentSimpleType) {
|
1519 |
+
$this->simpleTypes[$this->currentSimpleType]['enumeration'][] = $attrs['value'];
|
1520 |
+
} elseif ($this->currentComplexType) {
|
1521 |
+
$this->complexTypes[$this->currentComplexType]['enumeration'][] = $attrs['value'];
|
1522 |
+
}
|
1523 |
+
break;
|
1524 |
+
case 'extension': // simpleContent or complexContent type extension
|
1525 |
+
$this->xdebug('extension ' . $attrs['base']);
|
1526 |
+
if ($this->currentComplexType) {
|
1527 |
+
$ns = $this->getPrefix($attrs['base']);
|
1528 |
+
if ($ns == '') {
|
1529 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $this->schemaTargetNamespace . ':' . $attrs['base'];
|
1530 |
+
} else {
|
1531 |
+
$this->complexTypes[$this->currentComplexType]['extensionBase'] = $attrs['base'];
|
1532 |
+
}
|
1533 |
+
} else {
|
1534 |
+
$this->xdebug('no current complexType to set extensionBase');
|
1535 |
+
}
|
1536 |
+
break;
|
1537 |
+
case 'import':
|
1538 |
+
if (isset($attrs['schemaLocation'])) {
|
1539 |
+
$this->xdebug('import namespace ' . $attrs['namespace'] . ' from ' . $attrs['schemaLocation']);
|
1540 |
+
$this->imports[$attrs['namespace']][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
|
1541 |
+
} else {
|
1542 |
+
$this->xdebug('import namespace ' . $attrs['namespace']);
|
1543 |
+
$this->imports[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
|
1544 |
+
if (!$this->getPrefixFromNamespace($attrs['namespace'])) {
|
1545 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
|
1546 |
+
}
|
1547 |
+
}
|
1548 |
+
break;
|
1549 |
+
case 'include':
|
1550 |
+
if (isset($attrs['schemaLocation'])) {
|
1551 |
+
$this->xdebug('include into namespace ' . $this->schemaTargetNamespace . ' from ' . $attrs['schemaLocation']);
|
1552 |
+
$this->imports[$this->schemaTargetNamespace][] = array('location' => $attrs['schemaLocation'], 'loaded' => false);
|
1553 |
+
} else {
|
1554 |
+
$this->xdebug('ignoring invalid XML Schema construct: include without schemaLocation attribute');
|
1555 |
+
}
|
1556 |
+
break;
|
1557 |
+
case 'list': // simpleType value list
|
1558 |
+
$this->xdebug("do nothing for element $name");
|
1559 |
+
break;
|
1560 |
+
case 'restriction': // simpleType, simpleContent or complexContent value restriction
|
1561 |
+
$this->xdebug('restriction ' . $attrs['base']);
|
1562 |
+
if ($this->currentSimpleType) {
|
1563 |
+
$this->simpleTypes[$this->currentSimpleType]['type'] = $attrs['base'];
|
1564 |
+
} elseif ($this->currentComplexType) {
|
1565 |
+
$this->complexTypes[$this->currentComplexType]['restrictionBase'] = $attrs['base'];
|
1566 |
+
if (strstr($attrs['base'], ':') == ':Array') {
|
1567 |
+
$this->complexTypes[$this->currentComplexType]['phpType'] = 'array';
|
1568 |
+
}
|
1569 |
+
}
|
1570 |
+
break;
|
1571 |
+
case 'schema':
|
1572 |
+
$this->schemaInfo = $attrs;
|
1573 |
+
$this->schemaInfo['schemaVersion'] = $this->getNamespaceFromPrefix($prefix);
|
1574 |
+
if (isset($attrs['targetNamespace'])) {
|
1575 |
+
$this->schemaTargetNamespace = $attrs['targetNamespace'];
|
1576 |
+
}
|
1577 |
+
if (!isset($attrs['elementFormDefault'])) {
|
1578 |
+
$this->schemaInfo['elementFormDefault'] = 'unqualified';
|
1579 |
+
}
|
1580 |
+
if (!isset($attrs['attributeFormDefault'])) {
|
1581 |
+
$this->schemaInfo['attributeFormDefault'] = 'unqualified';
|
1582 |
+
}
|
1583 |
+
break;
|
1584 |
+
case 'simpleContent': // (optional) content for a complexType
|
1585 |
+
if ($this->currentComplexType) { // This should *always* be
|
1586 |
+
$this->complexTypes[$this->currentComplexType]['simpleContent'] = 'true';
|
1587 |
+
} else {
|
1588 |
+
$this->xdebug("do nothing for element $name because there is no current complexType");
|
1589 |
+
}
|
1590 |
+
break;
|
1591 |
+
case 'simpleType':
|
1592 |
+
array_push($this->simpleTypeStack, $this->currentSimpleType);
|
1593 |
+
if (isset($attrs['name'])) {
|
1594 |
+
$this->xdebug("processing simpleType for name " . $attrs['name']);
|
1595 |
+
$this->currentSimpleType = $attrs['name'];
|
1596 |
+
$this->simpleTypes[$attrs['name']] = $attrs;
|
1597 |
+
$this->simpleTypes[$attrs['name']]['typeClass'] = 'simpleType';
|
1598 |
+
$this->simpleTypes[$attrs['name']]['phpType'] = 'scalar';
|
1599 |
+
} else {
|
1600 |
+
$name = $this->CreateTypeName($this->currentComplexType . '_' . $this->currentElement);
|
1601 |
+
$this->xdebug('processing unnamed simpleType for element ' . $this->currentElement . ' named ' . $name);
|
1602 |
+
$this->currentSimpleType = $name;
|
1603 |
+
//$this->currentElement = false;
|
1604 |
+
$this->simpleTypes[$this->currentSimpleType] = $attrs;
|
1605 |
+
$this->simpleTypes[$this->currentSimpleType]['phpType'] = 'scalar';
|
1606 |
+
}
|
1607 |
+
break;
|
1608 |
+
case 'union': // simpleType type list
|
1609 |
+
$this->xdebug("do nothing for element $name");
|
1610 |
+
break;
|
1611 |
+
default:
|
1612 |
+
$this->xdebug("do not have any logic to process element $name");
|
1613 |
+
}
|
1614 |
+
}
|
1615 |
+
|
1616 |
+
/**
|
1617 |
+
* end-element handler
|
1618 |
+
*
|
1619 |
+
* @param string $parser XML parser object
|
1620 |
+
* @param string $name element name
|
1621 |
+
* @access private
|
1622 |
+
*/
|
1623 |
+
function schemaEndElement($parser, $name)
|
1624 |
+
{
|
1625 |
+
// bring depth down a notch
|
1626 |
+
$this->depth--;
|
1627 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
1628 |
+
if (isset($this->depth_array[$this->depth])) {
|
1629 |
+
$pos = $this->depth_array[$this->depth];
|
1630 |
+
}
|
1631 |
+
// get element prefix
|
1632 |
+
if ($prefix = $this->getPrefix($name)) {
|
1633 |
+
// get unqualified name
|
1634 |
+
$name = $this->getLocalPart($name);
|
1635 |
+
} else {
|
1636 |
+
$prefix = '';
|
1637 |
+
}
|
1638 |
+
// move on...
|
1639 |
+
if ($name == 'complexType') {
|
1640 |
+
$this->xdebug('done processing complexType ' . ($this->currentComplexType ? $this->currentComplexType : '(unknown)'));
|
1641 |
+
$this->xdebug($this->varDump($this->complexTypes[$this->currentComplexType]));
|
1642 |
+
$this->currentComplexType = array_pop($this->complexTypeStack);
|
1643 |
+
//$this->currentElement = false;
|
1644 |
+
}
|
1645 |
+
if ($name == 'element') {
|
1646 |
+
$this->xdebug('done processing element ' . ($this->currentElement ? $this->currentElement : '(unknown)'));
|
1647 |
+
$this->currentElement = array_pop($this->elementStack);
|
1648 |
+
}
|
1649 |
+
if ($name == 'simpleType') {
|
1650 |
+
$this->xdebug('done processing simpleType ' . ($this->currentSimpleType ? $this->currentSimpleType : '(unknown)'));
|
1651 |
+
$this->xdebug($this->varDump($this->simpleTypes[$this->currentSimpleType]));
|
1652 |
+
$this->currentSimpleType = array_pop($this->simpleTypeStack);
|
1653 |
+
}
|
1654 |
+
}
|
1655 |
+
|
1656 |
+
/**
|
1657 |
+
* element content handler
|
1658 |
+
*
|
1659 |
+
* @param string $parser XML parser object
|
1660 |
+
* @param string $data element content
|
1661 |
+
* @access private
|
1662 |
+
*/
|
1663 |
+
function schemaCharacterData($parser, $data)
|
1664 |
+
{
|
1665 |
+
$pos = $this->depth_array[$this->depth - 1];
|
1666 |
+
$this->message[$pos]['cdata'] .= $data;
|
1667 |
+
}
|
1668 |
+
|
1669 |
+
/**
|
1670 |
+
* serialize the schema
|
1671 |
+
*
|
1672 |
+
* @access public
|
1673 |
+
*/
|
1674 |
+
function serializeSchema()
|
1675 |
+
{
|
1676 |
+
|
1677 |
+
$schemaPrefix = $this->getPrefixFromNamespace($this->XMLSchemaVersion);
|
1678 |
+
$xml = '';
|
1679 |
+
// imports
|
1680 |
+
if (sizeof($this->imports) > 0) {
|
1681 |
+
foreach ($this->imports as $ns => $list) {
|
1682 |
+
foreach ($list as $ii) {
|
1683 |
+
if ($ii['location'] != '') {
|
1684 |
+
$xml .= " <$schemaPrefix:import location=\"" . $ii['location'] . '" namespace="' . $ns . "\" />\n";
|
1685 |
+
} else {
|
1686 |
+
$xml .= " <$schemaPrefix:import namespace=\"" . $ns . "\" />\n";
|
1687 |
+
}
|
1688 |
+
}
|
1689 |
+
}
|
1690 |
+
}
|
1691 |
+
// complex types
|
1692 |
+
foreach ($this->complexTypes as $typeName => $attrs) {
|
1693 |
+
$contentStr = '';
|
1694 |
+
// serialize child elements
|
1695 |
+
if (isset($attrs['elements']) && (count($attrs['elements']) > 0)) {
|
1696 |
+
foreach ($attrs['elements'] as $element => $eParts) {
|
1697 |
+
if (isset($eParts['ref'])) {
|
1698 |
+
$contentStr .= " <$schemaPrefix:element ref=\"$element\"/>\n";
|
1699 |
+
} else {
|
1700 |
+
$contentStr .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"";
|
1701 |
+
foreach ($eParts as $aName => $aValue) {
|
1702 |
+
// handle, e.g., abstract, default, form, minOccurs, maxOccurs, nillable
|
1703 |
+
if ($aName != 'name' && $aName != 'type') {
|
1704 |
+
$contentStr .= " $aName=\"$aValue\"";
|
1705 |
+
}
|
1706 |
+
}
|
1707 |
+
$contentStr .= "/>\n";
|
1708 |
+
}
|
1709 |
+
}
|
1710 |
+
// compositor wraps elements
|
1711 |
+
if (isset($attrs['compositor']) && ($attrs['compositor'] != '')) {
|
1712 |
+
$contentStr = " <$schemaPrefix:$attrs[compositor]>\n" . $contentStr . " </$schemaPrefix:$attrs[compositor]>\n";
|
1713 |
+
}
|
1714 |
+
}
|
1715 |
+
// attributes
|
1716 |
+
if (isset($attrs['attrs']) && (count($attrs['attrs']) >= 1)) {
|
1717 |
+
foreach ($attrs['attrs'] as $attr => $aParts) {
|
1718 |
+
$contentStr .= " <$schemaPrefix:attribute";
|
1719 |
+
foreach ($aParts as $a => $v) {
|
1720 |
+
if ($a == 'ref' || $a == 'type') {
|
1721 |
+
$contentStr .= " $a=\"" . $this->contractQName($v) . '"';
|
1722 |
+
} elseif ($a == 'http://schemas.xmlsoap.org/wsdl/:arrayType') {
|
1723 |
+
$this->usedNamespaces['wsdl'] = $this->namespaces['wsdl'];
|
1724 |
+
$contentStr .= ' wsdl:arrayType="' . $this->contractQName($v) . '"';
|
1725 |
+
} else {
|
1726 |
+
$contentStr .= " $a=\"$v\"";
|
1727 |
+
}
|
1728 |
+
}
|
1729 |
+
$contentStr .= "/>\n";
|
1730 |
+
}
|
1731 |
+
}
|
1732 |
+
// if restriction
|
1733 |
+
if (isset($attrs['restrictionBase']) && $attrs['restrictionBase'] != '') {
|
1734 |
+
$contentStr = " <$schemaPrefix:restriction base=\"" . $this->contractQName($attrs['restrictionBase']) . "\">\n" . $contentStr . " </$schemaPrefix:restriction>\n";
|
1735 |
+
// complex or simple content
|
1736 |
+
if ((isset($attrs['elements']) && count($attrs['elements']) > 0) || (isset($attrs['attrs']) && count($attrs['attrs']) > 0)) {
|
1737 |
+
$contentStr = " <$schemaPrefix:complexContent>\n" . $contentStr . " </$schemaPrefix:complexContent>\n";
|
1738 |
+
}
|
1739 |
+
}
|
1740 |
+
// finalize complex type
|
1741 |
+
if ($contentStr != '') {
|
1742 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\">\n" . $contentStr . " </$schemaPrefix:complexType>\n";
|
1743 |
+
} else {
|
1744 |
+
$contentStr = " <$schemaPrefix:complexType name=\"$typeName\"/>\n";
|
1745 |
+
}
|
1746 |
+
$xml .= $contentStr;
|
1747 |
+
}
|
1748 |
+
// simple types
|
1749 |
+
if (isset($this->simpleTypes) && count($this->simpleTypes) > 0) {
|
1750 |
+
foreach ($this->simpleTypes as $typeName => $eParts) {
|
1751 |
+
$xml .= " <$schemaPrefix:simpleType name=\"$typeName\">\n <$schemaPrefix:restriction base=\"" . $this->contractQName($eParts['type']) . "\">\n";
|
1752 |
+
if (isset($eParts['enumeration'])) {
|
1753 |
+
foreach ($eParts['enumeration'] as $e) {
|
1754 |
+
$xml .= " <$schemaPrefix:enumeration value=\"$e\"/>\n";
|
1755 |
+
}
|
1756 |
+
}
|
1757 |
+
$xml .= " </$schemaPrefix:restriction>\n </$schemaPrefix:simpleType>";
|
1758 |
+
}
|
1759 |
+
}
|
1760 |
+
// elements
|
1761 |
+
if (isset($this->elements) && count($this->elements) > 0) {
|
1762 |
+
foreach ($this->elements as $element => $eParts) {
|
1763 |
+
$xml .= " <$schemaPrefix:element name=\"$element\" type=\"" . $this->contractQName($eParts['type']) . "\"/>\n";
|
1764 |
+
}
|
1765 |
+
}
|
1766 |
+
// attributes
|
1767 |
+
if (isset($this->attributes) && count($this->attributes) > 0) {
|
1768 |
+
foreach ($this->attributes as $attr => $aParts) {
|
1769 |
+
$xml .= " <$schemaPrefix:attribute name=\"$attr\" type=\"" . $this->contractQName($aParts['type']) . "\"\n/>";
|
1770 |
+
}
|
1771 |
+
}
|
1772 |
+
// finish 'er up
|
1773 |
+
$attr = '';
|
1774 |
+
foreach ($this->schemaInfo as $k => $v) {
|
1775 |
+
if ($k == 'elementFormDefault' || $k == 'attributeFormDefault') {
|
1776 |
+
$attr .= " $k=\"$v\"";
|
1777 |
+
}
|
1778 |
+
}
|
1779 |
+
$el = "<$schemaPrefix:schema$attr targetNamespace=\"$this->schemaTargetNamespace\"\n";
|
1780 |
+
foreach (array_diff($this->usedNamespaces, $this->enclosingNamespaces) as $nsp => $ns) {
|
1781 |
+
$el .= " xmlns:$nsp=\"$ns\"";
|
1782 |
+
}
|
1783 |
+
$xml = $el . ">\n" . $xml . "</$schemaPrefix:schema>\n";
|
1784 |
+
return $xml;
|
1785 |
+
}
|
1786 |
+
|
1787 |
+
/**
|
1788 |
+
* adds debug data to the clas level debug string
|
1789 |
+
*
|
1790 |
+
* @param string $string debug data
|
1791 |
+
* @access private
|
1792 |
+
*/
|
1793 |
+
function xdebug($string)
|
1794 |
+
{
|
1795 |
+
$this->debug('<' . $this->schemaTargetNamespace . '> ' . $string);
|
1796 |
+
}
|
1797 |
+
|
1798 |
+
/**
|
1799 |
+
* get the PHP type of a user defined type in the schema
|
1800 |
+
* PHP type is kind of a misnomer since it actually returns 'struct' for assoc. arrays
|
1801 |
+
* returns false if no type exists, or not w/ the given namespace
|
1802 |
+
* else returns a string that is either a native php type, or 'struct'
|
1803 |
+
*
|
1804 |
+
* @param string $type name of defined type
|
1805 |
+
* @param string $ns namespace of type
|
1806 |
+
* @return mixed
|
1807 |
+
* @access public
|
1808 |
+
* @deprecated
|
1809 |
+
*/
|
1810 |
+
function getPHPType($type, $ns)
|
1811 |
+
{
|
1812 |
+
if (isset($this->typemap[$ns][$type])) {
|
1813 |
+
//print "found type '$type' and ns $ns in typemap<br>";
|
1814 |
+
return $this->typemap[$ns][$type];
|
1815 |
+
} elseif (isset($this->complexTypes[$type])) {
|
1816 |
+
//print "getting type '$type' and ns $ns from complexTypes array<br>";
|
1817 |
+
return $this->complexTypes[$type]['phpType'];
|
1818 |
+
}
|
1819 |
+
return false;
|
1820 |
+
}
|
1821 |
+
|
1822 |
+
/**
|
1823 |
+
* returns an associative array of information about a given type
|
1824 |
+
* returns false if no type exists by the given name
|
1825 |
+
*
|
1826 |
+
* For a complexType typeDef = array(
|
1827 |
+
* 'restrictionBase' => '',
|
1828 |
+
* 'phpType' => '',
|
1829 |
+
* 'compositor' => '(sequence|all)',
|
1830 |
+
* 'elements' => array(), // refs to elements array
|
1831 |
+
* 'attrs' => array() // refs to attributes array
|
1832 |
+
* ... and so on (see addComplexType)
|
1833 |
+
* )
|
1834 |
+
*
|
1835 |
+
* For simpleType or element, the array has different keys.
|
1836 |
+
*
|
1837 |
+
* @param string $type
|
1838 |
+
* @return mixed
|
1839 |
+
* @access public
|
1840 |
+
* @see addComplexType
|
1841 |
+
* @see addSimpleType
|
1842 |
+
* @see addElement
|
1843 |
+
*/
|
1844 |
+
function getTypeDef($type)
|
1845 |
+
{
|
1846 |
+
//$this->debug("in getTypeDef for type $type");
|
1847 |
+
if (substr($type, -1) == '^') {
|
1848 |
+
$is_element = 1;
|
1849 |
+
$type = substr($type, 0, -1);
|
1850 |
+
} else {
|
1851 |
+
$is_element = 0;
|
1852 |
+
}
|
1853 |
+
|
1854 |
+
if ((!$is_element) && isset($this->complexTypes[$type])) {
|
1855 |
+
$this->xdebug("in getTypeDef, found complexType $type");
|
1856 |
+
return $this->complexTypes[$type];
|
1857 |
+
} elseif ((!$is_element) && isset($this->simpleTypes[$type])) {
|
1858 |
+
$this->xdebug("in getTypeDef, found simpleType $type");
|
1859 |
+
if (!isset($this->simpleTypes[$type]['phpType'])) {
|
1860 |
+
// get info for type to tack onto the simple type
|
1861 |
+
// TODO: can this ever really apply (i.e. what is a simpleType really?)
|
1862 |
+
$uqType = substr($this->simpleTypes[$type]['type'], strrpos($this->simpleTypes[$type]['type'], ':') + 1);
|
1863 |
+
$ns = substr($this->simpleTypes[$type]['type'], 0, strrpos($this->simpleTypes[$type]['type'], ':'));
|
1864 |
+
$etype = $this->getTypeDef($uqType);
|
1865 |
+
if ($etype) {
|
1866 |
+
$this->xdebug("in getTypeDef, found type for simpleType $type:");
|
1867 |
+
$this->xdebug($this->varDump($etype));
|
1868 |
+
if (isset($etype['phpType'])) {
|
1869 |
+
$this->simpleTypes[$type]['phpType'] = $etype['phpType'];
|
1870 |
+
}
|
1871 |
+
if (isset($etype['elements'])) {
|
1872 |
+
$this->simpleTypes[$type]['elements'] = $etype['elements'];
|
1873 |
+
}
|
1874 |
+
}
|
1875 |
+
}
|
1876 |
+
return $this->simpleTypes[$type];
|
1877 |
+
} elseif (isset($this->elements[$type])) {
|
1878 |
+
$this->xdebug("in getTypeDef, found element $type");
|
1879 |
+
if (!isset($this->elements[$type]['phpType'])) {
|
1880 |
+
// get info for type to tack onto the element
|
1881 |
+
$uqType = substr($this->elements[$type]['type'], strrpos($this->elements[$type]['type'], ':') + 1);
|
1882 |
+
$ns = substr($this->elements[$type]['type'], 0, strrpos($this->elements[$type]['type'], ':'));
|
1883 |
+
$etype = $this->getTypeDef($uqType);
|
1884 |
+
if ($etype) {
|
1885 |
+
$this->xdebug("in getTypeDef, found type for element $type:");
|
1886 |
+
$this->xdebug($this->varDump($etype));
|
1887 |
+
if (isset($etype['phpType'])) {
|
1888 |
+
$this->elements[$type]['phpType'] = $etype['phpType'];
|
1889 |
+
}
|
1890 |
+
if (isset($etype['elements'])) {
|
1891 |
+
$this->elements[$type]['elements'] = $etype['elements'];
|
1892 |
+
}
|
1893 |
+
if (isset($etype['extensionBase'])) {
|
1894 |
+
$this->elements[$type]['extensionBase'] = $etype['extensionBase'];
|
1895 |
+
}
|
1896 |
+
} elseif ($ns == 'http://www.w3.org/2001/XMLSchema') {
|
1897 |
+
$this->xdebug("in getTypeDef, element $type is an XSD type");
|
1898 |
+
$this->elements[$type]['phpType'] = 'scalar';
|
1899 |
+
}
|
1900 |
+
}
|
1901 |
+
return $this->elements[$type];
|
1902 |
+
} elseif (isset($this->attributes[$type])) {
|
1903 |
+
$this->xdebug("in getTypeDef, found attribute $type");
|
1904 |
+
return $this->attributes[$type];
|
1905 |
+
} elseif (preg_match('/_ContainedType$/', $type)) {
|
1906 |
+
$this->xdebug("in getTypeDef, have an untyped element $type");
|
1907 |
+
$typeDef['typeClass'] = 'simpleType';
|
1908 |
+
$typeDef['phpType'] = 'scalar';
|
1909 |
+
$typeDef['type'] = 'http://www.w3.org/2001/XMLSchema:string';
|
1910 |
+
return $typeDef;
|
1911 |
+
}
|
1912 |
+
$this->xdebug("in getTypeDef, did not find $type");
|
1913 |
+
return false;
|
1914 |
+
}
|
1915 |
+
|
1916 |
+
/**
|
1917 |
+
* returns a sample serialization of a given type, or false if no type by the given name
|
1918 |
+
*
|
1919 |
+
* @param string $type name of type
|
1920 |
+
* @return mixed
|
1921 |
+
* @access public
|
1922 |
+
* @deprecated
|
1923 |
+
*/
|
1924 |
+
function serializeTypeDef($type)
|
1925 |
+
{
|
1926 |
+
//print "in sTD() for type $type<br>";
|
1927 |
+
if ($typeDef = $this->getTypeDef($type)) {
|
1928 |
+
$str .= '<' . $type;
|
1929 |
+
if (is_array($typeDef['attrs'])) {
|
1930 |
+
foreach ($typeDef['attrs'] as $attName => $data) {
|
1931 |
+
$str .= " $attName=\"{type = " . $data['type'] . "}\"";
|
1932 |
+
}
|
1933 |
+
}
|
1934 |
+
$str .= " xmlns=\"" . $this->schema['targetNamespace'] . "\"";
|
1935 |
+
if (count($typeDef['elements']) > 0) {
|
1936 |
+
$str .= ">";
|
1937 |
+
foreach ($typeDef['elements'] as $element => $eData) {
|
1938 |
+
$str .= $this->serializeTypeDef($element);
|
1939 |
+
}
|
1940 |
+
$str .= "</$type>";
|
1941 |
+
} elseif ($typeDef['typeClass'] == 'element') {
|
1942 |
+
$str .= "></$type>";
|
1943 |
+
} else {
|
1944 |
+
$str .= "/>";
|
1945 |
+
}
|
1946 |
+
return $str;
|
1947 |
+
}
|
1948 |
+
return false;
|
1949 |
+
}
|
1950 |
+
|
1951 |
+
/**
|
1952 |
+
* returns HTML form elements that allow a user
|
1953 |
+
* to enter values for creating an instance of the given type.
|
1954 |
+
*
|
1955 |
+
* @param string $name name for type instance
|
1956 |
+
* @param string $type name of type
|
1957 |
+
* @return string
|
1958 |
+
* @access public
|
1959 |
+
* @deprecated
|
1960 |
+
*/
|
1961 |
+
function typeToForm($name, $type)
|
1962 |
+
{
|
1963 |
+
// get typedef
|
1964 |
+
if ($typeDef = $this->getTypeDef($type)) {
|
1965 |
+
// if struct
|
1966 |
+
if ($typeDef['phpType'] == 'struct') {
|
1967 |
+
$buffer .= '<table>';
|
1968 |
+
foreach ($typeDef['elements'] as $child => $childDef) {
|
1969 |
+
$buffer .= "
|
1970 |
+
<tr><td align='right'>$childDef[name] (type: " . $this->getLocalPart($childDef['type']) . "):</td>
|
1971 |
+
<td><input type='text' name='parameters[" . $name . "][$childDef[name]]'></td></tr>";
|
1972 |
+
}
|
1973 |
+
$buffer .= '</table>';
|
1974 |
+
// if array
|
1975 |
+
} elseif ($typeDef['phpType'] == 'array') {
|
1976 |
+
$buffer .= '<table>';
|
1977 |
+
for ($i = 0; $i < 3; $i++) {
|
1978 |
+
$buffer .= "
|
1979 |
+
<tr><td align='right'>array item (type: $typeDef[arrayType]):</td>
|
1980 |
+
<td><input type='text' name='parameters[" . $name . "][]'></td></tr>";
|
1981 |
+
}
|
1982 |
+
$buffer .= '</table>';
|
1983 |
+
// if scalar
|
1984 |
+
} else {
|
1985 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
1986 |
+
}
|
1987 |
+
} else {
|
1988 |
+
$buffer .= "<input type='text' name='parameters[$name]'>";
|
1989 |
+
}
|
1990 |
+
return $buffer;
|
1991 |
+
}
|
1992 |
+
|
1993 |
+
/**
|
1994 |
+
* adds a complex type to the schema
|
1995 |
+
*
|
1996 |
+
* example: array
|
1997 |
+
*
|
1998 |
+
* addType(
|
1999 |
+
* 'ArrayOfstring',
|
2000 |
+
* 'complexType',
|
2001 |
+
* 'array',
|
2002 |
+
* '',
|
2003 |
+
* 'SOAP-ENC:Array',
|
2004 |
+
* array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]'),
|
2005 |
+
* 'xsd:string'
|
2006 |
+
* );
|
2007 |
+
*
|
2008 |
+
* example: PHP associative array ( SOAP Struct )
|
2009 |
+
*
|
2010 |
+
* addType(
|
2011 |
+
* 'SOAPStruct',
|
2012 |
+
* 'complexType',
|
2013 |
+
* 'struct',
|
2014 |
+
* 'all',
|
2015 |
+
* array('myVar'=> array('name'=>'myVar','type'=>'string')
|
2016 |
+
* );
|
2017 |
+
*
|
2018 |
+
* @param name
|
2019 |
+
* @param typeClass (complexType|simpleType|attribute)
|
2020 |
+
* @param phpType : currently supported are array and struct (php assoc array)
|
2021 |
+
* @param compositor (all|sequence|choice)
|
2022 |
+
* @param restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
2023 |
+
* @param elements = array ( name = array(name=>'',type=>'') )
|
2024 |
+
* @param attrs = array(
|
2025 |
+
* array(
|
2026 |
+
* 'ref' => "http://schemas.xmlsoap.org/soap/encoding/:arrayType",
|
2027 |
+
* "http://schemas.xmlsoap.org/wsdl/:arrayType" => "string[]"
|
2028 |
+
* )
|
2029 |
+
* )
|
2030 |
+
* @param arrayType : namespace:name (http://www.w3.org/2001/XMLSchema:string)
|
2031 |
+
* @access public
|
2032 |
+
* @see getTypeDef
|
2033 |
+
*/
|
2034 |
+
function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
|
2035 |
+
{
|
2036 |
+
$this->complexTypes[$name] = array(
|
2037 |
+
'name' => $name,
|
2038 |
+
'typeClass' => $typeClass,
|
2039 |
+
'phpType' => $phpType,
|
2040 |
+
'compositor' => $compositor,
|
2041 |
+
'restrictionBase' => $restrictionBase,
|
2042 |
+
'elements' => $elements,
|
2043 |
+
'attrs' => $attrs,
|
2044 |
+
'arrayType' => $arrayType
|
2045 |
+
);
|
2046 |
+
|
2047 |
+
$this->xdebug("addComplexType $name:");
|
2048 |
+
$this->appendDebug($this->varDump($this->complexTypes[$name]));
|
2049 |
+
}
|
2050 |
+
|
2051 |
+
/**
|
2052 |
+
* adds a simple type to the schema
|
2053 |
+
*
|
2054 |
+
* @param string $name
|
2055 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
2056 |
+
* @param string $typeClass (should always be simpleType)
|
2057 |
+
* @param string $phpType (should always be scalar)
|
2058 |
+
* @param array $enumeration array of values
|
2059 |
+
* @access public
|
2060 |
+
* @see nusoap_xmlschema
|
2061 |
+
* @see getTypeDef
|
2062 |
+
*/
|
2063 |
+
function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
|
2064 |
+
{
|
2065 |
+
$this->simpleTypes[$name] = array(
|
2066 |
+
'name' => $name,
|
2067 |
+
'typeClass' => $typeClass,
|
2068 |
+
'phpType' => $phpType,
|
2069 |
+
'type' => $restrictionBase,
|
2070 |
+
'enumeration' => $enumeration
|
2071 |
+
);
|
2072 |
+
|
2073 |
+
$this->xdebug("addSimpleType $name:");
|
2074 |
+
$this->appendDebug($this->varDump($this->simpleTypes[$name]));
|
2075 |
+
}
|
2076 |
+
|
2077 |
+
/**
|
2078 |
+
* adds an element to the schema
|
2079 |
+
*
|
2080 |
+
* @param array $attrs attributes that must include name and type
|
2081 |
+
* @see nusoap_xmlschema
|
2082 |
+
* @access public
|
2083 |
+
*/
|
2084 |
+
function addElement($attrs)
|
2085 |
+
{
|
2086 |
+
if (!$this->getPrefix($attrs['type'])) {
|
2087 |
+
$attrs['type'] = $this->schemaTargetNamespace . ':' . $attrs['type'];
|
2088 |
+
}
|
2089 |
+
$this->elements[$attrs['name']] = $attrs;
|
2090 |
+
$this->elements[$attrs['name']]['typeClass'] = 'element';
|
2091 |
+
|
2092 |
+
$this->xdebug("addElement " . $attrs['name']);
|
2093 |
+
$this->appendDebug($this->varDump($this->elements[$attrs['name']]));
|
2094 |
+
}
|
2095 |
+
}
|
2096 |
+
|
2097 |
+
/**
|
2098 |
+
* Backward compatibility
|
2099 |
+
*/
|
2100 |
+
class XMLSchema extends nusoap_xmlschema
|
2101 |
+
{
|
2102 |
+
}
|
2103 |
+
|
2104 |
+
|
2105 |
+
/**
|
2106 |
+
* For creating serializable abstractions of native PHP types. This class
|
2107 |
+
* allows element name/namespace, XSD type, and XML attributes to be
|
2108 |
+
* associated with a value. This is extremely useful when WSDL is not
|
2109 |
+
* used, but is also useful when WSDL is used with polymorphic types, including
|
2110 |
+
* xsd:anyType and user-defined types.
|
2111 |
+
*
|
2112 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2113 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2114 |
+
* @access public
|
2115 |
+
*/
|
2116 |
+
class soapval extends nusoap_base
|
2117 |
+
{
|
2118 |
+
/**
|
2119 |
+
* The XML element name
|
2120 |
+
*
|
2121 |
+
* @var string
|
2122 |
+
* @access private
|
2123 |
+
*/
|
2124 |
+
var $name;
|
2125 |
+
/**
|
2126 |
+
* The XML type name (string or false)
|
2127 |
+
*
|
2128 |
+
* @var mixed
|
2129 |
+
* @access private
|
2130 |
+
*/
|
2131 |
+
var $type;
|
2132 |
+
/**
|
2133 |
+
* The PHP value
|
2134 |
+
*
|
2135 |
+
* @var mixed
|
2136 |
+
* @access private
|
2137 |
+
*/
|
2138 |
+
var $value;
|
2139 |
+
/**
|
2140 |
+
* The XML element namespace (string or false)
|
2141 |
+
*
|
2142 |
+
* @var mixed
|
2143 |
+
* @access private
|
2144 |
+
*/
|
2145 |
+
var $element_ns;
|
2146 |
+
/**
|
2147 |
+
* The XML type namespace (string or false)
|
2148 |
+
*
|
2149 |
+
* @var mixed
|
2150 |
+
* @access private
|
2151 |
+
*/
|
2152 |
+
var $type_ns;
|
2153 |
+
/**
|
2154 |
+
* The XML element attributes (array or false)
|
2155 |
+
*
|
2156 |
+
* @var mixed
|
2157 |
+
* @access private
|
2158 |
+
*/
|
2159 |
+
var $attributes;
|
2160 |
+
|
2161 |
+
/**
|
2162 |
+
* constructor
|
2163 |
+
*
|
2164 |
+
* @param string $name optional name
|
2165 |
+
* @param mixed $type optional type name
|
2166 |
+
* @param mixed $value optional value
|
2167 |
+
* @param mixed $element_ns optional namespace of value
|
2168 |
+
* @param mixed $type_ns optional namespace of type
|
2169 |
+
* @param mixed $attributes associative array of attributes to add to element serialization
|
2170 |
+
* @access public
|
2171 |
+
*/
|
2172 |
+
function __construct($name = 'soapval', $type = false, $value = -1, $element_ns = false, $type_ns = false, $attributes = false)
|
2173 |
+
{
|
2174 |
+
parent::__construct();
|
2175 |
+
$this->name = $name;
|
2176 |
+
$this->type = $type;
|
2177 |
+
$this->value = $value;
|
2178 |
+
$this->element_ns = $element_ns;
|
2179 |
+
$this->type_ns = $type_ns;
|
2180 |
+
$this->attributes = $attributes;
|
2181 |
+
}
|
2182 |
+
|
2183 |
+
/**
|
2184 |
+
* return serialized value
|
2185 |
+
*
|
2186 |
+
* @param string $use The WSDL use value (encoded|literal)
|
2187 |
+
* @return string XML data
|
2188 |
+
* @access public
|
2189 |
+
*/
|
2190 |
+
function serialize($use = 'encoded')
|
2191 |
+
{
|
2192 |
+
return $this->serialize_val($this->value, $this->name, $this->type, $this->element_ns, $this->type_ns, $this->attributes, $use, true);
|
2193 |
+
}
|
2194 |
+
|
2195 |
+
/**
|
2196 |
+
* decodes a soapval object into a PHP native type
|
2197 |
+
*
|
2198 |
+
* @return mixed
|
2199 |
+
* @access public
|
2200 |
+
*/
|
2201 |
+
function decode()
|
2202 |
+
{
|
2203 |
+
return $this->value;
|
2204 |
+
}
|
2205 |
+
}
|
2206 |
+
|
2207 |
+
|
2208 |
+
/**
|
2209 |
+
* transport class for sending/receiving data via HTTP and HTTPS
|
2210 |
+
* NOTE: PHP must be compiled with the CURL extension for HTTPS support
|
2211 |
+
*
|
2212 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
2213 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
2214 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
2215 |
+
* @access public
|
2216 |
+
*/
|
2217 |
+
class soap_transport_http extends nusoap_base
|
2218 |
+
{
|
2219 |
+
|
2220 |
+
var $url = '';
|
2221 |
+
var $uri = '';
|
2222 |
+
var $digest_uri = '';
|
2223 |
+
var $scheme = '';
|
2224 |
+
var $host = '';
|
2225 |
+
var $port = '';
|
2226 |
+
var $path = '';
|
2227 |
+
var $request_method = 'POST';
|
2228 |
+
var $protocol_version = '1.0';
|
2229 |
+
var $encoding = '';
|
2230 |
+
var $outgoing_headers = array();
|
2231 |
+
var $incoming_headers = array();
|
2232 |
+
var $incoming_cookies = array();
|
2233 |
+
var $outgoing_payload = '';
|
2234 |
+
var $incoming_payload = '';
|
2235 |
+
var $response_status_line; // HTTP response status line
|
2236 |
+
var $useSOAPAction = true;
|
2237 |
+
var $persistentConnection = false;
|
2238 |
+
var $ch = false; // cURL handle
|
2239 |
+
var $ch_options = array(); // cURL custom options
|
2240 |
+
var $use_curl = false; // force cURL use
|
2241 |
+
var $proxy = null; // proxy information (associative array)
|
2242 |
+
var $username = '';
|
2243 |
+
var $password = '';
|
2244 |
+
var $authtype = '';
|
2245 |
+
var $digestRequest = array();
|
2246 |
+
var $certRequest = array(); // keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional)
|
2247 |
+
// cainfofile: certificate authority file, e.g. '$pathToPemFiles/rootca.pem'
|
2248 |
+
// sslcertfile: SSL certificate file, e.g. '$pathToPemFiles/mycert.pem'
|
2249 |
+
// sslkeyfile: SSL key file, e.g. '$pathToPemFiles/mykey.pem'
|
2250 |
+
// passphrase: SSL key password/passphrase
|
2251 |
+
// certpassword: SSL certificate password
|
2252 |
+
// verifypeer: default is 1
|
2253 |
+
// verifyhost: default is 1
|
2254 |
+
|
2255 |
+
/**
|
2256 |
+
* constructor
|
2257 |
+
*
|
2258 |
+
* @param string $url The URL to which to connect
|
2259 |
+
* @param array $curl_options User-specified cURL options
|
2260 |
+
* @param boolean $use_curl Whether to try to force cURL use
|
2261 |
+
* @access public
|
2262 |
+
*/
|
2263 |
+
function __construct($url, $curl_options = null, $use_curl = false)
|
2264 |
+
{
|
2265 |
+
parent::__construct();
|
2266 |
+
$this->debug("ctor url=$url use_curl=$use_curl curl_options:");
|
2267 |
+
$this->appendDebug($this->varDump($curl_options));
|
2268 |
+
$this->setURL($url);
|
2269 |
+
if (is_array($curl_options)) {
|
2270 |
+
$this->ch_options = $curl_options;
|
2271 |
+
}
|
2272 |
+
$this->use_curl = $use_curl;
|
2273 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
2274 |
+
$this->setHeader('User-Agent', $this->title . '/' . $this->version . ' (' . $rev[1] . ')');
|
2275 |
+
}
|
2276 |
+
|
2277 |
+
/**
|
2278 |
+
* sets a cURL option
|
2279 |
+
*
|
2280 |
+
* @param mixed $option The cURL option (always integer?)
|
2281 |
+
* @param mixed $value The cURL option value
|
2282 |
+
* @access private
|
2283 |
+
*/
|
2284 |
+
function setCurlOption($option, $value)
|
2285 |
+
{
|
2286 |
+
$this->debug("setCurlOption option=$option, value=");
|
2287 |
+
$this->appendDebug($this->varDump($value));
|
2288 |
+
curl_setopt($this->ch, $option, $value);
|
2289 |
+
}
|
2290 |
+
|
2291 |
+
/**
|
2292 |
+
* sets an HTTP header
|
2293 |
+
*
|
2294 |
+
* @param string $name The name of the header
|
2295 |
+
* @param string $value The value of the header
|
2296 |
+
* @access private
|
2297 |
+
*/
|
2298 |
+
function setHeader($name, $value)
|
2299 |
+
{
|
2300 |
+
$this->outgoing_headers[$name] = $value;
|
2301 |
+
$this->debug("set header $name: $value");
|
2302 |
+
}
|
2303 |
+
|
2304 |
+
/**
|
2305 |
+
* unsets an HTTP header
|
2306 |
+
*
|
2307 |
+
* @param string $name The name of the header
|
2308 |
+
* @access private
|
2309 |
+
*/
|
2310 |
+
function unsetHeader($name)
|
2311 |
+
{
|
2312 |
+
if (isset($this->outgoing_headers[$name])) {
|
2313 |
+
$this->debug("unset header $name");
|
2314 |
+
unset($this->outgoing_headers[$name]);
|
2315 |
+
}
|
2316 |
+
}
|
2317 |
+
|
2318 |
+
/**
|
2319 |
+
* sets the URL to which to connect
|
2320 |
+
*
|
2321 |
+
* @param string $url The URL to which to connect
|
2322 |
+
* @access private
|
2323 |
+
*/
|
2324 |
+
function setURL($url)
|
2325 |
+
{
|
2326 |
+
$this->url = $url;
|
2327 |
+
|
2328 |
+
$u = parse_url($url);
|
2329 |
+
foreach ($u as $k => $v) {
|
2330 |
+
$this->debug("parsed URL $k = $v");
|
2331 |
+
$this->$k = $v;
|
2332 |
+
}
|
2333 |
+
|
2334 |
+
// add any GET params to path
|
2335 |
+
if (isset($u['query']) && $u['query'] != '') {
|
2336 |
+
$this->path .= '?' . $u['query'];
|
2337 |
+
}
|
2338 |
+
|
2339 |
+
// set default port
|
2340 |
+
if (!isset($u['port'])) {
|
2341 |
+
if ($u['scheme'] == 'https') {
|
2342 |
+
$this->port = 443;
|
2343 |
+
} else {
|
2344 |
+
$this->port = 80;
|
2345 |
+
}
|
2346 |
+
}
|
2347 |
+
|
2348 |
+
$this->uri = $this->path;
|
2349 |
+
$this->digest_uri = $this->uri;
|
2350 |
+
|
2351 |
+
// build headers
|
2352 |
+
if (!isset($u['port'])) {
|
2353 |
+
$this->setHeader('Host', $this->host);
|
2354 |
+
} else {
|
2355 |
+
$this->setHeader('Host', $this->host . ':' . $this->port);
|
2356 |
+
}
|
2357 |
+
|
2358 |
+
if (isset($u['user']) && $u['user'] != '') {
|
2359 |
+
$this->setCredentials(urldecode($u['user']), isset($u['pass']) ? urldecode($u['pass']) : '');
|
2360 |
+
}
|
2361 |
+
}
|
2362 |
+
|
2363 |
+
/**
|
2364 |
+
* gets the I/O method to use
|
2365 |
+
*
|
2366 |
+
* @return string I/O method to use (socket|curl|unknown)
|
2367 |
+
* @access private
|
2368 |
+
*/
|
2369 |
+
function io_method()
|
2370 |
+
{
|
2371 |
+
if ($this->use_curl || ($this->scheme == 'https') || ($this->scheme == 'http' && $this->authtype == 'ntlm') || ($this->scheme == 'http' && is_array($this->proxy) && $this->proxy['authtype'] == 'ntlm')) {
|
2372 |
+
return 'curl';
|
2373 |
+
}
|
2374 |
+
if (($this->scheme == 'http' || $this->scheme == 'ssl') && $this->authtype != 'ntlm' && (!is_array($this->proxy) || $this->proxy['authtype'] != 'ntlm')) {
|
2375 |
+
return 'socket';
|
2376 |
+
}
|
2377 |
+
return 'unknown';
|
2378 |
+
}
|
2379 |
+
|
2380 |
+
/**
|
2381 |
+
* establish an HTTP connection
|
2382 |
+
*
|
2383 |
+
* @param integer $timeout set connection timeout in seconds
|
2384 |
+
* @param integer $response_timeout set response timeout in seconds
|
2385 |
+
* @return boolean true if connected, false if not
|
2386 |
+
* @access private
|
2387 |
+
*/
|
2388 |
+
function connect($connection_timeout = 0, $response_timeout = 30)
|
2389 |
+
{
|
2390 |
+
// For PHP 4.3 with OpenSSL, change https scheme to ssl, then treat like
|
2391 |
+
// "regular" socket.
|
2392 |
+
// TODO: disabled for now because OpenSSL must be *compiled* in (not just
|
2393 |
+
// loaded), and until PHP5 stream_get_wrappers is not available.
|
2394 |
+
// if ($this->scheme == 'https') {
|
2395 |
+
// if (version_compare(phpversion(), '4.3.0') >= 0) {
|
2396 |
+
// if (extension_loaded('openssl')) {
|
2397 |
+
// $this->scheme = 'ssl';
|
2398 |
+
// $this->debug('Using SSL over OpenSSL');
|
2399 |
+
// }
|
2400 |
+
// }
|
2401 |
+
// }
|
2402 |
+
$this->debug("connect connection_timeout $connection_timeout, response_timeout $response_timeout, scheme $this->scheme, host $this->host, port $this->port");
|
2403 |
+
if ($this->io_method() == 'socket') {
|
2404 |
+
if (!is_array($this->proxy)) {
|
2405 |
+
$host = $this->host;
|
2406 |
+
$port = $this->port;
|
2407 |
+
} else {
|
2408 |
+
$host = $this->proxy['host'];
|
2409 |
+
$port = $this->proxy['port'];
|
2410 |
+
}
|
2411 |
+
|
2412 |
+
// use persistent connection
|
2413 |
+
if ($this->persistentConnection && isset($this->fp) && is_resource($this->fp)) {
|
2414 |
+
if (!feof($this->fp)) {
|
2415 |
+
$this->debug('Re-use persistent connection');
|
2416 |
+
return true;
|
2417 |
+
}
|
2418 |
+
fclose($this->fp);
|
2419 |
+
$this->debug('Closed persistent connection at EOF');
|
2420 |
+
}
|
2421 |
+
|
2422 |
+
// munge host if using OpenSSL
|
2423 |
+
if ($this->scheme == 'ssl') {
|
2424 |
+
$host = 'ssl://' . $host;
|
2425 |
+
}
|
2426 |
+
$this->debug('calling fsockopen with host ' . $host . ' connection_timeout ' . $connection_timeout);
|
2427 |
+
|
2428 |
+
// open socket
|
2429 |
+
if ($connection_timeout > 0) {
|
2430 |
+
$this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str, $connection_timeout);
|
2431 |
+
} else {
|
2432 |
+
$this->fp = @fsockopen($host, $this->port, $this->errno, $this->error_str);
|
2433 |
+
}
|
2434 |
+
|
2435 |
+
// test pointer
|
2436 |
+
if (!$this->fp) {
|
2437 |
+
$msg = 'Couldn\'t open socket connection to server ' . $this->url;
|
2438 |
+
if ($this->errno) {
|
2439 |
+
$msg .= ', Error (' . $this->errno . '): ' . $this->error_str;
|
2440 |
+
} else {
|
2441 |
+
$msg .= ' prior to connect(). This is often a problem looking up the host name.';
|
2442 |
+
}
|
2443 |
+
$this->debug($msg);
|
2444 |
+
$this->setError($msg);
|
2445 |
+
return false;
|
2446 |
+
}
|
2447 |
+
|
2448 |
+
// set response timeout
|
2449 |
+
$this->debug('set response timeout to ' . $response_timeout);
|
2450 |
+
socket_set_timeout($this->fp, $response_timeout);
|
2451 |
+
|
2452 |
+
$this->debug('socket connected');
|
2453 |
+
return true;
|
2454 |
+
} elseif ($this->io_method() == 'curl') {
|
2455 |
+
if (!extension_loaded('curl')) {
|
2456 |
+
// $this->setError('cURL Extension, or OpenSSL extension w/ PHP version >= 4.3 is required for HTTPS');
|
2457 |
+
$this->setError('The PHP cURL Extension is required for HTTPS or NLTM. You will need to re-build or update your PHP to include cURL or change php.ini to load the PHP cURL extension.');
|
2458 |
+
return false;
|
2459 |
+
}
|
2460 |
+
// Avoid warnings when PHP does not have these options
|
2461 |
+
if (defined('CURLOPT_CONNECTIONTIMEOUT')) {
|
2462 |
+
$CURLOPT_CONNECTIONTIMEOUT = CURLOPT_CONNECTIONTIMEOUT;
|
2463 |
+
} else {
|
2464 |
+
$CURLOPT_CONNECTIONTIMEOUT = 78;
|
2465 |
+
}
|
2466 |
+
if (defined('CURLOPT_HTTPAUTH')) {
|
2467 |
+
$CURLOPT_HTTPAUTH = CURLOPT_HTTPAUTH;
|
2468 |
+
} else {
|
2469 |
+
$CURLOPT_HTTPAUTH = 107;
|
2470 |
+
}
|
2471 |
+
if (defined('CURLOPT_PROXYAUTH')) {
|
2472 |
+
$CURLOPT_PROXYAUTH = CURLOPT_PROXYAUTH;
|
2473 |
+
} else {
|
2474 |
+
$CURLOPT_PROXYAUTH = 111;
|
2475 |
+
}
|
2476 |
+
if (defined('CURLAUTH_BASIC')) {
|
2477 |
+
$CURLAUTH_BASIC = CURLAUTH_BASIC;
|
2478 |
+
} else {
|
2479 |
+
$CURLAUTH_BASIC = 1;
|
2480 |
+
}
|
2481 |
+
if (defined('CURLAUTH_DIGEST')) {
|
2482 |
+
$CURLAUTH_DIGEST = CURLAUTH_DIGEST;
|
2483 |
+
} else {
|
2484 |
+
$CURLAUTH_DIGEST = 2;
|
2485 |
+
}
|
2486 |
+
if (defined('CURLAUTH_NTLM')) {
|
2487 |
+
$CURLAUTH_NTLM = CURLAUTH_NTLM;
|
2488 |
+
} else {
|
2489 |
+
$CURLAUTH_NTLM = 8;
|
2490 |
+
}
|
2491 |
+
|
2492 |
+
$this->debug('connect using cURL');
|
2493 |
+
// init CURL
|
2494 |
+
$this->ch = curl_init();
|
2495 |
+
// set url
|
2496 |
+
$hostURL = ($this->port != '') ? "$this->scheme://$this->host:$this->port" : "$this->scheme://$this->host";
|
2497 |
+
// add path
|
2498 |
+
$hostURL .= $this->path;
|
2499 |
+
$this->setCurlOption(CURLOPT_URL, $hostURL);
|
2500 |
+
// follow location headers (re-directs)
|
2501 |
+
if (ini_get('safe_mode') || ini_get('open_basedir')) {
|
2502 |
+
$this->debug('safe_mode or open_basedir set, so do not set CURLOPT_FOLLOWLOCATION');
|
2503 |
+
$this->debug('safe_mode = ');
|
2504 |
+
$this->appendDebug($this->varDump(ini_get('safe_mode')));
|
2505 |
+
$this->debug('open_basedir = ');
|
2506 |
+
$this->appendDebug($this->varDump(ini_get('open_basedir')));
|
2507 |
+
} else {
|
2508 |
+
$this->setCurlOption(CURLOPT_FOLLOWLOCATION, 1);
|
2509 |
+
}
|
2510 |
+
// ask for headers in the response output
|
2511 |
+
$this->setCurlOption(CURLOPT_HEADER, 1);
|
2512 |
+
// ask for the response output as the return value
|
2513 |
+
$this->setCurlOption(CURLOPT_RETURNTRANSFER, 1);
|
2514 |
+
// encode
|
2515 |
+
// We manage this ourselves through headers and encoding
|
2516 |
+
// if(function_exists('gzuncompress')){
|
2517 |
+
// $this->setCurlOption(CURLOPT_ENCODING, 'deflate');
|
2518 |
+
// }
|
2519 |
+
// persistent connection
|
2520 |
+
if ($this->persistentConnection) {
|
2521 |
+
// I believe the following comment is now bogus, having applied to
|
2522 |
+
// the code when it used CURLOPT_CUSTOMREQUEST to send the request.
|
2523 |
+
// The way we send data, we cannot use persistent connections, since
|
2524 |
+
// there will be some "junk" at the end of our request.
|
2525 |
+
//$this->setCurlOption(CURL_HTTP_VERSION_1_1, true);
|
2526 |
+
$this->persistentConnection = false;
|
2527 |
+
$this->setHeader('Connection', 'close');
|
2528 |
+
}
|
2529 |
+
// set timeouts
|
2530 |
+
if ($connection_timeout != 0) {
|
2531 |
+
$this->setCurlOption($CURLOPT_CONNECTIONTIMEOUT, $connection_timeout);
|
2532 |
+
}
|
2533 |
+
if ($response_timeout != 0) {
|
2534 |
+
$this->setCurlOption(CURLOPT_TIMEOUT, $response_timeout);
|
2535 |
+
}
|
2536 |
+
|
2537 |
+
if ($this->scheme == 'https') {
|
2538 |
+
$this->debug('set cURL SSL verify options');
|
2539 |
+
// recent versions of cURL turn on peer/host checking by default,
|
2540 |
+
// while PHP binaries are not compiled with a default location for the
|
2541 |
+
// CA cert bundle, so disable peer/host checking.
|
2542 |
+
//$this->setCurlOption(CURLOPT_CAINFO, 'f:\php-4.3.2-win32\extensions\curl-ca-bundle.crt');
|
2543 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 0);
|
2544 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 0);
|
2545 |
+
|
2546 |
+
// support client certificates (thanks Tobias Boes, Doug Anarino, Eryan Ariobowo)
|
2547 |
+
if ($this->authtype == 'certificate') {
|
2548 |
+
$this->debug('set cURL certificate options');
|
2549 |
+
if (isset($this->certRequest['cainfofile'])) {
|
2550 |
+
$this->setCurlOption(CURLOPT_CAINFO, $this->certRequest['cainfofile']);
|
2551 |
+
}
|
2552 |
+
if (isset($this->certRequest['verifypeer'])) {
|
2553 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, $this->certRequest['verifypeer']);
|
2554 |
+
} else {
|
2555 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYPEER, 1);
|
2556 |
+
}
|
2557 |
+
if (isset($this->certRequest['verifyhost'])) {
|
2558 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, $this->certRequest['verifyhost']);
|
2559 |
+
} else {
|
2560 |
+
$this->setCurlOption(CURLOPT_SSL_VERIFYHOST, 1);
|
2561 |
+
}
|
2562 |
+
if (isset($this->certRequest['sslcertfile'])) {
|
2563 |
+
$this->setCurlOption(CURLOPT_SSLCERT, $this->certRequest['sslcertfile']);
|
2564 |
+
}
|
2565 |
+
if (isset($this->certRequest['sslkeyfile'])) {
|
2566 |
+
$this->setCurlOption(CURLOPT_SSLKEY, $this->certRequest['sslkeyfile']);
|
2567 |
+
}
|
2568 |
+
if (isset($this->certRequest['passphrase'])) {
|
2569 |
+
$this->setCurlOption(CURLOPT_SSLKEYPASSWD, $this->certRequest['passphrase']);
|
2570 |
+
}
|
2571 |
+
if (isset($this->certRequest['certpassword'])) {
|
2572 |
+
$this->setCurlOption(CURLOPT_SSLCERTPASSWD, $this->certRequest['certpassword']);
|
2573 |
+
}
|
2574 |
+
}
|
2575 |
+
}
|
2576 |
+
if ($this->authtype && ($this->authtype != 'certificate')) {
|
2577 |
+
if ($this->username) {
|
2578 |
+
$this->debug('set cURL username/password');
|
2579 |
+
$this->setCurlOption(CURLOPT_USERPWD, "$this->username:$this->password");
|
2580 |
+
}
|
2581 |
+
if ($this->authtype == 'basic') {
|
2582 |
+
$this->debug('set cURL for Basic authentication');
|
2583 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_BASIC);
|
2584 |
+
}
|
2585 |
+
if ($this->authtype == 'digest') {
|
2586 |
+
$this->debug('set cURL for digest authentication');
|
2587 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_DIGEST);
|
2588 |
+
}
|
2589 |
+
if ($this->authtype == 'ntlm') {
|
2590 |
+
$this->debug('set cURL for NTLM authentication');
|
2591 |
+
$this->setCurlOption($CURLOPT_HTTPAUTH, $CURLAUTH_NTLM);
|
2592 |
+
}
|
2593 |
+
}
|
2594 |
+
if (is_array($this->proxy)) {
|
2595 |
+
$this->debug('set cURL proxy options');
|
2596 |
+
if ($this->proxy['port'] != '') {
|
2597 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host'] . ':' . $this->proxy['port']);
|
2598 |
+
} else {
|
2599 |
+
$this->setCurlOption(CURLOPT_PROXY, $this->proxy['host']);
|
2600 |
+
}
|
2601 |
+
if ($this->proxy['username'] || $this->proxy['password']) {
|
2602 |
+
$this->debug('set cURL proxy authentication options');
|
2603 |
+
$this->setCurlOption(CURLOPT_PROXYUSERPWD, $this->proxy['username'] . ':' . $this->proxy['password']);
|
2604 |
+
if ($this->proxy['authtype'] == 'basic') {
|
2605 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_BASIC);
|
2606 |
+
}
|
2607 |
+
if ($this->proxy['authtype'] == 'ntlm') {
|
2608 |
+
$this->setCurlOption($CURLOPT_PROXYAUTH, $CURLAUTH_NTLM);
|
2609 |
+
}
|
2610 |
+
}
|
2611 |
+
}
|
2612 |
+
$this->debug('cURL connection set up');
|
2613 |
+
return true;
|
2614 |
+
} else {
|
2615 |
+
$this->setError('Unknown scheme ' . $this->scheme);
|
2616 |
+
$this->debug('Unknown scheme ' . $this->scheme);
|
2617 |
+
return false;
|
2618 |
+
}
|
2619 |
+
}
|
2620 |
+
|
2621 |
+
/**
|
2622 |
+
* sends the SOAP request and gets the SOAP response via HTTP[S]
|
2623 |
+
*
|
2624 |
+
* @param string $data message data
|
2625 |
+
* @param integer $timeout set connection timeout in seconds
|
2626 |
+
* @param integer $response_timeout set response timeout in seconds
|
2627 |
+
* @param array $cookies cookies to send
|
2628 |
+
* @return string data
|
2629 |
+
* @access public
|
2630 |
+
*/
|
2631 |
+
function send($data, $timeout = 0, $response_timeout = 30, $cookies = null)
|
2632 |
+
{
|
2633 |
+
|
2634 |
+
$this->debug('entered send() with data of length: ' . strlen($data));
|
2635 |
+
|
2636 |
+
$this->tryagain = true;
|
2637 |
+
$tries = 0;
|
2638 |
+
while ($this->tryagain) {
|
2639 |
+
$this->tryagain = false;
|
2640 |
+
if ($tries++ < 2) {
|
2641 |
+
// make connnection
|
2642 |
+
if (!$this->connect($timeout, $response_timeout)) {
|
2643 |
+
return false;
|
2644 |
+
}
|
2645 |
+
|
2646 |
+
// send request
|
2647 |
+
if (!$this->sendRequest($data, $cookies)) {
|
2648 |
+
return false;
|
2649 |
+
}
|
2650 |
+
|
2651 |
+
// get response
|
2652 |
+
$respdata = $this->getResponse();
|
2653 |
+
} else {
|
2654 |
+
$this->setError("Too many tries to get an OK response ($this->response_status_line)");
|
2655 |
+
}
|
2656 |
+
}
|
2657 |
+
$this->debug('end of send()');
|
2658 |
+
return $respdata;
|
2659 |
+
}
|
2660 |
+
|
2661 |
+
|
2662 |
+
/**
|
2663 |
+
* sends the SOAP request and gets the SOAP response via HTTPS using CURL
|
2664 |
+
*
|
2665 |
+
* @param string $data message data
|
2666 |
+
* @param integer $timeout set connection timeout in seconds
|
2667 |
+
* @param integer $response_timeout set response timeout in seconds
|
2668 |
+
* @param array $cookies cookies to send
|
2669 |
+
* @return string data
|
2670 |
+
* @access public
|
2671 |
+
* @deprecated
|
2672 |
+
*/
|
2673 |
+
function sendHTTPS($data, $timeout = 0, $response_timeout = 30, $cookies)
|
2674 |
+
{
|
2675 |
+
return $this->send($data, $timeout, $response_timeout, $cookies);
|
2676 |
+
}
|
2677 |
+
|
2678 |
+
/**
|
2679 |
+
* if authenticating, set user credentials here
|
2680 |
+
*
|
2681 |
+
* @param string $username
|
2682 |
+
* @param string $password
|
2683 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
2684 |
+
* @param array $digestRequest (keys must be nonce, nc, realm, qop)
|
2685 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
2686 |
+
* @access public
|
2687 |
+
*/
|
2688 |
+
function setCredentials($username, $password, $authtype = 'basic', $digestRequest = array(), $certRequest = array())
|
2689 |
+
{
|
2690 |
+
$this->debug("setCredentials username=$username authtype=$authtype digestRequest=");
|
2691 |
+
$this->appendDebug($this->varDump($digestRequest));
|
2692 |
+
$this->debug("certRequest=");
|
2693 |
+
$this->appendDebug($this->varDump($certRequest));
|
2694 |
+
// cf. RFC 2617
|
2695 |
+
if ($authtype == 'basic') {
|
2696 |
+
$this->setHeader('Authorization', 'Basic ' . base64_encode(str_replace(':', '', $username) . ':' . $password));
|
2697 |
+
} elseif ($authtype == 'digest') {
|
2698 |
+
if (isset($digestRequest['nonce'])) {
|
2699 |
+
$digestRequest['nc'] = isset($digestRequest['nc']) ? $digestRequest['nc']++ : 1;
|
2700 |
+
|
2701 |
+
// calculate the Digest hashes (calculate code based on digest implementation found at: http://www.rassoc.com/gregr/weblog/stories/2002/07/09/webServicesSecurityHttpDigestAuthenticationWithoutActiveDirectory.html)
|
2702 |
+
|
2703 |
+
// A1 = unq(username-value) ":" unq(realm-value) ":" passwd
|
2704 |
+
$A1 = $username . ':' . (isset($digestRequest['realm']) ? $digestRequest['realm'] : '') . ':' . $password;
|
2705 |
+
|
2706 |
+
// H(A1) = MD5(A1)
|
2707 |
+
$HA1 = md5($A1);
|
2708 |
+
|
2709 |
+
// A2 = Method ":" digest-uri-value
|
2710 |
+
$A2 = $this->request_method . ':' . $this->digest_uri;
|
2711 |
+
|
2712 |
+
// H(A2)
|
2713 |
+
$HA2 = md5($A2);
|
2714 |
+
|
2715 |
+
// KD(secret, data) = H(concat(secret, ":", data))
|
2716 |
+
// if qop == auth:
|
2717 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value)
|
2718 |
+
// ":" nc-value
|
2719 |
+
// ":" unq(cnonce-value)
|
2720 |
+
// ":" unq(qop-value)
|
2721 |
+
// ":" H(A2)
|
2722 |
+
// ) <">
|
2723 |
+
// if qop is missing,
|
2724 |
+
// request-digest = <"> < KD ( H(A1), unq(nonce-value) ":" H(A2) ) > <">
|
2725 |
+
|
2726 |
+
$unhashedDigest = '';
|
2727 |
+
$nonce = isset($digestRequest['nonce']) ? $digestRequest['nonce'] : '';
|
2728 |
+
$cnonce = $nonce;
|
2729 |
+
if ($digestRequest['qop'] != '') {
|
2730 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . sprintf("%08d", $digestRequest['nc']) . ':' . $cnonce . ':' . $digestRequest['qop'] . ':' . $HA2;
|
2731 |
+
} else {
|
2732 |
+
$unhashedDigest = $HA1 . ':' . $nonce . ':' . $HA2;
|
2733 |
+
}
|
2734 |
+
|
2735 |
+
$hashedDigest = md5($unhashedDigest);
|
2736 |
+
|
2737 |
+
$opaque = '';
|
2738 |
+
if (isset($digestRequest['opaque'])) {
|
2739 |
+
$opaque = ', opaque="' . $digestRequest['opaque'] . '"';
|
2740 |
+
}
|
2741 |
+
|
2742 |
+
$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 . '"');
|
2743 |
+
}
|
2744 |
+
} elseif ($authtype == 'certificate') {
|
2745 |
+
$this->certRequest = $certRequest;
|
2746 |
+
$this->debug('Authorization header not set for certificate');
|
2747 |
+
} elseif ($authtype == 'ntlm') {
|
2748 |
+
// do nothing
|
2749 |
+
$this->debug('Authorization header not set for ntlm');
|
2750 |
+
}
|
2751 |
+
$this->username = $username;
|
2752 |
+
$this->password = $password;
|
2753 |
+
$this->authtype = $authtype;
|
2754 |
+
$this->digestRequest = $digestRequest;
|
2755 |
+
}
|
2756 |
+
|
2757 |
+
/**
|
2758 |
+
* set the soapaction value
|
2759 |
+
*
|
2760 |
+
* @param string $soapaction
|
2761 |
+
* @access public
|
2762 |
+
*/
|
2763 |
+
function setSOAPAction($soapaction)
|
2764 |
+
{
|
2765 |
+
$this->setHeader('SOAPAction', '"' . $soapaction . '"');
|
2766 |
+
}
|
2767 |
+
|
2768 |
+
/**
|
2769 |
+
* use http encoding
|
2770 |
+
*
|
2771 |
+
* @param string $enc encoding style. supported values: gzip, deflate, or both
|
2772 |
+
* @access public
|
2773 |
+
*/
|
2774 |
+
function setEncoding($enc = 'gzip, deflate')
|
2775 |
+
{
|
2776 |
+
if (function_exists('gzdeflate')) {
|
2777 |
+
$this->protocol_version = '1.1';
|
2778 |
+
$this->setHeader('Accept-Encoding', $enc);
|
2779 |
+
if (!isset($this->outgoing_headers['Connection'])) {
|
2780 |
+
$this->setHeader('Connection', 'close');
|
2781 |
+
$this->persistentConnection = false;
|
2782 |
+
}
|
2783 |
+
// deprecated as of PHP 5.3.0
|
2784 |
+
//set_magic_quotes_runtime(0);
|
2785 |
+
$this->encoding = $enc;
|
2786 |
+
}
|
2787 |
+
}
|
2788 |
+
|
2789 |
+
/**
|
2790 |
+
* set proxy info here
|
2791 |
+
*
|
2792 |
+
* @param string $proxyhost use an empty string to remove proxy
|
2793 |
+
* @param string $proxyport
|
2794 |
+
* @param string $proxyusername
|
2795 |
+
* @param string $proxypassword
|
2796 |
+
* @param string $proxyauthtype (basic|ntlm)
|
2797 |
+
* @access public
|
2798 |
+
*/
|
2799 |
+
function setProxy($proxyhost, $proxyport, $proxyusername = '', $proxypassword = '', $proxyauthtype = 'basic')
|
2800 |
+
{
|
2801 |
+
if ($proxyhost) {
|
2802 |
+
$this->proxy = array(
|
2803 |
+
'host' => $proxyhost,
|
2804 |
+
'port' => $proxyport,
|
2805 |
+
'username' => $proxyusername,
|
2806 |
+
'password' => $proxypassword,
|
2807 |
+
'authtype' => $proxyauthtype
|
2808 |
+
);
|
2809 |
+
if ($proxyusername != '' && $proxypassword != '' && $proxyauthtype = 'basic') {
|
2810 |
+
$this->setHeader('Proxy-Authorization', ' Basic ' . base64_encode($proxyusername . ':' . $proxypassword));
|
2811 |
+
}
|
2812 |
+
} else {
|
2813 |
+
$this->debug('remove proxy');
|
2814 |
+
$proxy = null;
|
2815 |
+
unsetHeader('Proxy-Authorization');
|
2816 |
+
}
|
2817 |
+
}
|
2818 |
+
|
2819 |
+
|
2820 |
+
/**
|
2821 |
+
* Test if the given string starts with a header that is to be skipped.
|
2822 |
+
* Skippable headers result from chunked transfer and proxy requests.
|
2823 |
+
*
|
2824 |
+
* @param string $data The string to check.
|
2825 |
+
* @returns boolean Whether a skippable header was found.
|
2826 |
+
* @access private
|
2827 |
+
*/
|
2828 |
+
function isSkippableCurlHeader(&$data)
|
2829 |
+
{
|
2830 |
+
$skipHeaders = array('HTTP/1.1 100',
|
2831 |
+
'HTTP/1.0 301',
|
2832 |
+
'HTTP/1.1 301',
|
2833 |
+
'HTTP/1.0 302',
|
2834 |
+
'HTTP/1.1 302',
|
2835 |
+
'HTTP/1.0 401',
|
2836 |
+
'HTTP/1.1 401',
|
2837 |
+
'HTTP/1.0 200 Connection established');
|
2838 |
+
foreach ($skipHeaders as $hd) {
|
2839 |
+
$prefix = substr($data, 0, strlen($hd));
|
2840 |
+
if ($prefix == $hd) {
|
2841 |
+
return true;
|
2842 |
+
}
|
2843 |
+
}
|
2844 |
+
|
2845 |
+
return false;
|
2846 |
+
}
|
2847 |
+
|
2848 |
+
/**
|
2849 |
+
* decode a string that is encoded w/ "chunked' transfer encoding
|
2850 |
+
* as defined in RFC2068 19.4.6
|
2851 |
+
*
|
2852 |
+
* @param string $buffer
|
2853 |
+
* @param string $lb
|
2854 |
+
* @returns string
|
2855 |
+
* @access public
|
2856 |
+
* @deprecated
|
2857 |
+
*/
|
2858 |
+
function decodeChunked($buffer, $lb)
|
2859 |
+
{
|
2860 |
+
// length := 0
|
2861 |
+
$length = 0;
|
2862 |
+
$new = '';
|
2863 |
+
|
2864 |
+
// read chunk-size, chunk-extension (if any) and CRLF
|
2865 |
+
// get the position of the linebreak
|
2866 |
+
$chunkend = strpos($buffer, $lb);
|
2867 |
+
if ($chunkend == false) {
|
2868 |
+
$this->debug('no linebreak found in decodeChunked');
|
2869 |
+
return $new;
|
2870 |
+
}
|
2871 |
+
$temp = substr($buffer, 0, $chunkend);
|
2872 |
+
$chunk_size = hexdec(trim($temp));
|
2873 |
+
$chunkstart = $chunkend + strlen($lb);
|
2874 |
+
// while (chunk-size > 0) {
|
2875 |
+
while ($chunk_size > 0) {
|
2876 |
+
$this->debug("chunkstart: $chunkstart chunk_size: $chunk_size");
|
2877 |
+
$chunkend = strpos($buffer, $lb, $chunkstart + $chunk_size);
|
2878 |
+
|
2879 |
+
// Just in case we got a broken connection
|
2880 |
+
if ($chunkend == false) {
|
2881 |
+
$chunk = substr($buffer, $chunkstart);
|
2882 |
+
// append chunk-data to entity-body
|
2883 |
+
$new .= $chunk;
|
2884 |
+
$length += strlen($chunk);
|
2885 |
+
break;
|
2886 |
+
}
|
2887 |
+
|
2888 |
+
// read chunk-data and CRLF
|
2889 |
+
$chunk = substr($buffer, $chunkstart, $chunkend - $chunkstart);
|
2890 |
+
// append chunk-data to entity-body
|
2891 |
+
$new .= $chunk;
|
2892 |
+
// length := length + chunk-size
|
2893 |
+
$length += strlen($chunk);
|
2894 |
+
// read chunk-size and CRLF
|
2895 |
+
$chunkstart = $chunkend + strlen($lb);
|
2896 |
+
|
2897 |
+
$chunkend = strpos($buffer, $lb, $chunkstart) + strlen($lb);
|
2898 |
+
if ($chunkend == false) {
|
2899 |
+
break; //Just in case we got a broken connection
|
2900 |
+
}
|
2901 |
+
$temp = substr($buffer, $chunkstart, $chunkend - $chunkstart);
|
2902 |
+
$chunk_size = hexdec(trim($temp));
|
2903 |
+
$chunkstart = $chunkend;
|
2904 |
+
}
|
2905 |
+
return $new;
|
2906 |
+
}
|
2907 |
+
|
2908 |
+
/**
|
2909 |
+
* Writes the payload, including HTTP headers, to $this->outgoing_payload.
|
2910 |
+
*
|
2911 |
+
* @param string $data HTTP body
|
2912 |
+
* @param string $cookie_str data for HTTP Cookie header
|
2913 |
+
* @return void
|
2914 |
+
* @access private
|
2915 |
+
*/
|
2916 |
+
function buildPayload($data, $cookie_str = '')
|
2917 |
+
{
|
2918 |
+
// Note: for cURL connections, $this->outgoing_payload is ignored,
|
2919 |
+
// as is the Content-Length header, but these are still created as
|
2920 |
+
// debugging guides.
|
2921 |
+
|
2922 |
+
// add content-length header
|
2923 |
+
if ($this->request_method != 'GET') {
|
2924 |
+
$this->setHeader('Content-Length', strlen($data));
|
2925 |
+
}
|
2926 |
+
|
2927 |
+
// start building outgoing payload:
|
2928 |
+
if ($this->proxy) {
|
2929 |
+
$uri = $this->url;
|
2930 |
+
} else {
|
2931 |
+
$uri = $this->uri;
|
2932 |
+
}
|
2933 |
+
$req = "$this->request_method $uri HTTP/$this->protocol_version";
|
2934 |
+
$this->debug("HTTP request: $req");
|
2935 |
+
$this->outgoing_payload = "$req\r\n";
|
2936 |
+
|
2937 |
+
// loop thru headers, serializing
|
2938 |
+
foreach ($this->outgoing_headers as $k => $v) {
|
2939 |
+
$hdr = $k . ': ' . $v;
|
2940 |
+
$this->debug("HTTP header: $hdr");
|
2941 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
2942 |
+
}
|
2943 |
+
|
2944 |
+
// add any cookies
|
2945 |
+
if ($cookie_str != '') {
|
2946 |
+
$hdr = 'Cookie: ' . $cookie_str;
|
2947 |
+
$this->debug("HTTP header: $hdr");
|
2948 |
+
$this->outgoing_payload .= "$hdr\r\n";
|
2949 |
+
}
|
2950 |
+
|
2951 |
+
// header/body separator
|
2952 |
+
$this->outgoing_payload .= "\r\n";
|
2953 |
+
|
2954 |
+
// add data
|
2955 |
+
$this->outgoing_payload .= $data;
|
2956 |
+
}
|
2957 |
+
|
2958 |
+
/**
|
2959 |
+
* sends the SOAP request via HTTP[S]
|
2960 |
+
*
|
2961 |
+
* @param string $data message data
|
2962 |
+
* @param array $cookies cookies to send
|
2963 |
+
* @return boolean true if OK, false if problem
|
2964 |
+
* @access private
|
2965 |
+
*/
|
2966 |
+
function sendRequest($data, $cookies = null)
|
2967 |
+
{
|
2968 |
+
// build cookie string
|
2969 |
+
$cookie_str = $this->getCookiesForRequest($cookies, (($this->scheme == 'ssl') || ($this->scheme == 'https')));
|
2970 |
+
|
2971 |
+
// build payload
|
2972 |
+
$this->buildPayload($data, $cookie_str);
|
2973 |
+
|
2974 |
+
if ($this->io_method() == 'socket') {
|
2975 |
+
// send payload
|
2976 |
+
if (!fputs($this->fp, $this->outgoing_payload, strlen($this->outgoing_payload))) {
|
2977 |
+
$this->setError('couldn\'t write message data to socket');
|
2978 |
+
$this->debug('couldn\'t write message data to socket');
|
2979 |
+
return false;
|
2980 |
+
}
|
2981 |
+
$this->debug('wrote data to socket, length = ' . strlen($this->outgoing_payload));
|
2982 |
+
return true;
|
2983 |
+
} elseif ($this->io_method() == 'curl') {
|
2984 |
+
// set payload
|
2985 |
+
// cURL does say this should only be the verb, and in fact it
|
2986 |
+
// turns out that the URI and HTTP version are appended to this, which
|
2987 |
+
// some servers refuse to work with (so we no longer use this method!)
|
2988 |
+
//$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $this->outgoing_payload);
|
2989 |
+
$curl_headers = array();
|
2990 |
+
foreach ($this->outgoing_headers as $k => $v) {
|
2991 |
+
if ($k == 'Connection' || $k == 'Content-Length' || $k == 'Host' || $k == 'Authorization' || $k == 'Proxy-Authorization') {
|
2992 |
+
$this->debug("Skip cURL header $k: $v");
|
2993 |
+
} else {
|
2994 |
+
$curl_headers[] = "$k: $v";
|
2995 |
+
}
|
2996 |
+
}
|
2997 |
+
if ($cookie_str != '') {
|
2998 |
+
$curl_headers[] = 'Cookie: ' . $cookie_str;
|
2999 |
+
}
|
3000 |
+
$this->setCurlOption(CURLOPT_HTTPHEADER, $curl_headers);
|
3001 |
+
$this->debug('set cURL HTTP headers');
|
3002 |
+
if ($this->request_method == "POST") {
|
3003 |
+
$this->setCurlOption(CURLOPT_POST, 1);
|
3004 |
+
$this->setCurlOption(CURLOPT_POSTFIELDS, $data);
|
3005 |
+
$this->debug('set cURL POST data');
|
3006 |
+
} else {
|
3007 |
+
}
|
3008 |
+
// insert custom user-set cURL options
|
3009 |
+
foreach ($this->ch_options as $key => $val) {
|
3010 |
+
$this->setCurlOption($key, $val);
|
3011 |
+
}
|
3012 |
+
|
3013 |
+
$this->debug('set cURL payload');
|
3014 |
+
return true;
|
3015 |
+
}
|
3016 |
+
}
|
3017 |
+
|
3018 |
+
/**
|
3019 |
+
* gets the SOAP response via HTTP[S]
|
3020 |
+
*
|
3021 |
+
* @return string the response (also sets member variables like incoming_payload)
|
3022 |
+
* @access private
|
3023 |
+
*/
|
3024 |
+
function getResponse()
|
3025 |
+
{
|
3026 |
+
$this->incoming_payload = '';
|
3027 |
+
|
3028 |
+
if ($this->io_method() == 'socket') {
|
3029 |
+
// loop until headers have been retrieved
|
3030 |
+
$data = '';
|
3031 |
+
while (!isset($lb)) {
|
3032 |
+
|
3033 |
+
// We might EOF during header read.
|
3034 |
+
if (feof($this->fp)) {
|
3035 |
+
$this->incoming_payload = $data;
|
3036 |
+
$this->debug('found no headers before EOF after length ' . strlen($data));
|
3037 |
+
$this->debug("received before EOF:\n" . $data);
|
3038 |
+
$this->setError('server failed to send headers');
|
3039 |
+
return false;
|
3040 |
+
}
|
3041 |
+
|
3042 |
+
$tmp = fgets($this->fp, 256);
|
3043 |
+
$tmplen = strlen($tmp);
|
3044 |
+
$this->debug("read line of $tmplen bytes: " . trim($tmp));
|
3045 |
+
|
3046 |
+
if ($tmplen == 0) {
|
3047 |
+
$this->incoming_payload = $data;
|
3048 |
+
$this->debug('socket read of headers timed out after length ' . strlen($data));
|
3049 |
+
$this->debug("read before timeout: " . $data);
|
3050 |
+
$this->setError('socket read of headers timed out');
|
3051 |
+
return false;
|
3052 |
+
}
|
3053 |
+
|
3054 |
+
$data .= $tmp;
|
3055 |
+
$pos = strpos($data, "\r\n\r\n");
|
3056 |
+
if ($pos > 1) {
|
3057 |
+
$lb = "\r\n";
|
3058 |
+
} else {
|
3059 |
+
$pos = strpos($data, "\n\n");
|
3060 |
+
if ($pos > 1) {
|
3061 |
+
$lb = "\n";
|
3062 |
+
}
|
3063 |
+
}
|
3064 |
+
// remove 100 headers
|
3065 |
+
if (isset($lb) && preg_match('/^HTTP\/1.1 100/', $data)) {
|
3066 |
+
unset($lb);
|
3067 |
+
$data = '';
|
3068 |
+
}//
|
3069 |
+
}
|
3070 |
+
// store header data
|
3071 |
+
$this->incoming_payload .= $data;
|
3072 |
+
$this->debug('found end of headers after length ' . strlen($data));
|
3073 |
+
// process headers
|
3074 |
+
$header_data = trim(substr($data, 0, $pos));
|
3075 |
+
$header_array = explode($lb, $header_data);
|
3076 |
+
$this->incoming_headers = array();
|
3077 |
+
$this->incoming_cookies = array();
|
3078 |
+
foreach ($header_array as $header_line) {
|
3079 |
+
$arr = explode(':', $header_line, 2);
|
3080 |
+
if (count($arr) > 1) {
|
3081 |
+
$header_name = strtolower(trim($arr[0]));
|
3082 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
3083 |
+
if ($header_name == 'set-cookie') {
|
3084 |
+
// TODO: allow multiple cookies from parseCookie
|
3085 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
3086 |
+
if ($cookie) {
|
3087 |
+
$this->incoming_cookies[] = $cookie;
|
3088 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
3089 |
+
} else {
|
3090 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
3091 |
+
}
|
3092 |
+
}
|
3093 |
+
} elseif (isset($header_name)) {
|
3094 |
+
// append continuation line to previous header
|
3095 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
3096 |
+
}
|
3097 |
+
}
|
3098 |
+
|
3099 |
+
// loop until msg has been received
|
3100 |
+
if (isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked') {
|
3101 |
+
$content_length = 2147483647; // ignore any content-length header
|
3102 |
+
$chunked = true;
|
3103 |
+
$this->debug("want to read chunked content");
|
3104 |
+
} elseif (isset($this->incoming_headers['content-length'])) {
|
3105 |
+
$content_length = $this->incoming_headers['content-length'];
|
3106 |
+
$chunked = false;
|
3107 |
+
$this->debug("want to read content of length $content_length");
|
3108 |
+
} else {
|
3109 |
+
$content_length = 2147483647;
|
3110 |
+
$chunked = false;
|
3111 |
+
$this->debug("want to read content to EOF");
|
3112 |
+
}
|
3113 |
+
$data = '';
|
3114 |
+
do {
|
3115 |
+
if ($chunked) {
|
3116 |
+
$tmp = fgets($this->fp, 256);
|
3117 |
+
$tmplen = strlen($tmp);
|
3118 |
+
$this->debug("read chunk line of $tmplen bytes");
|
3119 |
+
if ($tmplen == 0) {
|
3120 |
+
$this->incoming_payload = $data;
|
3121 |
+
$this->debug('socket read of chunk length timed out after length ' . strlen($data));
|
3122 |
+
$this->debug("read before timeout:\n" . $data);
|
3123 |
+
$this->setError('socket read of chunk length timed out');
|
3124 |
+
return false;
|
3125 |
+
}
|
3126 |
+
$content_length = hexdec(trim($tmp));
|
3127 |
+
$this->debug("chunk length $content_length");
|
3128 |
+
}
|
3129 |
+
$strlen = 0;
|
3130 |
+
while (($strlen < $content_length) && (!feof($this->fp))) {
|
3131 |
+
$readlen = min(8192, $content_length - $strlen);
|
3132 |
+
$tmp = fread($this->fp, $readlen);
|
3133 |
+
$tmplen = strlen($tmp);
|
3134 |
+
$this->debug("read buffer of $tmplen bytes");
|
3135 |
+
if (($tmplen == 0) && (!feof($this->fp))) {
|
3136 |
+
$this->incoming_payload = $data;
|
3137 |
+
$this->debug('socket read of body timed out after length ' . strlen($data));
|
3138 |
+
$this->debug("read before timeout:\n" . $data);
|
3139 |
+
$this->setError('socket read of body timed out');
|
3140 |
+
return false;
|
3141 |
+
}
|
3142 |
+
$strlen += $tmplen;
|
3143 |
+
$data .= $tmp;
|
3144 |
+
}
|
3145 |
+
if ($chunked && ($content_length > 0)) {
|
3146 |
+
$tmp = fgets($this->fp, 256);
|
3147 |
+
$tmplen = strlen($tmp);
|
3148 |
+
$this->debug("read chunk terminator of $tmplen bytes");
|
3149 |
+
if ($tmplen == 0) {
|
3150 |
+
$this->incoming_payload = $data;
|
3151 |
+
$this->debug('socket read of chunk terminator timed out after length ' . strlen($data));
|
3152 |
+
$this->debug("read before timeout:\n" . $data);
|
3153 |
+
$this->setError('socket read of chunk terminator timed out');
|
3154 |
+
return false;
|
3155 |
+
}
|
3156 |
+
}
|
3157 |
+
} while ($chunked && ($content_length > 0) && (!feof($this->fp)));
|
3158 |
+
if (feof($this->fp)) {
|
3159 |
+
$this->debug('read to EOF');
|
3160 |
+
}
|
3161 |
+
$this->debug('read body of length ' . strlen($data));
|
3162 |
+
$this->incoming_payload .= $data;
|
3163 |
+
$this->debug('received a total of ' . strlen($this->incoming_payload) . ' bytes of data from server');
|
3164 |
+
|
3165 |
+
// close filepointer
|
3166 |
+
if (
|
3167 |
+
(isset($this->incoming_headers['connection']) && strtolower($this->incoming_headers['connection']) == 'close') ||
|
3168 |
+
(!$this->persistentConnection) || feof($this->fp)
|
3169 |
+
) {
|
3170 |
+
fclose($this->fp);
|
3171 |
+
$this->fp = false;
|
3172 |
+
$this->debug('closed socket');
|
3173 |
+
}
|
3174 |
+
|
3175 |
+
// connection was closed unexpectedly
|
3176 |
+
if ($this->incoming_payload == '') {
|
3177 |
+
$this->setError('no response from server');
|
3178 |
+
return false;
|
3179 |
+
}
|
3180 |
+
|
3181 |
+
// decode transfer-encoding
|
3182 |
+
// if(isset($this->incoming_headers['transfer-encoding']) && strtolower($this->incoming_headers['transfer-encoding']) == 'chunked'){
|
3183 |
+
// if(!$data = $this->decodeChunked($data, $lb)){
|
3184 |
+
// $this->setError('Decoding of chunked data failed');
|
3185 |
+
// return false;
|
3186 |
+
// }
|
3187 |
+
//print "<pre>\nde-chunked:\n---------------\n$data\n\n---------------\n</pre>";
|
3188 |
+
// set decoded payload
|
3189 |
+
// $this->incoming_payload = $header_data.$lb.$lb.$data;
|
3190 |
+
// }
|
3191 |
+
|
3192 |
+
} elseif ($this->io_method() == 'curl') {
|
3193 |
+
// send and receive
|
3194 |
+
$this->debug('send and receive with cURL');
|
3195 |
+
$this->incoming_payload = curl_exec($this->ch);
|
3196 |
+
$data = $this->incoming_payload;
|
3197 |
+
|
3198 |
+
$cErr = curl_error($this->ch);
|
3199 |
+
if ($cErr != '') {
|
3200 |
+
$err = 'cURL ERROR: ' . curl_errno($this->ch) . ': ' . $cErr . '<br>';
|
3201 |
+
// TODO: there is a PHP bug that can cause this to SEGV for CURLINFO_CONTENT_TYPE
|
3202 |
+
foreach (curl_getinfo($this->ch) as $k => $v) {
|
3203 |
+
$err .= "$k: $v<br>";
|
3204 |
+
}
|
3205 |
+
$this->debug($err);
|
3206 |
+
$this->setError($err);
|
3207 |
+
curl_close($this->ch);
|
3208 |
+
return false;
|
3209 |
+
} else {
|
3210 |
+
//echo '<pre>';
|
3211 |
+
//var_dump(curl_getinfo($this->ch));
|
3212 |
+
//echo '</pre>';
|
3213 |
+
}
|
3214 |
+
// close curl
|
3215 |
+
$this->debug('No cURL error, closing cURL');
|
3216 |
+
curl_close($this->ch);
|
3217 |
+
|
3218 |
+
// try removing skippable headers
|
3219 |
+
$savedata = $data;
|
3220 |
+
while ($this->isSkippableCurlHeader($data)) {
|
3221 |
+
$this->debug("Found HTTP header to skip");
|
3222 |
+
if ($pos = strpos($data, "\r\n\r\n")) {
|
3223 |
+
$data = ltrim(substr($data, $pos));
|
3224 |
+
} elseif ($pos = strpos($data, "\n\n")) {
|
3225 |
+
$data = ltrim(substr($data, $pos));
|
3226 |
+
}
|
3227 |
+
}
|
3228 |
+
|
3229 |
+
if ($data == '') {
|
3230 |
+
// have nothing left; just remove 100 header(s)
|
3231 |
+
$data = $savedata;
|
3232 |
+
while (preg_match('/^HTTP\/1.1 100/', $data)) {
|
3233 |
+
if ($pos = strpos($data, "\r\n\r\n")) {
|
3234 |
+
$data = ltrim(substr($data, $pos));
|
3235 |
+
} elseif ($pos = strpos($data, "\n\n")) {
|
3236 |
+
$data = ltrim(substr($data, $pos));
|
3237 |
+
}
|
3238 |
+
}
|
3239 |
+
}
|
3240 |
+
|
3241 |
+
// separate content from HTTP headers
|
3242 |
+
if ($pos = strpos($data, "\r\n\r\n")) {
|
3243 |
+
$lb = "\r\n";
|
3244 |
+
} elseif ($pos = strpos($data, "\n\n")) {
|
3245 |
+
$lb = "\n";
|
3246 |
+
} else {
|
3247 |
+
$this->debug('no proper separation of headers and document');
|
3248 |
+
$this->setError('no proper separation of headers and document');
|
3249 |
+
return false;
|
3250 |
+
}
|
3251 |
+
$header_data = trim(substr($data, 0, $pos));
|
3252 |
+
$header_array = explode($lb, $header_data);
|
3253 |
+
$data = ltrim(substr($data, $pos));
|
3254 |
+
$this->debug('found proper separation of headers and document');
|
3255 |
+
$this->debug('cleaned data, stringlen: ' . strlen($data));
|
3256 |
+
// clean headers
|
3257 |
+
foreach ($header_array as $header_line) {
|
3258 |
+
$arr = explode(':', $header_line, 2);
|
3259 |
+
if (count($arr) > 1) {
|
3260 |
+
$header_name = strtolower(trim($arr[0]));
|
3261 |
+
$this->incoming_headers[$header_name] = trim($arr[1]);
|
3262 |
+
if ($header_name == 'set-cookie') {
|
3263 |
+
// TODO: allow multiple cookies from parseCookie
|
3264 |
+
$cookie = $this->parseCookie(trim($arr[1]));
|
3265 |
+
if ($cookie) {
|
3266 |
+
$this->incoming_cookies[] = $cookie;
|
3267 |
+
$this->debug('found cookie: ' . $cookie['name'] . ' = ' . $cookie['value']);
|
3268 |
+
} else {
|
3269 |
+
$this->debug('did not find cookie in ' . trim($arr[1]));
|
3270 |
+
}
|
3271 |
+
}
|
3272 |
+
} elseif (isset($header_name)) {
|
3273 |
+
// append continuation line to previous header
|
3274 |
+
$this->incoming_headers[$header_name] .= $lb . ' ' . $header_line;
|
3275 |
+
}
|
3276 |
+
}
|
3277 |
+
}
|
3278 |
+
|
3279 |
+
$this->response_status_line = $header_array[0];
|
3280 |
+
$arr = explode(' ', $this->response_status_line, 3);
|
3281 |
+
$http_version = $arr[0];
|
3282 |
+
$http_status = intval($arr[1]);
|
3283 |
+
$http_reason = count($arr) > 2 ? $arr[2] : '';
|
3284 |
+
|
3285 |
+
// see if we need to resend the request with http digest authentication
|
3286 |
+
if (isset($this->incoming_headers['location']) && ($http_status == 301 || $http_status == 302)) {
|
3287 |
+
$this->debug("Got $http_status $http_reason with Location: " . $this->incoming_headers['location']);
|
3288 |
+
$this->setURL($this->incoming_headers['location']);
|
3289 |
+
$this->tryagain = true;
|
3290 |
+
return false;
|
3291 |
+
}
|
3292 |
+
|
3293 |
+
// see if we need to resend the request with http digest authentication
|
3294 |
+
if (isset($this->incoming_headers['www-authenticate']) && $http_status == 401) {
|
3295 |
+
$this->debug("Got 401 $http_reason with WWW-Authenticate: " . $this->incoming_headers['www-authenticate']);
|
3296 |
+
if (strstr($this->incoming_headers['www-authenticate'], "Digest ")) {
|
3297 |
+
$this->debug('Server wants digest authentication');
|
3298 |
+
// remove "Digest " from our elements
|
3299 |
+
$digestString = str_replace('Digest ', '', $this->incoming_headers['www-authenticate']);
|
3300 |
+
|
3301 |
+
// parse elements into array
|
3302 |
+
$digestElements = explode(',', $digestString);
|
3303 |
+
foreach ($digestElements as $val) {
|
3304 |
+
$tempElement = explode('=', trim($val), 2);
|
3305 |
+
$digestRequest[$tempElement[0]] = str_replace("\"", '', $tempElement[1]);
|
3306 |
+
}
|
3307 |
+
|
3308 |
+
// should have (at least) qop, realm, nonce
|
3309 |
+
if (isset($digestRequest['nonce'])) {
|
3310 |
+
$this->setCredentials($this->username, $this->password, 'digest', $digestRequest);
|
3311 |
+
$this->tryagain = true;
|
3312 |
+
return false;
|
3313 |
+
}
|
3314 |
+
}
|
3315 |
+
$this->debug('HTTP authentication failed');
|
3316 |
+
$this->setError('HTTP authentication failed');
|
3317 |
+
return false;
|
3318 |
+
}
|
3319 |
+
|
3320 |
+
if (
|
3321 |
+
($http_status >= 300 && $http_status <= 307) ||
|
3322 |
+
($http_status >= 400 && $http_status <= 417) ||
|
3323 |
+
($http_status >= 501 && $http_status <= 505)
|
3324 |
+
) {
|
3325 |
+
$this->setError("Unsupported HTTP response status $http_status $http_reason (soapclient->response has contents of the response)");
|
3326 |
+
return false;
|
3327 |
+
}
|
3328 |
+
|
3329 |
+
// decode content-encoding
|
3330 |
+
if (isset($this->incoming_headers['content-encoding']) && $this->incoming_headers['content-encoding'] != '') {
|
3331 |
+
if (strtolower($this->incoming_headers['content-encoding']) == 'deflate' || strtolower($this->incoming_headers['content-encoding']) == 'gzip') {
|
3332 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
3333 |
+
if (function_exists('gzinflate')) {
|
3334 |
+
//$timer->setMarker('starting decoding of gzip/deflated content');
|
3335 |
+
// IIS 5 requires gzinflate instead of gzuncompress (similar to IE 5 and gzdeflate v. gzcompress)
|
3336 |
+
// this means there are no Zlib headers, although there should be
|
3337 |
+
$this->debug('The gzinflate function exists');
|
3338 |
+
$datalen = strlen($data);
|
3339 |
+
if ($this->incoming_headers['content-encoding'] == 'deflate') {
|
3340 |
+
if ($degzdata = @gzinflate($data)) {
|
3341 |
+
$data = $degzdata;
|
3342 |
+
$this->debug('The payload has been inflated to ' . strlen($data) . ' bytes');
|
3343 |
+
if (strlen($data) < $datalen) {
|
3344 |
+
// test for the case that the payload has been compressed twice
|
3345 |
+
$this->debug('The inflated payload is smaller than the gzipped one; try again');
|
3346 |
+
if ($degzdata = @gzinflate($data)) {
|
3347 |
+
$data = $degzdata;
|
3348 |
+
$this->debug('The payload has been inflated again to ' . strlen($data) . ' bytes');
|
3349 |
+
}
|
3350 |
+
}
|
3351 |
+
} else {
|
3352 |
+
$this->debug('Error using gzinflate to inflate the payload');
|
3353 |
+
$this->setError('Error using gzinflate to inflate the payload');
|
3354 |
+
}
|
3355 |
+
} elseif ($this->incoming_headers['content-encoding'] == 'gzip') {
|
3356 |
+
if ($degzdata = @gzinflate(substr($data, 10))) { // do our best
|
3357 |
+
$data = $degzdata;
|
3358 |
+
$this->debug('The payload has been un-gzipped to ' . strlen($data) . ' bytes');
|
3359 |
+
if (strlen($data) < $datalen) {
|
3360 |
+
// test for the case that the payload has been compressed twice
|
3361 |
+
$this->debug('The un-gzipped payload is smaller than the gzipped one; try again');
|
3362 |
+
if ($degzdata = @gzinflate(substr($data, 10))) {
|
3363 |
+
$data = $degzdata;
|
3364 |
+
$this->debug('The payload has been un-gzipped again to ' . strlen($data) . ' bytes');
|
3365 |
+
}
|
3366 |
+
}
|
3367 |
+
} else {
|
3368 |
+
$this->debug('Error using gzinflate to un-gzip the payload');
|
3369 |
+
$this->setError('Error using gzinflate to un-gzip the payload');
|
3370 |
+
}
|
3371 |
+
}
|
3372 |
+
//$timer->setMarker('finished decoding of gzip/deflated content');
|
3373 |
+
//print "<xmp>\nde-inflated:\n---------------\n$data\n-------------\n</xmp>";
|
3374 |
+
// set decoded payload
|
3375 |
+
$this->incoming_payload = $header_data . $lb . $lb . $data;
|
3376 |
+
} else {
|
3377 |
+
$this->debug('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
3378 |
+
$this->setError('The server sent compressed data. Your php install must have the Zlib extension compiled in to support this.');
|
3379 |
+
}
|
3380 |
+
} else {
|
3381 |
+
$this->debug('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
3382 |
+
$this->setError('Unsupported Content-Encoding ' . $this->incoming_headers['content-encoding']);
|
3383 |
+
}
|
3384 |
+
} else {
|
3385 |
+
$this->debug('No Content-Encoding header');
|
3386 |
+
}
|
3387 |
+
|
3388 |
+
if (strlen($data) == 0) {
|
3389 |
+
$this->debug('no data after headers!');
|
3390 |
+
$this->setError('no data present after HTTP headers');
|
3391 |
+
return false;
|
3392 |
+
}
|
3393 |
+
|
3394 |
+
return $data;
|
3395 |
+
}
|
3396 |
+
|
3397 |
+
/**
|
3398 |
+
* sets the content-type for the SOAP message to be sent
|
3399 |
+
*
|
3400 |
+
* @param string $type the content type, MIME style
|
3401 |
+
* @param mixed $charset character set used for encoding (or false)
|
3402 |
+
* @access public
|
3403 |
+
*/
|
3404 |
+
function setContentType($type, $charset = false)
|
3405 |
+
{
|
3406 |
+
$this->setHeader('Content-Type', $type . ($charset ? '; charset=' . $charset : ''));
|
3407 |
+
}
|
3408 |
+
|
3409 |
+
/**
|
3410 |
+
* specifies that an HTTP persistent connection should be used
|
3411 |
+
*
|
3412 |
+
* @return boolean whether the request was honored by this method.
|
3413 |
+
* @access public
|
3414 |
+
*/
|
3415 |
+
function usePersistentConnection()
|
3416 |
+
{
|
3417 |
+
if (isset($this->outgoing_headers['Accept-Encoding'])) {
|
3418 |
+
return false;
|
3419 |
+
}
|
3420 |
+
$this->protocol_version = '1.1';
|
3421 |
+
$this->persistentConnection = true;
|
3422 |
+
$this->setHeader('Connection', 'Keep-Alive');
|
3423 |
+
return true;
|
3424 |
+
}
|
3425 |
+
|
3426 |
+
/**
|
3427 |
+
* parse an incoming Cookie into it's parts
|
3428 |
+
*
|
3429 |
+
* @param string $cookie_str content of cookie
|
3430 |
+
* @return array with data of that cookie
|
3431 |
+
* @access private
|
3432 |
+
*/
|
3433 |
+
/*
|
3434 |
+
* TODO: allow a Set-Cookie string to be parsed into multiple cookies
|
3435 |
+
*/
|
3436 |
+
function parseCookie($cookie_str)
|
3437 |
+
{
|
3438 |
+
$cookie_str = str_replace('; ', ';', $cookie_str) . ';';
|
3439 |
+
$data = preg_split('/;/', $cookie_str);
|
3440 |
+
$value_str = $data[0];
|
3441 |
+
|
3442 |
+
$cookie_param = 'domain=';
|
3443 |
+
$start = strpos($cookie_str, $cookie_param);
|
3444 |
+
if ($start > 0) {
|
3445 |
+
$domain = substr($cookie_str, $start + strlen($cookie_param));
|
3446 |
+
$domain = substr($domain, 0, strpos($domain, ';'));
|
3447 |
+
} else {
|
3448 |
+
$domain = '';
|
3449 |
+
}
|
3450 |
+
|
3451 |
+
$cookie_param = 'expires=';
|
3452 |
+
$start = strpos($cookie_str, $cookie_param);
|
3453 |
+
if ($start > 0) {
|
3454 |
+
$expires = substr($cookie_str, $start + strlen($cookie_param));
|
3455 |
+
$expires = substr($expires, 0, strpos($expires, ';'));
|
3456 |
+
} else {
|
3457 |
+
$expires = '';
|
3458 |
+
}
|
3459 |
+
|
3460 |
+
$cookie_param = 'path=';
|
3461 |
+
$start = strpos($cookie_str, $cookie_param);
|
3462 |
+
if ($start > 0) {
|
3463 |
+
$path = substr($cookie_str, $start + strlen($cookie_param));
|
3464 |
+
$path = substr($path, 0, strpos($path, ';'));
|
3465 |
+
} else {
|
3466 |
+
$path = '/';
|
3467 |
+
}
|
3468 |
+
|
3469 |
+
$cookie_param = ';secure;';
|
3470 |
+
if (strpos($cookie_str, $cookie_param) !== false) {
|
3471 |
+
$secure = true;
|
3472 |
+
} else {
|
3473 |
+
$secure = false;
|
3474 |
+
}
|
3475 |
+
|
3476 |
+
$sep_pos = strpos($value_str, '=');
|
3477 |
+
|
3478 |
+
if ($sep_pos) {
|
3479 |
+
$name = substr($value_str, 0, $sep_pos);
|
3480 |
+
$value = substr($value_str, $sep_pos + 1);
|
3481 |
+
$cookie = array('name' => $name,
|
3482 |
+
'value' => $value,
|
3483 |
+
'domain' => $domain,
|
3484 |
+
'path' => $path,
|
3485 |
+
'expires' => $expires,
|
3486 |
+
'secure' => $secure
|
3487 |
+
);
|
3488 |
+
return $cookie;
|
3489 |
+
}
|
3490 |
+
return false;
|
3491 |
+
}
|
3492 |
+
|
3493 |
+
/**
|
3494 |
+
* sort out cookies for the current request
|
3495 |
+
*
|
3496 |
+
* @param array $cookies array with all cookies
|
3497 |
+
* @param boolean $secure is the send-content secure or not?
|
3498 |
+
* @return string for Cookie-HTTP-Header
|
3499 |
+
* @access private
|
3500 |
+
*/
|
3501 |
+
function getCookiesForRequest($cookies, $secure = false)
|
3502 |
+
{
|
3503 |
+
$cookie_str = '';
|
3504 |
+
if ((!is_null($cookies)) && (is_array($cookies))) {
|
3505 |
+
foreach ($cookies as $cookie) {
|
3506 |
+
if (!is_array($cookie)) {
|
3507 |
+
continue;
|
3508 |
+
}
|
3509 |
+
$this->debug("check cookie for validity: " . $cookie['name'] . '=' . $cookie['value']);
|
3510 |
+
if ((isset($cookie['expires'])) && (!empty($cookie['expires']))) {
|
3511 |
+
if (strtotime($cookie['expires']) <= time()) {
|
3512 |
+
$this->debug('cookie has expired');
|
3513 |
+
continue;
|
3514 |
+
}
|
3515 |
+
}
|
3516 |
+
if ((isset($cookie['domain'])) && (!empty($cookie['domain']))) {
|
3517 |
+
$domain = preg_quote($cookie['domain']);
|
3518 |
+
if (!preg_match("'.*$domain$'i", $this->host)) {
|
3519 |
+
$this->debug('cookie has different domain');
|
3520 |
+
continue;
|
3521 |
+
}
|
3522 |
+
}
|
3523 |
+
if ((isset($cookie['path'])) && (!empty($cookie['path']))) {
|
3524 |
+
$path = preg_quote($cookie['path']);
|
3525 |
+
if (!preg_match("'^$path.*'i", $this->path)) {
|
3526 |
+
$this->debug('cookie is for a different path');
|
3527 |
+
continue;
|
3528 |
+
}
|
3529 |
+
}
|
3530 |
+
if ((!$secure) && (isset($cookie['secure'])) && ($cookie['secure'])) {
|
3531 |
+
$this->debug('cookie is secure, transport is not');
|
3532 |
+
continue;
|
3533 |
+
}
|
3534 |
+
$cookie_str .= $cookie['name'] . '=' . $cookie['value'] . '; ';
|
3535 |
+
$this->debug('add cookie to Cookie-String: ' . $cookie['name'] . '=' . $cookie['value']);
|
3536 |
+
}
|
3537 |
+
}
|
3538 |
+
return $cookie_str;
|
3539 |
+
}
|
3540 |
+
}
|
3541 |
+
|
3542 |
+
|
3543 |
+
/**
|
3544 |
+
*
|
3545 |
+
* nusoap_server allows the user to create a SOAP server
|
3546 |
+
* that is capable of receiving messages and returning responses
|
3547 |
+
*
|
3548 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
3549 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
3550 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
3551 |
+
* @access public
|
3552 |
+
*/
|
3553 |
+
class nusoap_server extends nusoap_base
|
3554 |
+
{
|
3555 |
+
/**
|
3556 |
+
* HTTP headers of request
|
3557 |
+
*
|
3558 |
+
* @var array
|
3559 |
+
* @access private
|
3560 |
+
*/
|
3561 |
+
var $headers = array();
|
3562 |
+
/**
|
3563 |
+
* HTTP request
|
3564 |
+
*
|
3565 |
+
* @var string
|
3566 |
+
* @access private
|
3567 |
+
*/
|
3568 |
+
var $request = '';
|
3569 |
+
/**
|
3570 |
+
* SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
|
3571 |
+
*
|
3572 |
+
* @var string
|
3573 |
+
* @access public
|
3574 |
+
*/
|
3575 |
+
var $requestHeaders = '';
|
3576 |
+
/**
|
3577 |
+
* SOAP Headers from request (parsed)
|
3578 |
+
*
|
3579 |
+
* @var mixed
|
3580 |
+
* @access public
|
3581 |
+
*/
|
3582 |
+
var $requestHeader = null;
|
3583 |
+
/**
|
3584 |
+
* SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
|
3585 |
+
*
|
3586 |
+
* @var string
|
3587 |
+
* @access public
|
3588 |
+
*/
|
3589 |
+
var $document = '';
|
3590 |
+
/**
|
3591 |
+
* SOAP payload for request (text)
|
3592 |
+
*
|
3593 |
+
* @var string
|
3594 |
+
* @access public
|
3595 |
+
*/
|
3596 |
+
var $requestSOAP = '';
|
3597 |
+
/**
|
3598 |
+
* requested method namespace URI
|
3599 |
+
*
|
3600 |
+
* @var string
|
3601 |
+
* @access private
|
3602 |
+
*/
|
3603 |
+
var $methodURI = '';
|
3604 |
+
/**
|
3605 |
+
* name of method requested
|
3606 |
+
*
|
3607 |
+
* @var string
|
3608 |
+
* @access private
|
3609 |
+
*/
|
3610 |
+
var $methodname = '';
|
3611 |
+
/**
|
3612 |
+
* method parameters from request
|
3613 |
+
*
|
3614 |
+
* @var array
|
3615 |
+
* @access private
|
3616 |
+
*/
|
3617 |
+
var $methodparams = array();
|
3618 |
+
/**
|
3619 |
+
* SOAP Action from request
|
3620 |
+
*
|
3621 |
+
* @var string
|
3622 |
+
* @access private
|
3623 |
+
*/
|
3624 |
+
var $SOAPAction = '';
|
3625 |
+
/**
|
3626 |
+
* character set encoding of incoming (request) messages
|
3627 |
+
*
|
3628 |
+
* @var string
|
3629 |
+
* @access public
|
3630 |
+
*/
|
3631 |
+
var $xml_encoding = '';
|
3632 |
+
/**
|
3633 |
+
* toggles whether the parser decodes element content w/ utf8_decode()
|
3634 |
+
*
|
3635 |
+
* @var boolean
|
3636 |
+
* @access public
|
3637 |
+
*/
|
3638 |
+
var $decode_utf8 = true;
|
3639 |
+
|
3640 |
+
/**
|
3641 |
+
* HTTP headers of response
|
3642 |
+
*
|
3643 |
+
* @var array
|
3644 |
+
* @access public
|
3645 |
+
*/
|
3646 |
+
var $outgoing_headers = array();
|
3647 |
+
/**
|
3648 |
+
* HTTP response
|
3649 |
+
*
|
3650 |
+
* @var string
|
3651 |
+
* @access private
|
3652 |
+
*/
|
3653 |
+
var $response = '';
|
3654 |
+
/**
|
3655 |
+
* SOAP headers for response (text or array of soapval or associative array)
|
3656 |
+
*
|
3657 |
+
* @var mixed
|
3658 |
+
* @access public
|
3659 |
+
*/
|
3660 |
+
var $responseHeaders = '';
|
3661 |
+
/**
|
3662 |
+
* SOAP payload for response (text)
|
3663 |
+
*
|
3664 |
+
* @var string
|
3665 |
+
* @access private
|
3666 |
+
*/
|
3667 |
+
var $responseSOAP = '';
|
3668 |
+
/**
|
3669 |
+
* method return value to place in response
|
3670 |
+
*
|
3671 |
+
* @var mixed
|
3672 |
+
* @access private
|
3673 |
+
*/
|
3674 |
+
var $methodreturn = false;
|
3675 |
+
/**
|
3676 |
+
* whether $methodreturn is a string of literal XML
|
3677 |
+
*
|
3678 |
+
* @var boolean
|
3679 |
+
* @access public
|
3680 |
+
*/
|
3681 |
+
var $methodreturnisliteralxml = false;
|
3682 |
+
/**
|
3683 |
+
* SOAP fault for response (or false)
|
3684 |
+
*
|
3685 |
+
* @var mixed
|
3686 |
+
* @access private
|
3687 |
+
*/
|
3688 |
+
var $fault = false;
|
3689 |
+
/**
|
3690 |
+
* text indication of result (for debugging)
|
3691 |
+
*
|
3692 |
+
* @var string
|
3693 |
+
* @access private
|
3694 |
+
*/
|
3695 |
+
var $result = 'successful';
|
3696 |
+
|
3697 |
+
/**
|
3698 |
+
* assoc array of operations => opData; operations are added by the register()
|
3699 |
+
* method or by parsing an external WSDL definition
|
3700 |
+
*
|
3701 |
+
* @var array
|
3702 |
+
* @access private
|
3703 |
+
*/
|
3704 |
+
var $operations = array();
|
3705 |
+
/**
|
3706 |
+
* wsdl instance (if one)
|
3707 |
+
*
|
3708 |
+
* @var mixed
|
3709 |
+
* @access private
|
3710 |
+
*/
|
3711 |
+
var $wsdl = false;
|
3712 |
+
/**
|
3713 |
+
* URL for WSDL (if one)
|
3714 |
+
*
|
3715 |
+
* @var mixed
|
3716 |
+
* @access private
|
3717 |
+
*/
|
3718 |
+
var $externalWSDLURL = false;
|
3719 |
+
/**
|
3720 |
+
* whether to append debug to response as XML comment
|
3721 |
+
*
|
3722 |
+
* @var boolean
|
3723 |
+
* @access public
|
3724 |
+
*/
|
3725 |
+
var $debug_flag = false;
|
3726 |
+
|
3727 |
+
|
3728 |
+
/**
|
3729 |
+
* constructor
|
3730 |
+
* the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
|
3731 |
+
*
|
3732 |
+
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
|
3733 |
+
* @access public
|
3734 |
+
*/
|
3735 |
+
function __construct($wsdl = false)
|
3736 |
+
{
|
3737 |
+
parent::__construct();
|
3738 |
+
// turn on debugging?
|
3739 |
+
global $debug;
|
3740 |
+
global $HTTP_SERVER_VARS;
|
3741 |
+
|
3742 |
+
if (isset($_SERVER)) {
|
3743 |
+
$this->debug("_SERVER is defined:");
|
3744 |
+
$this->appendDebug($this->varDump($_SERVER));
|
3745 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
3746 |
+
$this->debug("HTTP_SERVER_VARS is defined:");
|
3747 |
+
$this->appendDebug($this->varDump($HTTP_SERVER_VARS));
|
3748 |
+
} else {
|
3749 |
+
$this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
|
3750 |
+
}
|
3751 |
+
|
3752 |
+
if (isset($debug)) {
|
3753 |
+
$this->debug("In nusoap_server, set debug_flag=$debug based on global flag");
|
3754 |
+
$this->debug_flag = $debug;
|
3755 |
+
} elseif (isset($_SERVER['QUERY_STRING'])) {
|
3756 |
+
$qs = explode('&', $_SERVER['QUERY_STRING']);
|
3757 |
+
foreach ($qs as $v) {
|
3758 |
+
if (substr($v, 0, 6) == 'debug=') {
|
3759 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
|
3760 |
+
$this->debug_flag = substr($v, 6);
|
3761 |
+
}
|
3762 |
+
}
|
3763 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
3764 |
+
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
|
3765 |
+
foreach ($qs as $v) {
|
3766 |
+
if (substr($v, 0, 6) == 'debug=') {
|
3767 |
+
$this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
|
3768 |
+
$this->debug_flag = substr($v, 6);
|
3769 |
+
}
|
3770 |
+
}
|
3771 |
+
}
|
3772 |
+
|
3773 |
+
// wsdl
|
3774 |
+
if ($wsdl) {
|
3775 |
+
$this->debug("In nusoap_server, WSDL is specified");
|
3776 |
+
if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) {
|
3777 |
+
$this->wsdl = $wsdl;
|
3778 |
+
$this->externalWSDLURL = $this->wsdl->wsdl;
|
3779 |
+
$this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
|
3780 |
+
} else {
|
3781 |
+
$this->debug('Create wsdl from ' . $wsdl);
|
3782 |
+
$this->wsdl = new wsdl($wsdl);
|
3783 |
+
$this->externalWSDLURL = $wsdl;
|
3784 |
+
}
|
3785 |
+
$this->appendDebug($this->wsdl->getDebug());
|
3786 |
+
$this->wsdl->clearDebug();
|
3787 |
+
if ($err = $this->wsdl->getError()) {
|
3788 |
+
die('WSDL ERROR: ' . $err);
|
3789 |
+
}
|
3790 |
+
}
|
3791 |
+
}
|
3792 |
+
|
3793 |
+
/**
|
3794 |
+
* processes request and returns response
|
3795 |
+
*
|
3796 |
+
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
|
3797 |
+
* @access public
|
3798 |
+
*/
|
3799 |
+
function service($data)
|
3800 |
+
{
|
3801 |
+
global $HTTP_SERVER_VARS;
|
3802 |
+
|
3803 |
+
if (isset($_SERVER['REQUEST_METHOD'])) {
|
3804 |
+
$rm = $_SERVER['REQUEST_METHOD'];
|
3805 |
+
} elseif (isset($HTTP_SERVER_VARS['REQUEST_METHOD'])) {
|
3806 |
+
$rm = $HTTP_SERVER_VARS['REQUEST_METHOD'];
|
3807 |
+
} else {
|
3808 |
+
$rm = '';
|
3809 |
+
}
|
3810 |
+
|
3811 |
+
if (isset($_SERVER['QUERY_STRING'])) {
|
3812 |
+
$qs = $_SERVER['QUERY_STRING'];
|
3813 |
+
} elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
|
3814 |
+
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
|
3815 |
+
} else {
|
3816 |
+
$qs = '';
|
3817 |
+
}
|
3818 |
+
$this->debug("In service, request method=$rm query string=$qs strlen(\$data)=" . strlen($data));
|
3819 |
+
|
3820 |
+
if ($rm == 'POST') {
|
3821 |
+
$this->debug("In service, invoke the request");
|
3822 |
+
$this->parse_request($data);
|
3823 |
+
if (!$this->fault) {
|
3824 |
+
$this->invoke_method();
|
3825 |
+
}
|
3826 |
+
if (!$this->fault) {
|
3827 |
+
$this->serialize_return();
|
3828 |
+
}
|
3829 |
+
$this->send_response();
|
3830 |
+
} elseif (preg_match('/wsdl/', $qs)) {
|
3831 |
+
$this->debug("In service, this is a request for WSDL");
|
3832 |
+
if ($this->externalWSDLURL) {
|
3833 |
+
if (strpos($this->externalWSDLURL, "http://") !== false) { // assume URL
|
3834 |
+
$this->debug("In service, re-direct for WSDL");
|
3835 |
+
header('Location: ' . $this->externalWSDLURL);
|
3836 |
+
} else { // assume file
|
3837 |
+
$this->debug("In service, use file passthru for WSDL");
|
3838 |
+
header("Content-Type: text/xml\r\n");
|
3839 |
+
$pos = strpos($this->externalWSDLURL, "file://");
|
3840 |
+
if ($pos === false) {
|
3841 |
+
$filename = $this->externalWSDLURL;
|
3842 |
+
} else {
|
3843 |
+
$filename = substr($this->externalWSDLURL, $pos + 7);
|
3844 |
+
}
|
3845 |
+
$fp = fopen($this->externalWSDLURL, 'r');
|
3846 |
+
fpassthru($fp);
|
3847 |
+
}
|
3848 |
+
} elseif ($this->wsdl) {
|
3849 |
+
$this->debug("In service, serialize WSDL");
|
3850 |
+
header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
|
3851 |
+
print $this->wsdl->serialize($this->debug_flag);
|
3852 |
+
if ($this->debug_flag) {
|
3853 |
+
$this->debug('wsdl:');
|
3854 |
+
$this->appendDebug($this->varDump($this->wsdl));
|
3855 |
+
print $this->getDebugAsXMLComment();
|
3856 |
+
}
|
3857 |
+
} else {
|
3858 |
+
$this->debug("In service, there is no WSDL");
|
3859 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
3860 |
+
print "This service does not provide WSDL";
|
3861 |
+
}
|
3862 |
+
} elseif ($this->wsdl) {
|
3863 |
+
$this->debug("In service, return Web description");
|
3864 |
+
print $this->wsdl->webDescription();
|
3865 |
+
} else {
|
3866 |
+
$this->debug("In service, no Web description");
|
3867 |
+
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
|
3868 |
+
print "This service does not provide a Web description";
|
3869 |
+
}
|
3870 |
+
}
|
3871 |
+
|
3872 |
+
/**
|
3873 |
+
* parses HTTP request headers.
|
3874 |
+
*
|
3875 |
+
* The following fields are set by this function (when successful)
|
3876 |
+
*
|
3877 |
+
* headers
|
3878 |
+
* request
|
3879 |
+
* xml_encoding
|
3880 |
+
* SOAPAction
|
3881 |
+
*
|
3882 |
+
* @access private
|
3883 |
+
*/
|
3884 |
+
function parse_http_headers()
|
3885 |
+
{
|
3886 |
+
global $HTTP_SERVER_VARS;
|
3887 |
+
|
3888 |
+
$this->request = '';
|
3889 |
+
$this->SOAPAction = '';
|
3890 |
+
if (function_exists('getallheaders')) {
|
3891 |
+
$this->debug("In parse_http_headers, use getallheaders");
|
3892 |
+
$headers = getallheaders();
|
3893 |
+
foreach ($headers as $k => $v) {
|
3894 |
+
$k = strtolower($k);
|
3895 |
+
$this->headers[$k] = $v;
|
3896 |
+
$this->request .= "$k: $v\r\n";
|
3897 |
+
$this->debug("$k: $v");
|
3898 |
+
}
|
3899 |
+
// get SOAPAction header
|
3900 |
+
if (isset($this->headers['soapaction'])) {
|
3901 |
+
$this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
|
3902 |
+
}
|
3903 |
+
// get the character encoding of the incoming request
|
3904 |
+
if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
|
3905 |
+
$enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
|
3906 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
|
3907 |
+
$this->xml_encoding = strtoupper($enc);
|
3908 |
+
} else {
|
3909 |
+
$this->xml_encoding = 'US-ASCII';
|
3910 |
+
}
|
3911 |
+
} else {
|
3912 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3913 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3914 |
+
}
|
3915 |
+
} elseif (isset($_SERVER) && is_array($_SERVER)) {
|
3916 |
+
$this->debug("In parse_http_headers, use _SERVER");
|
3917 |
+
foreach ($_SERVER as $k => $v) {
|
3918 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
3919 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
|
3920 |
+
} else {
|
3921 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
|
3922 |
+
}
|
3923 |
+
if ($k == 'soapaction') {
|
3924 |
+
// get SOAPAction header
|
3925 |
+
$k = 'SOAPAction';
|
3926 |
+
$v = str_replace('"', '', $v);
|
3927 |
+
$v = str_replace('\\', '', $v);
|
3928 |
+
$this->SOAPAction = $v;
|
3929 |
+
} elseif ($k == 'content-type') {
|
3930 |
+
// get the character encoding of the incoming request
|
3931 |
+
if (strpos($v, '=')) {
|
3932 |
+
$enc = substr(strstr($v, '='), 1);
|
3933 |
+
$enc = str_replace('"', '', $enc);
|
3934 |
+
$enc = str_replace('\\', '', $enc);
|
3935 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
|
3936 |
+
$this->xml_encoding = strtoupper($enc);
|
3937 |
+
} else {
|
3938 |
+
$this->xml_encoding = 'US-ASCII';
|
3939 |
+
}
|
3940 |
+
} else {
|
3941 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3942 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3943 |
+
}
|
3944 |
+
}
|
3945 |
+
$this->headers[$k] = $v;
|
3946 |
+
$this->request .= "$k: $v\r\n";
|
3947 |
+
$this->debug("$k: $v");
|
3948 |
+
}
|
3949 |
+
} elseif (is_array($HTTP_SERVER_VARS)) {
|
3950 |
+
$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
|
3951 |
+
foreach ($HTTP_SERVER_VARS as $k => $v) {
|
3952 |
+
if (substr($k, 0, 5) == 'HTTP_') {
|
3953 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5))));
|
3954 |
+
$k = strtolower(substr($k, 5));
|
3955 |
+
} else {
|
3956 |
+
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k)));
|
3957 |
+
$k = strtolower($k);
|
3958 |
+
}
|
3959 |
+
if ($k == 'soapaction') {
|
3960 |
+
// get SOAPAction header
|
3961 |
+
$k = 'SOAPAction';
|
3962 |
+
$v = str_replace('"', '', $v);
|
3963 |
+
$v = str_replace('\\', '', $v);
|
3964 |
+
$this->SOAPAction = $v;
|
3965 |
+
} elseif ($k == 'content-type') {
|
3966 |
+
// get the character encoding of the incoming request
|
3967 |
+
if (strpos($v, '=')) {
|
3968 |
+
$enc = substr(strstr($v, '='), 1);
|
3969 |
+
$enc = str_replace('"', '', $enc);
|
3970 |
+
$enc = str_replace('\\', '', $enc);
|
3971 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
|
3972 |
+
$this->xml_encoding = strtoupper($enc);
|
3973 |
+
} else {
|
3974 |
+
$this->xml_encoding = 'US-ASCII';
|
3975 |
+
}
|
3976 |
+
} else {
|
3977 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
3978 |
+
$this->xml_encoding = 'ISO-8859-1';
|
3979 |
+
}
|
3980 |
+
}
|
3981 |
+
$this->headers[$k] = $v;
|
3982 |
+
$this->request .= "$k: $v\r\n";
|
3983 |
+
$this->debug("$k: $v");
|
3984 |
+
}
|
3985 |
+
} else {
|
3986 |
+
$this->debug("In parse_http_headers, HTTP headers not accessible");
|
3987 |
+
$this->setError("HTTP headers not accessible");
|
3988 |
+
}
|
3989 |
+
}
|
3990 |
+
|
3991 |
+
/**
|
3992 |
+
* parses a request
|
3993 |
+
*
|
3994 |
+
* The following fields are set by this function (when successful)
|
3995 |
+
*
|
3996 |
+
* headers
|
3997 |
+
* request
|
3998 |
+
* xml_encoding
|
3999 |
+
* SOAPAction
|
4000 |
+
* request
|
4001 |
+
* requestSOAP
|
4002 |
+
* methodURI
|
4003 |
+
* methodname
|
4004 |
+
* methodparams
|
4005 |
+
* requestHeaders
|
4006 |
+
* document
|
4007 |
+
*
|
4008 |
+
* This sets the fault field on error
|
4009 |
+
*
|
4010 |
+
* @param string $data XML string
|
4011 |
+
* @access private
|
4012 |
+
*/
|
4013 |
+
function parse_request($data = '')
|
4014 |
+
{
|
4015 |
+
$this->debug('entering parse_request()');
|
4016 |
+
$this->parse_http_headers();
|
4017 |
+
$this->debug('got character encoding: ' . $this->xml_encoding);
|
4018 |
+
// uncompress if necessary
|
4019 |
+
if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
|
4020 |
+
$this->debug('got content encoding: ' . $this->headers['content-encoding']);
|
4021 |
+
if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
|
4022 |
+
// if decoding works, use it. else assume data wasn't gzencoded
|
4023 |
+
if (function_exists('gzuncompress')) {
|
4024 |
+
if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
|
4025 |
+
$data = $degzdata;
|
4026 |
+
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
|
4027 |
+
$data = $degzdata;
|
4028 |
+
} else {
|
4029 |
+
$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
|
4030 |
+
return;
|
4031 |
+
}
|
4032 |
+
} else {
|
4033 |
+
$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
|
4034 |
+
return;
|
4035 |
+
}
|
4036 |
+
}
|
4037 |
+
}
|
4038 |
+
$this->request .= "\r\n" . $data;
|
4039 |
+
$data = $this->parseRequest($this->headers, $data);
|
4040 |
+
$this->requestSOAP = $data;
|
4041 |
+
$this->debug('leaving parse_request');
|
4042 |
+
}
|
4043 |
+
|
4044 |
+
/**
|
4045 |
+
* invokes a PHP function for the requested SOAP method
|
4046 |
+
*
|
4047 |
+
* The following fields are set by this function (when successful)
|
4048 |
+
*
|
4049 |
+
* methodreturn
|
4050 |
+
*
|
4051 |
+
* Note that the PHP function that is called may also set the following
|
4052 |
+
* fields to affect the response sent to the client
|
4053 |
+
*
|
4054 |
+
* responseHeaders
|
4055 |
+
* outgoing_headers
|
4056 |
+
*
|
4057 |
+
* This sets the fault field on error
|
4058 |
+
*
|
4059 |
+
* @access private
|
4060 |
+
*/
|
4061 |
+
function invoke_method()
|
4062 |
+
{
|
4063 |
+
$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
|
4064 |
+
|
4065 |
+
//
|
4066 |
+
// if you are debugging in this area of the code, your service uses a class to implement methods,
|
4067 |
+
// you use SOAP RPC, and the client is .NET, please be aware of the following...
|
4068 |
+
// when the .NET wsdl.exe utility generates a proxy, it will remove the '.' or '..' from the
|
4069 |
+
// method name. that is fine for naming the .NET methods. it is not fine for properly constructing
|
4070 |
+
// the XML request and reading the XML response. you need to add the RequestElementName and
|
4071 |
+
// ResponseElementName to the System.Web.Services.Protocols.SoapRpcMethodAttribute that wsdl.exe
|
4072 |
+
// generates for the method. these parameters are used to specify the correct XML element names
|
4073 |
+
// for .NET to use, i.e. the names with the '.' in them.
|
4074 |
+
//
|
4075 |
+
$orig_methodname = $this->methodname;
|
4076 |
+
if ($this->wsdl) {
|
4077 |
+
if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
|
4078 |
+
$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
|
4079 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
4080 |
+
} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
|
4081 |
+
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
|
4082 |
+
$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
|
4083 |
+
$this->appendDebug('opData=' . $this->varDump($this->opData));
|
4084 |
+
$this->methodname = $this->opData['name'];
|
4085 |
+
} else {
|
4086 |
+
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
|
4087 |
+
$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
|
4088 |
+
return;
|
4089 |
+
}
|
4090 |
+
} else {
|
4091 |
+
$this->debug('in invoke_method, no WSDL to validate method');
|
4092 |
+
}
|
4093 |
+
|
4094 |
+
// if a . is present in $this->methodname, we see if there is a class in scope,
|
4095 |
+
// which could be referred to. We will also distinguish between two deliminators,
|
4096 |
+
// to allow methods to be called a the class or an instance
|
4097 |
+
if (strpos($this->methodname, '..') > 0) {
|
4098 |
+
$delim = '..';
|
4099 |
+
} elseif (strpos($this->methodname, '.') > 0) {
|
4100 |
+
$delim = '.';
|
4101 |
+
} else {
|
4102 |
+
$delim = '';
|
4103 |
+
}
|
4104 |
+
$this->debug("in invoke_method, delim=$delim");
|
4105 |
+
|
4106 |
+
$class = '';
|
4107 |
+
$method = '';
|
4108 |
+
if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
|
4109 |
+
$try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
|
4110 |
+
if (class_exists($try_class)) {
|
4111 |
+
// get the class and method name
|
4112 |
+
$class = $try_class;
|
4113 |
+
$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
|
4114 |
+
$this->debug("in invoke_method, class=$class method=$method delim=$delim");
|
4115 |
+
} else {
|
4116 |
+
$this->debug("in invoke_method, class=$try_class not found");
|
4117 |
+
}
|
4118 |
+
} elseif (strlen($delim) > 0 && substr_count($this->methodname, $delim) > 1) {
|
4119 |
+
$split = explode($delim, $this->methodname);
|
4120 |
+
$method = array_pop($split);
|
4121 |
+
$class = implode('\\', $split);
|
4122 |
+
} else {
|
4123 |
+
$try_class = '';
|
4124 |
+
$this->debug("in invoke_method, no class to try");
|
4125 |
+
}
|
4126 |
+
|
4127 |
+
// does method exist?
|
4128 |
+
if ($class == '') {
|
4129 |
+
if (!function_exists($this->methodname)) {
|
4130 |
+
$this->debug("in invoke_method, function '$this->methodname' not found!");
|
4131 |
+
$this->result = 'fault: method not found';
|
4132 |
+
$this->fault('SOAP-ENV:Client', "method '$this->methodname'('$orig_methodname') not defined in service('$try_class' '$delim')");
|
4133 |
+
return;
|
4134 |
+
}
|
4135 |
+
} else {
|
4136 |
+
$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
|
4137 |
+
if (!in_array($method_to_compare, get_class_methods($class))) {
|
4138 |
+
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
|
4139 |
+
$this->result = 'fault: method not found';
|
4140 |
+
$this->fault('SOAP-ENV:Client', "method '$this->methodname'/'$method_to_compare'('$orig_methodname') not defined in service/'$class'('$try_class' '$delim')");
|
4141 |
+
return;
|
4142 |
+
}
|
4143 |
+
}
|
4144 |
+
|
4145 |
+
// evaluate message, getting back parameters
|
4146 |
+
// verify that request parameters match the method's signature
|
4147 |
+
if (!$this->verify_method($this->methodname, $this->methodparams)) {
|
4148 |
+
// debug
|
4149 |
+
$this->debug('ERROR: request not verified against method signature');
|
4150 |
+
$this->result = 'fault: request failed validation against method signature';
|
4151 |
+
// return fault
|
4152 |
+
$this->fault('SOAP-ENV:Client', "Operation '$this->methodname' not defined in service.");
|
4153 |
+
return;
|
4154 |
+
}
|
4155 |
+
|
4156 |
+
// if there are parameters to pass
|
4157 |
+
$this->debug('in invoke_method, params:');
|
4158 |
+
$this->appendDebug($this->varDump($this->methodparams));
|
4159 |
+
$this->debug("in invoke_method, calling '$this->methodname'");
|
4160 |
+
if (!function_exists('call_user_func_array')) {
|
4161 |
+
if ($class == '') {
|
4162 |
+
$this->debug('in invoke_method, calling function using eval()');
|
4163 |
+
$funcCall = "\$this->methodreturn = $this->methodname(";
|
4164 |
+
} else {
|
4165 |
+
if ($delim == '..') {
|
4166 |
+
$this->debug('in invoke_method, calling class method using eval()');
|
4167 |
+
$funcCall = "\$this->methodreturn = " . $class . "::" . $method . "(";
|
4168 |
+
} else {
|
4169 |
+
$this->debug('in invoke_method, calling instance method using eval()');
|
4170 |
+
// generate unique instance name
|
4171 |
+
$instname = "\$inst_" . time();
|
4172 |
+
$funcCall = $instname . " = new " . $class . "(); ";
|
4173 |
+
$funcCall .= "\$this->methodreturn = " . $instname . "->" . $method . "(";
|
4174 |
+
}
|
4175 |
+
}
|
4176 |
+
if ($this->methodparams) {
|
4177 |
+
foreach ($this->methodparams as $param) {
|
4178 |
+
if (is_array($param) || is_object($param)) {
|
4179 |
+
$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
|
4180 |
+
return;
|
4181 |
+
}
|
4182 |
+
$funcCall .= "\"$param\",";
|
4183 |
+
}
|
4184 |
+
$funcCall = substr($funcCall, 0, -1);
|
4185 |
+
}
|
4186 |
+
$funcCall .= ');';
|
4187 |
+
$this->debug('in invoke_method, function call: ' . $funcCall);
|
4188 |
+
@eval($funcCall);
|
4189 |
+
} else {
|
4190 |
+
if ($class == '') {
|
4191 |
+
$this->debug('in invoke_method, calling function using call_user_func_array()');
|
4192 |
+
$call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
|
4193 |
+
} elseif ($delim == '..') {
|
4194 |
+
$this->debug('in invoke_method, calling class method using call_user_func_array()');
|
4195 |
+
$call_arg = array($class, $method);
|
4196 |
+
} else {
|
4197 |
+
$this->debug('in invoke_method, calling instance method using call_user_func_array()');
|
4198 |
+
$instance = new $class ();
|
4199 |
+
$call_arg = array(&$instance, $method);
|
4200 |
+
}
|
4201 |
+
if (is_array($this->methodparams)) {
|
4202 |
+
$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
|
4203 |
+
} else {
|
4204 |
+
$this->methodreturn = call_user_func_array($call_arg, array());
|
4205 |
+
}
|
4206 |
+
}
|
4207 |
+
$this->debug('in invoke_method, methodreturn:');
|
4208 |
+
$this->appendDebug($this->varDump($this->methodreturn));
|
4209 |
+
$this->debug("in invoke_method, called method $this->methodname, received data of type " . gettype($this->methodreturn));
|
4210 |
+
}
|
4211 |
+
|
4212 |
+
/**
|
4213 |
+
* serializes the return value from a PHP function into a full SOAP Envelope
|
4214 |
+
*
|
4215 |
+
* The following fields are set by this function (when successful)
|
4216 |
+
*
|
4217 |
+
* responseSOAP
|
4218 |
+
*
|
4219 |
+
* This sets the fault field on error
|
4220 |
+
*
|
4221 |
+
* @access private
|
4222 |
+
*/
|
4223 |
+
function serialize_return()
|
4224 |
+
{
|
4225 |
+
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
|
4226 |
+
// if fault
|
4227 |
+
if (isset($this->methodreturn) && is_object($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
|
4228 |
+
$this->debug('got a fault object from method');
|
4229 |
+
$this->fault = $this->methodreturn;
|
4230 |
+
return;
|
4231 |
+
} elseif ($this->methodreturnisliteralxml) {
|
4232 |
+
$return_val = $this->methodreturn;
|
4233 |
+
// returned value(s)
|
4234 |
+
} else {
|
4235 |
+
$this->debug('got a(n) ' . gettype($this->methodreturn) . ' from method');
|
4236 |
+
$this->debug('serializing return value');
|
4237 |
+
if ($this->wsdl) {
|
4238 |
+
if (sizeof($this->opData['output']['parts']) > 1) {
|
4239 |
+
$this->debug('more than one output part, so use the method return unchanged');
|
4240 |
+
$opParams = $this->methodreturn;
|
4241 |
+
} elseif (sizeof($this->opData['output']['parts']) == 1) {
|
4242 |
+
$this->debug('exactly one output part, so wrap the method return in a simple array');
|
4243 |
+
// TODO: verify that it is not already wrapped!
|
4244 |
+
//foreach ($this->opData['output']['parts'] as $name => $type) {
|
4245 |
+
// $this->debug('wrap in element named ' . $name);
|
4246 |
+
//}
|
4247 |
+
$opParams = array($this->methodreturn);
|
4248 |
+
}
|
4249 |
+
$return_val = $this->wsdl->serializeRPCParameters($this->methodname, 'output', $opParams);
|
4250 |
+
$this->appendDebug($this->wsdl->getDebug());
|
4251 |
+
$this->wsdl->clearDebug();
|
4252 |
+
if ($errstr = $this->wsdl->getError()) {
|
4253 |
+
$this->debug('got wsdl error: ' . $errstr);
|
4254 |
+
$this->fault('SOAP-ENV:Server', 'unable to serialize result');
|
4255 |
+
return;
|
4256 |
+
}
|
4257 |
+
} else {
|
4258 |
+
if (isset($this->methodreturn)) {
|
4259 |
+
$return_val = $this->serialize_val($this->methodreturn, 'return');
|
4260 |
+
} else {
|
4261 |
+
$return_val = '';
|
4262 |
+
$this->debug('in absence of WSDL, assume void return for backward compatibility');
|
4263 |
+
}
|
4264 |
+
}
|
4265 |
+
}
|
4266 |
+
$this->debug('return value:');
|
4267 |
+
$this->appendDebug($this->varDump($return_val));
|
4268 |
+
|
4269 |
+
$this->debug('serializing response');
|
4270 |
+
if ($this->wsdl) {
|
4271 |
+
$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
|
4272 |
+
if ($this->opData['style'] == 'rpc') {
|
4273 |
+
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
|
4274 |
+
if ($this->opData['output']['use'] == 'literal') {
|
4275 |
+
// 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
|
4276 |
+
if ($this->methodURI) {
|
4277 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4278 |
+
} else {
|
4279 |
+
$payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
|
4280 |
+
}
|
4281 |
+
} else {
|
4282 |
+
if ($this->methodURI) {
|
4283 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4284 |
+
} else {
|
4285 |
+
$payload = '<' . $this->methodname . 'Response>' . $return_val . '</' . $this->methodname . 'Response>';
|
4286 |
+
}
|
4287 |
+
}
|
4288 |
+
} else {
|
4289 |
+
$this->debug('style is not rpc for serialization: assume document');
|
4290 |
+
$payload = $return_val;
|
4291 |
+
}
|
4292 |
+
} else {
|
4293 |
+
$this->debug('do not have WSDL for serialization: assume rpc/encoded');
|
4294 |
+
$payload = '<ns1:' . $this->methodname . 'Response xmlns:ns1="' . $this->methodURI . '">' . $return_val . '</ns1:' . $this->methodname . "Response>";
|
4295 |
+
}
|
4296 |
+
$this->result = 'successful';
|
4297 |
+
if ($this->wsdl) {
|
4298 |
+
//if($this->debug_flag){
|
4299 |
+
$this->appendDebug($this->wsdl->getDebug());
|
4300 |
+
// }
|
4301 |
+
if (isset($this->opData['output']['encodingStyle'])) {
|
4302 |
+
$encodingStyle = $this->opData['output']['encodingStyle'];
|
4303 |
+
} else {
|
4304 |
+
$encodingStyle = '';
|
4305 |
+
}
|
4306 |
+
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
|
4307 |
+
$this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders, $this->wsdl->usedNamespaces, $this->opData['style'], $this->opData['output']['use'], $encodingStyle);
|
4308 |
+
} else {
|
4309 |
+
$this->responseSOAP = $this->serializeEnvelope($payload, $this->responseHeaders);
|
4310 |
+
}
|
4311 |
+
$this->debug("Leaving serialize_return");
|
4312 |
+
}
|
4313 |
+
|
4314 |
+
/**
|
4315 |
+
* sends an HTTP response
|
4316 |
+
*
|
4317 |
+
* The following fields are set by this function (when successful)
|
4318 |
+
*
|
4319 |
+
* outgoing_headers
|
4320 |
+
* response
|
4321 |
+
*
|
4322 |
+
* @access private
|
4323 |
+
*/
|
4324 |
+
function send_response()
|
4325 |
+
{
|
4326 |
+
$this->debug('Enter send_response');
|
4327 |
+
if ($this->fault) {
|
4328 |
+
$payload = $this->fault->serialize();
|
4329 |
+
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
|
4330 |
+
$this->outgoing_headers[] = "Status: 500 Internal Server Error";
|
4331 |
+
} else {
|
4332 |
+
$payload = $this->responseSOAP;
|
4333 |
+
// Some combinations of PHP+Web server allow the Status
|
4334 |
+
// to come through as a header. Since OK is the default
|
4335 |
+
// just do nothing.
|
4336 |
+
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
|
4337 |
+
// $this->outgoing_headers[] = "Status: 200 OK";
|
4338 |
+
}
|
4339 |
+
// add debug data if in debug mode
|
4340 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4341 |
+
$payload .= $this->getDebugAsXMLComment();
|
4342 |
+
}
|
4343 |
+
$this->outgoing_headers[] = "Server: $this->title Server v$this->version";
|
4344 |
+
preg_match('/\$Revisio' . 'n: ([^ ]+)/', $this->revision, $rev);
|
4345 |
+
$this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (" . $rev[1] . ")";
|
4346 |
+
// Let the Web server decide about this
|
4347 |
+
//$this->outgoing_headers[] = "Connection: Close\r\n";
|
4348 |
+
$payload = $this->getHTTPBody($payload);
|
4349 |
+
$type = $this->getHTTPContentType();
|
4350 |
+
$charset = $this->getHTTPContentTypeCharset();
|
4351 |
+
$this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : '');
|
4352 |
+
//begin code to compress payload - by John
|
4353 |
+
// NOTE: there is no way to know whether the Web server will also compress
|
4354 |
+
// this data.
|
4355 |
+
if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
|
4356 |
+
if (strstr($this->headers['accept-encoding'], 'gzip')) {
|
4357 |
+
if (function_exists('gzencode')) {
|
4358 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4359 |
+
$payload .= "<!-- Content being gzipped -->";
|
4360 |
+
}
|
4361 |
+
$this->outgoing_headers[] = "Content-Encoding: gzip";
|
4362 |
+
$payload = gzencode($payload);
|
4363 |
+
} else {
|
4364 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4365 |
+
$payload .= "<!-- Content will not be gzipped: no gzencode -->";
|
4366 |
+
}
|
4367 |
+
}
|
4368 |
+
} elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
|
4369 |
+
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
|
4370 |
+
// instead of gzcompress output,
|
4371 |
+
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
|
4372 |
+
if (function_exists('gzdeflate')) {
|
4373 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4374 |
+
$payload .= "<!-- Content being deflated -->";
|
4375 |
+
}
|
4376 |
+
$this->outgoing_headers[] = "Content-Encoding: deflate";
|
4377 |
+
$payload = gzdeflate($payload);
|
4378 |
+
} else {
|
4379 |
+
if (isset($this->debug_flag) && $this->debug_flag) {
|
4380 |
+
$payload .= "<!-- Content will not be deflated: no gzcompress -->";
|
4381 |
+
}
|
4382 |
+
}
|
4383 |
+
}
|
4384 |
+
}
|
4385 |
+
//end code
|
4386 |
+
$this->outgoing_headers[] = "Content-Length: " . strlen($payload);
|
4387 |
+
reset($this->outgoing_headers);
|
4388 |
+
foreach ($this->outgoing_headers as $hdr) {
|
4389 |
+
header($hdr, false);
|
4390 |
+
}
|
4391 |
+
print $payload;
|
4392 |
+
$this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
|
4393 |
+
}
|
4394 |
+
|
4395 |
+
/**
|
4396 |
+
* takes the value that was created by parsing the request
|
4397 |
+
* and compares to the method's signature, if available.
|
4398 |
+
*
|
4399 |
+
* @param string $operation The operation to be invoked
|
4400 |
+
* @param array $request The array of parameter values
|
4401 |
+
* @return boolean Whether the operation was found
|
4402 |
+
* @access private
|
4403 |
+
*/
|
4404 |
+
function verify_method($operation, $request)
|
4405 |
+
{
|
4406 |
+
if (isset($this->wsdl) && is_object($this->wsdl)) {
|
4407 |
+
if ($this->wsdl->getOperationData($operation)) {
|
4408 |
+
return true;
|
4409 |
+
}
|
4410 |
+
} elseif (isset($this->operations[$operation])) {
|
4411 |
+
return true;
|
4412 |
+
}
|
4413 |
+
return false;
|
4414 |
+
}
|
4415 |
+
|
4416 |
+
/**
|
4417 |
+
* processes SOAP message received from client
|
4418 |
+
*
|
4419 |
+
* @param array $headers The HTTP headers
|
4420 |
+
* @param string $data unprocessed request data from client
|
4421 |
+
* @return mixed value of the message, decoded into a PHP type
|
4422 |
+
* @access private
|
4423 |
+
*/
|
4424 |
+
function parseRequest($headers, $data)
|
4425 |
+
{
|
4426 |
+
$this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' headers:');
|
4427 |
+
$this->appendDebug($this->varDump($headers));
|
4428 |
+
if (!isset($headers['content-type'])) {
|
4429 |
+
$this->setError('Request not of type text/xml (no content-type header)');
|
4430 |
+
return false;
|
4431 |
+
}
|
4432 |
+
if (!strstr($headers['content-type'], 'text/xml')) {
|
4433 |
+
$this->setError('Request not of type text/xml');
|
4434 |
+
return false;
|
4435 |
+
}
|
4436 |
+
if (strpos($headers['content-type'], '=')) {
|
4437 |
+
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
|
4438 |
+
$this->debug('Got response encoding: ' . $enc);
|
4439 |
+
if (preg_match('/^(ISO-8859-1|US-ASCII|UTF-8)$/i', $enc)) {
|
4440 |
+
$this->xml_encoding = strtoupper($enc);
|
4441 |
+
} else {
|
4442 |
+
$this->xml_encoding = 'US-ASCII';
|
4443 |
+
}
|
4444 |
+
} else {
|
4445 |
+
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
|
4446 |
+
$this->xml_encoding = 'ISO-8859-1';
|
4447 |
+
}
|
4448 |
+
$this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser');
|
4449 |
+
// parse response, get soap parser obj
|
4450 |
+
$parser = new nusoap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
|
4451 |
+
// parser debug
|
4452 |
+
$this->debug("parser debug: \n" . $parser->getDebug());
|
4453 |
+
// if fault occurred during message parsing
|
4454 |
+
if ($err = $parser->getError()) {
|
4455 |
+
$this->result = 'fault: error in msg parsing: ' . $err;
|
4456 |
+
$this->fault('SOAP-ENV:Client', "error in msg parsing:\n" . $err);
|
4457 |
+
// else successfully parsed request into soapval object
|
4458 |
+
} else {
|
4459 |
+
// get/set methodname
|
4460 |
+
$this->methodURI = $parser->root_struct_namespace;
|
4461 |
+
$this->methodname = $parser->root_struct_name;
|
4462 |
+
$this->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
|
4463 |
+
$this->debug('calling parser->get_soapbody()');
|
4464 |
+
$this->methodparams = $parser->get_soapbody();
|
4465 |
+
// get SOAP headers
|
4466 |
+
$this->requestHeaders = $parser->getHeaders();
|
4467 |
+
// get SOAP Header
|
4468 |
+
$this->requestHeader = $parser->get_soapheader();
|
4469 |
+
// add document for doclit support
|
4470 |
+
$this->document = $parser->document;
|
4471 |
+
}
|
4472 |
+
}
|
4473 |
+
|
4474 |
+
/**
|
4475 |
+
* gets the HTTP body for the current response.
|
4476 |
+
*
|
4477 |
+
* @param string $soapmsg The SOAP payload
|
4478 |
+
* @return string The HTTP body, which includes the SOAP payload
|
4479 |
+
* @access private
|
4480 |
+
*/
|
4481 |
+
function getHTTPBody($soapmsg)
|
4482 |
+
{
|
4483 |
+
return $soapmsg;
|
4484 |
+
}
|
4485 |
+
|
4486 |
+
/**
|
4487 |
+
* gets the HTTP content type for the current response.
|
4488 |
+
*
|
4489 |
+
* Note: getHTTPBody must be called before this.
|
4490 |
+
*
|
4491 |
+
* @return string the HTTP content type for the current response.
|
4492 |
+
* @access private
|
4493 |
+
*/
|
4494 |
+
function getHTTPContentType()
|
4495 |
+
{
|
4496 |
+
return 'text/xml';
|
4497 |
+
}
|
4498 |
+
|
4499 |
+
/**
|
4500 |
+
* gets the HTTP content type charset for the current response.
|
4501 |
+
* returns false for non-text content types.
|
4502 |
+
*
|
4503 |
+
* Note: getHTTPBody must be called before this.
|
4504 |
+
*
|
4505 |
+
* @return string the HTTP content type charset for the current response.
|
4506 |
+
* @access private
|
4507 |
+
*/
|
4508 |
+
function getHTTPContentTypeCharset()
|
4509 |
+
{
|
4510 |
+
return $this->soap_defencoding;
|
4511 |
+
}
|
4512 |
+
|
4513 |
+
/**
|
4514 |
+
* add a method to the dispatch map (this has been replaced by the register method)
|
4515 |
+
*
|
4516 |
+
* @param string $methodname
|
4517 |
+
* @param string $in array of input values
|
4518 |
+
* @param string $out array of output values
|
4519 |
+
* @access public
|
4520 |
+
* @deprecated
|
4521 |
+
*/
|
4522 |
+
function add_to_map($methodname, $in, $out)
|
4523 |
+
{
|
4524 |
+
$this->operations[$methodname] = array('name' => $methodname, 'in' => $in, 'out' => $out);
|
4525 |
+
}
|
4526 |
+
|
4527 |
+
/**
|
4528 |
+
* register a service function with the server
|
4529 |
+
*
|
4530 |
+
* @param string $name the name of the PHP function, class.method or class..method
|
4531 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
4532 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
4533 |
+
* @param mixed $namespace the element namespace for the method or false
|
4534 |
+
* @param mixed $soapaction the soapaction for the method or false
|
4535 |
+
* @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
|
4536 |
+
* @param mixed $use optional (encoded|literal) or false
|
4537 |
+
* @param string $documentation optional Description to include in WSDL
|
4538 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
4539 |
+
* @access public
|
4540 |
+
*/
|
4541 |
+
function register($name, $in = array(), $out = array(), $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '')
|
4542 |
+
{
|
4543 |
+
global $HTTP_SERVER_VARS;
|
4544 |
+
|
4545 |
+
if ($this->externalWSDLURL) {
|
4546 |
+
die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
|
4547 |
+
}
|
4548 |
+
if (!$name) {
|
4549 |
+
die('You must specify a name when you register an operation');
|
4550 |
+
}
|
4551 |
+
if (!is_array($in)) {
|
4552 |
+
die('You must provide an array for operation inputs');
|
4553 |
+
}
|
4554 |
+
if (!is_array($out)) {
|
4555 |
+
die('You must provide an array for operation outputs');
|
4556 |
+
}
|
4557 |
+
if (false == $namespace) {
|
4558 |
+
}
|
4559 |
+
if (false == $soapaction) {
|
4560 |
+
if (isset($_SERVER)) {
|
4561 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4562 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4563 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
4564 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
4565 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4566 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4567 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4568 |
+
} else {
|
4569 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
4570 |
+
}
|
4571 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
4572 |
+
$SCHEME = 'https';
|
4573 |
+
} else {
|
4574 |
+
$SCHEME = 'http';
|
4575 |
+
}
|
4576 |
+
$soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name";
|
4577 |
+
}
|
4578 |
+
if (false == $style) {
|
4579 |
+
$style = "rpc";
|
4580 |
+
}
|
4581 |
+
if (false == $use) {
|
4582 |
+
$use = "encoded";
|
4583 |
+
}
|
4584 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
4585 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
4586 |
+
}
|
4587 |
+
|
4588 |
+
$this->operations[$name] = array(
|
4589 |
+
'name' => $name,
|
4590 |
+
'in' => $in,
|
4591 |
+
'out' => $out,
|
4592 |
+
'namespace' => $namespace,
|
4593 |
+
'soapaction' => $soapaction,
|
4594 |
+
'style' => $style);
|
4595 |
+
if ($this->wsdl) {
|
4596 |
+
$this->wsdl->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
|
4597 |
+
}
|
4598 |
+
return true;
|
4599 |
+
}
|
4600 |
+
|
4601 |
+
/**
|
4602 |
+
* Specify a fault to be returned to the client.
|
4603 |
+
* This also acts as a flag to the server that a fault has occured.
|
4604 |
+
*
|
4605 |
+
* @param string $faultcode
|
4606 |
+
* @param string $faultstring
|
4607 |
+
* @param string $faultactor
|
4608 |
+
* @param string $faultdetail
|
4609 |
+
* @access public
|
4610 |
+
*/
|
4611 |
+
function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '')
|
4612 |
+
{
|
4613 |
+
if ($faultdetail == '' && $this->debug_flag) {
|
4614 |
+
$faultdetail = $this->getDebug();
|
4615 |
+
}
|
4616 |
+
$this->fault = new nusoap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
|
4617 |
+
$this->fault->soap_defencoding = $this->soap_defencoding;
|
4618 |
+
}
|
4619 |
+
|
4620 |
+
/**
|
4621 |
+
* Sets up wsdl object.
|
4622 |
+
* Acts as a flag to enable internal WSDL generation
|
4623 |
+
*
|
4624 |
+
* @param string $serviceName , name of the service
|
4625 |
+
* @param mixed $namespace optional 'tns' service namespace or false
|
4626 |
+
* @param mixed $endpoint optional URL of service endpoint or false
|
4627 |
+
* @param string $style optional (rpc|document) WSDL style (also specified by operation)
|
4628 |
+
* @param string $transport optional SOAP transport
|
4629 |
+
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
|
4630 |
+
*/
|
4631 |
+
function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false)
|
4632 |
+
{
|
4633 |
+
global $HTTP_SERVER_VARS;
|
4634 |
+
|
4635 |
+
if (isset($_SERVER)) {
|
4636 |
+
$SERVER_NAME = $_SERVER['SERVER_NAME'];
|
4637 |
+
$SERVER_PORT = $_SERVER['SERVER_PORT'];
|
4638 |
+
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
|
4639 |
+
$HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off');
|
4640 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
4641 |
+
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
|
4642 |
+
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
|
4643 |
+
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
|
4644 |
+
$HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off';
|
4645 |
+
} else {
|
4646 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
4647 |
+
}
|
4648 |
+
// If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI)
|
4649 |
+
$colon = strpos($SERVER_NAME, ":");
|
4650 |
+
if ($colon) {
|
4651 |
+
$SERVER_NAME = substr($SERVER_NAME, 0, $colon);
|
4652 |
+
}
|
4653 |
+
if ($SERVER_PORT == 80) {
|
4654 |
+
$SERVER_PORT = '';
|
4655 |
+
} else {
|
4656 |
+
$SERVER_PORT = ':' . $SERVER_PORT;
|
4657 |
+
}
|
4658 |
+
if (false == $namespace) {
|
4659 |
+
$namespace = "http://$SERVER_NAME/soap/$serviceName";
|
4660 |
+
}
|
4661 |
+
|
4662 |
+
if (false == $endpoint) {
|
4663 |
+
if ($HTTPS == '1' || $HTTPS == 'on') {
|
4664 |
+
$SCHEME = 'https';
|
4665 |
+
} else {
|
4666 |
+
$SCHEME = 'http';
|
4667 |
+
}
|
4668 |
+
$endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME";
|
4669 |
+
}
|
4670 |
+
|
4671 |
+
if (false == $schemaTargetNamespace) {
|
4672 |
+
$schemaTargetNamespace = $namespace;
|
4673 |
+
}
|
4674 |
+
|
4675 |
+
$this->wsdl = new wsdl;
|
4676 |
+
$this->wsdl->serviceName = $serviceName;
|
4677 |
+
$this->wsdl->endpoint = $endpoint;
|
4678 |
+
$this->wsdl->namespaces['tns'] = $namespace;
|
4679 |
+
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
4680 |
+
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
|
4681 |
+
if ($schemaTargetNamespace != $namespace) {
|
4682 |
+
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
|
4683 |
+
}
|
4684 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces);
|
4685 |
+
if ($style == 'document') {
|
4686 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified';
|
4687 |
+
}
|
4688 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
|
4689 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true);
|
4690 |
+
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true);
|
4691 |
+
$this->wsdl->bindings[$serviceName . 'Binding'] = array(
|
4692 |
+
'name' => $serviceName . 'Binding',
|
4693 |
+
'style' => $style,
|
4694 |
+
'transport' => $transport,
|
4695 |
+
'portType' => $serviceName . 'PortType');
|
4696 |
+
$this->wsdl->ports[$serviceName . 'Port'] = array(
|
4697 |
+
'binding' => $serviceName . 'Binding',
|
4698 |
+
'location' => $endpoint,
|
4699 |
+
'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/');
|
4700 |
+
}
|
4701 |
+
}
|
4702 |
+
|
4703 |
+
/**
|
4704 |
+
* Backward compatibility
|
4705 |
+
*/
|
4706 |
+
class soap_server extends nusoap_server
|
4707 |
+
{
|
4708 |
+
}
|
4709 |
+
|
4710 |
+
|
4711 |
+
/**
|
4712 |
+
* parses a WSDL file, allows access to it's data, other utility methods.
|
4713 |
+
* also builds WSDL structures programmatically.
|
4714 |
+
*
|
4715 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
4716 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
4717 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
4718 |
+
* @access public
|
4719 |
+
*/
|
4720 |
+
class wsdl extends nusoap_base
|
4721 |
+
{
|
4722 |
+
// URL or filename of the root of this WSDL
|
4723 |
+
var $wsdl;
|
4724 |
+
// define internal arrays of bindings, ports, operations, messages, etc.
|
4725 |
+
var $schemas = array();
|
4726 |
+
var $currentSchema;
|
4727 |
+
var $message = array();
|
4728 |
+
var $complexTypes = array();
|
4729 |
+
var $messages = array();
|
4730 |
+
var $currentMessage;
|
4731 |
+
var $currentOperation;
|
4732 |
+
var $portTypes = array();
|
4733 |
+
var $currentPortType;
|
4734 |
+
var $bindings = array();
|
4735 |
+
var $currentBinding;
|
4736 |
+
var $ports = array();
|
4737 |
+
var $currentPort;
|
4738 |
+
var $opData = array();
|
4739 |
+
var $status = '';
|
4740 |
+
var $documentation = false;
|
4741 |
+
var $endpoint = '';
|
4742 |
+
// array of wsdl docs to import
|
4743 |
+
var $import = array();
|
4744 |
+
// parser vars
|
4745 |
+
var $parser;
|
4746 |
+
var $position = 0;
|
4747 |
+
var $depth = 0;
|
4748 |
+
var $depth_array = array();
|
4749 |
+
// for getting wsdl
|
4750 |
+
var $proxyhost = '';
|
4751 |
+
var $proxyport = '';
|
4752 |
+
var $proxyusername = '';
|
4753 |
+
var $proxypassword = '';
|
4754 |
+
var $timeout = 0;
|
4755 |
+
var $response_timeout = 30;
|
4756 |
+
var $curl_options = array(); // User-specified cURL options
|
4757 |
+
var $use_curl = false; // whether to always try to use cURL
|
4758 |
+
// for HTTP authentication
|
4759 |
+
var $username = ''; // Username for HTTP authentication
|
4760 |
+
var $password = ''; // Password for HTTP authentication
|
4761 |
+
var $authtype = ''; // Type of HTTP authentication
|
4762 |
+
var $certRequest = array(); // Certificate for HTTP SSL authentication
|
4763 |
+
|
4764 |
+
/**
|
4765 |
+
* constructor
|
4766 |
+
*
|
4767 |
+
* @param string $wsdl WSDL document URL
|
4768 |
+
* @param string $proxyhost
|
4769 |
+
* @param string $proxyport
|
4770 |
+
* @param string $proxyusername
|
4771 |
+
* @param string $proxypassword
|
4772 |
+
* @param integer $timeout set the connection timeout
|
4773 |
+
* @param integer $response_timeout set the response timeout
|
4774 |
+
* @param array $curl_options user-specified cURL options
|
4775 |
+
* @param boolean $use_curl try to use cURL
|
4776 |
+
* @access public
|
4777 |
+
*/
|
4778 |
+
function __construct($wsdl = '', $proxyhost = false, $proxyport = false, $proxyusername = false, $proxypassword = false, $timeout = 0, $response_timeout = 30, $curl_options = null, $use_curl = false)
|
4779 |
+
{
|
4780 |
+
parent::__construct();
|
4781 |
+
$this->debug("ctor wsdl=$wsdl timeout=$timeout response_timeout=$response_timeout");
|
4782 |
+
$this->proxyhost = $proxyhost;
|
4783 |
+
$this->proxyport = $proxyport;
|
4784 |
+
$this->proxyusername = $proxyusername;
|
4785 |
+
$this->proxypassword = $proxypassword;
|
4786 |
+
$this->timeout = $timeout;
|
4787 |
+
$this->response_timeout = $response_timeout;
|
4788 |
+
if (is_array($curl_options)) {
|
4789 |
+
$this->curl_options = $curl_options;
|
4790 |
+
}
|
4791 |
+
$this->use_curl = $use_curl;
|
4792 |
+
$this->fetchWSDL($wsdl);
|
4793 |
+
}
|
4794 |
+
|
4795 |
+
/**
|
4796 |
+
* fetches the WSDL document and parses it
|
4797 |
+
*
|
4798 |
+
* @access public
|
4799 |
+
*/
|
4800 |
+
function fetchWSDL($wsdl)
|
4801 |
+
{
|
4802 |
+
$this->debug("parse and process WSDL path=$wsdl");
|
4803 |
+
$this->wsdl = $wsdl;
|
4804 |
+
// parse wsdl file
|
4805 |
+
if ($this->wsdl != "") {
|
4806 |
+
$this->parseWSDL($this->wsdl);
|
4807 |
+
}
|
4808 |
+
// imports
|
4809 |
+
// TODO: handle imports more properly, grabbing them in-line and nesting them
|
4810 |
+
$imported_urls = array();
|
4811 |
+
$imported = 1;
|
4812 |
+
while ($imported > 0) {
|
4813 |
+
$imported = 0;
|
4814 |
+
// Schema imports
|
4815 |
+
foreach ($this->schemas as $ns => $list) {
|
4816 |
+
foreach ($list as $xs) {
|
4817 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
4818 |
+
foreach ($xs->imports as $ns2 => $list2) {
|
4819 |
+
for ($ii = 0; $ii < count($list2); $ii++) {
|
4820 |
+
if (!$list2[$ii]['loaded']) {
|
4821 |
+
$this->schemas[$ns][$ns2]->imports[$ns2][$ii]['loaded'] = true;
|
4822 |
+
$url = $list2[$ii]['location'];
|
4823 |
+
if ($url != '') {
|
4824 |
+
$urlparts = parse_url($url);
|
4825 |
+
if (!isset($urlparts['host'])) {
|
4826 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
|
4827 |
+
substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
|
4828 |
+
}
|
4829 |
+
if (!in_array($url, $imported_urls)) {
|
4830 |
+
$this->parseWSDL($url);
|
4831 |
+
$imported++;
|
4832 |
+
$imported_urls[] = $url;
|
4833 |
+
}
|
4834 |
+
} else {
|
4835 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
4836 |
+
}
|
4837 |
+
}
|
4838 |
+
}
|
4839 |
+
}
|
4840 |
+
}
|
4841 |
+
}
|
4842 |
+
// WSDL imports
|
4843 |
+
$wsdlparts = parse_url($this->wsdl); // this is bogusly simple!
|
4844 |
+
foreach ($this->import as $ns => $list) {
|
4845 |
+
for ($ii = 0; $ii < count($list); $ii++) {
|
4846 |
+
if (!$list[$ii]['loaded']) {
|
4847 |
+
$this->import[$ns][$ii]['loaded'] = true;
|
4848 |
+
$url = $list[$ii]['location'];
|
4849 |
+
if ($url != '') {
|
4850 |
+
$urlparts = parse_url($url);
|
4851 |
+
if (!isset($urlparts['host'])) {
|
4852 |
+
$url = $wsdlparts['scheme'] . '://' . $wsdlparts['host'] . (isset($wsdlparts['port']) ? ':' . $wsdlparts['port'] : '') .
|
4853 |
+
substr($wsdlparts['path'], 0, strrpos($wsdlparts['path'], '/') + 1) . $urlparts['path'];
|
4854 |
+
}
|
4855 |
+
if (!in_array($url, $imported_urls)) {
|
4856 |
+
$this->parseWSDL($url);
|
4857 |
+
$imported++;
|
4858 |
+
$imported_urls[] = $url;
|
4859 |
+
}
|
4860 |
+
} else {
|
4861 |
+
$this->debug("Unexpected scenario: empty URL for unloaded import");
|
4862 |
+
}
|
4863 |
+
}
|
4864 |
+
}
|
4865 |
+
}
|
4866 |
+
}
|
4867 |
+
// add new data to operation data
|
4868 |
+
foreach ($this->bindings as $binding => $bindingData) {
|
4869 |
+
if (isset($bindingData['operations']) && is_array($bindingData['operations'])) {
|
4870 |
+
foreach ($bindingData['operations'] as $operation => $data) {
|
4871 |
+
$this->debug('post-parse data gathering for ' . $operation);
|
4872 |
+
$this->bindings[$binding]['operations'][$operation]['input'] =
|
4873 |
+
isset($this->bindings[$binding]['operations'][$operation]['input']) ?
|
4874 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['input'], $this->portTypes[$bindingData['portType']][$operation]['input']) :
|
4875 |
+
$this->portTypes[$bindingData['portType']][$operation]['input'];
|
4876 |
+
$this->bindings[$binding]['operations'][$operation]['output'] =
|
4877 |
+
isset($this->bindings[$binding]['operations'][$operation]['output']) ?
|
4878 |
+
array_merge($this->bindings[$binding]['operations'][$operation]['output'], $this->portTypes[$bindingData['portType']][$operation]['output']) :
|
4879 |
+
$this->portTypes[$bindingData['portType']][$operation]['output'];
|
4880 |
+
if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']])) {
|
4881 |
+
$this->bindings[$binding]['operations'][$operation]['input']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['input']['message']];
|
4882 |
+
}
|
4883 |
+
if (isset($this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']])) {
|
4884 |
+
$this->bindings[$binding]['operations'][$operation]['output']['parts'] = $this->messages[$this->bindings[$binding]['operations'][$operation]['output']['message']];
|
4885 |
+
}
|
4886 |
+
// Set operation style if necessary, but do not override one already provided
|
4887 |
+
if (isset($bindingData['style']) && !isset($this->bindings[$binding]['operations'][$operation]['style'])) {
|
4888 |
+
$this->bindings[$binding]['operations'][$operation]['style'] = $bindingData['style'];
|
4889 |
+
}
|
4890 |
+
$this->bindings[$binding]['operations'][$operation]['transport'] = isset($bindingData['transport']) ? $bindingData['transport'] : '';
|
4891 |
+
$this->bindings[$binding]['operations'][$operation]['documentation'] = isset($this->portTypes[$bindingData['portType']][$operation]['documentation']) ? $this->portTypes[$bindingData['portType']][$operation]['documentation'] : '';
|
4892 |
+
$this->bindings[$binding]['operations'][$operation]['endpoint'] = isset($bindingData['endpoint']) ? $bindingData['endpoint'] : '';
|
4893 |
+
}
|
4894 |
+
}
|
4895 |
+
}
|
4896 |
+
}
|
4897 |
+
|
4898 |
+
/**
|
4899 |
+
* parses the wsdl document
|
4900 |
+
*
|
4901 |
+
* @param string $wsdl path or URL
|
4902 |
+
* @access private
|
4903 |
+
*/
|
4904 |
+
function parseWSDL($wsdl = '')
|
4905 |
+
{
|
4906 |
+
$this->debug("parse WSDL at path=$wsdl");
|
4907 |
+
|
4908 |
+
if ($wsdl == '') {
|
4909 |
+
$this->debug('no wsdl passed to parseWSDL()!!');
|
4910 |
+
$this->setError('no wsdl passed to parseWSDL()!!');
|
4911 |
+
return false;
|
4912 |
+
}
|
4913 |
+
|
4914 |
+
// parse $wsdl for url format
|
4915 |
+
$wsdl_props = parse_url($wsdl);
|
4916 |
+
|
4917 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'http' || $wsdl_props['scheme'] == 'https')) {
|
4918 |
+
$this->debug('getting WSDL http(s) URL ' . $wsdl);
|
4919 |
+
// get wsdl
|
4920 |
+
$tr = new soap_transport_http($wsdl, $this->curl_options, $this->use_curl);
|
4921 |
+
$tr->request_method = 'GET';
|
4922 |
+
$tr->useSOAPAction = false;
|
4923 |
+
if ($this->proxyhost && $this->proxyport) {
|
4924 |
+
$tr->setProxy($this->proxyhost, $this->proxyport, $this->proxyusername, $this->proxypassword);
|
4925 |
+
}
|
4926 |
+
if ($this->authtype != '') {
|
4927 |
+
$tr->setCredentials($this->username, $this->password, $this->authtype, array(), $this->certRequest);
|
4928 |
+
}
|
4929 |
+
$tr->setEncoding('gzip, deflate');
|
4930 |
+
$wsdl_string = $tr->send('', $this->timeout, $this->response_timeout);
|
4931 |
+
//$this->debug("WSDL request\n" . $tr->outgoing_payload);
|
4932 |
+
//$this->debug("WSDL response\n" . $tr->incoming_payload);
|
4933 |
+
$this->appendDebug($tr->getDebug());
|
4934 |
+
// catch errors
|
4935 |
+
if ($err = $tr->getError()) {
|
4936 |
+
$errstr = 'Getting ' . $wsdl . ' - HTTP ERROR: ' . $err;
|
4937 |
+
$this->debug($errstr);
|
4938 |
+
$this->setError($errstr);
|
4939 |
+
unset($tr);
|
4940 |
+
return false;
|
4941 |
+
}
|
4942 |
+
unset($tr);
|
4943 |
+
$this->debug("got WSDL URL");
|
4944 |
+
} else {
|
4945 |
+
// $wsdl is not http(s), so treat it as a file URL or plain file path
|
4946 |
+
if (isset($wsdl_props['scheme']) && ($wsdl_props['scheme'] == 'file') && isset($wsdl_props['path'])) {
|
4947 |
+
$path = isset($wsdl_props['host']) ? ($wsdl_props['host'] . ':' . $wsdl_props['path']) : $wsdl_props['path'];
|
4948 |
+
} else {
|
4949 |
+
$path = $wsdl;
|
4950 |
+
}
|
4951 |
+
$this->debug('getting WSDL file ' . $path);
|
4952 |
+
if ($fp = @fopen($path, 'r')) {
|
4953 |
+
$wsdl_string = '';
|
4954 |
+
while ($data = fread($fp, 32768)) {
|
4955 |
+
$wsdl_string .= $data;
|
4956 |
+
}
|
4957 |
+
fclose($fp);
|
4958 |
+
} else {
|
4959 |
+
$errstr = "Bad path to WSDL file $path";
|
4960 |
+
$this->debug($errstr);
|
4961 |
+
$this->setError($errstr);
|
4962 |
+
return false;
|
4963 |
+
}
|
4964 |
+
}
|
4965 |
+
$this->debug('Parse WSDL');
|
4966 |
+
// end new code added
|
4967 |
+
// Create an XML parser.
|
4968 |
+
$this->parser = xml_parser_create();
|
4969 |
+
// Set the options for parsing the XML data.
|
4970 |
+
// xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
4971 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
4972 |
+
// Set the object for the parser.
|
4973 |
+
xml_set_object($this->parser, $this);
|
4974 |
+
// Set the element handlers for the parser.
|
4975 |
+
xml_set_element_handler($this->parser, 'start_element', 'end_element');
|
4976 |
+
xml_set_character_data_handler($this->parser, 'character_data');
|
4977 |
+
// Parse the XML file.
|
4978 |
+
if (!xml_parse($this->parser, $wsdl_string, true)) {
|
4979 |
+
// Display an error message.
|
4980 |
+
$errstr = sprintf(
|
4981 |
+
'XML error parsing WSDL from %s on line %d: %s',
|
4982 |
+
$wsdl,
|
4983 |
+
xml_get_current_line_number($this->parser),
|
4984 |
+
xml_error_string(xml_get_error_code($this->parser))
|
4985 |
+
);
|
4986 |
+
$this->debug($errstr);
|
4987 |
+
$this->debug("XML payload:\n" . $wsdl_string);
|
4988 |
+
$this->setError($errstr);
|
4989 |
+
xml_parser_free($this->parser);
|
4990 |
+
unset($this->parser);
|
4991 |
+
return false;
|
4992 |
+
}
|
4993 |
+
// free the parser
|
4994 |
+
xml_parser_free($this->parser);
|
4995 |
+
unset($this->parser);
|
4996 |
+
$this->debug('Parsing WSDL done');
|
4997 |
+
// catch wsdl parse errors
|
4998 |
+
if ($this->getError()) {
|
4999 |
+
return false;
|
5000 |
+
}
|
5001 |
+
return true;
|
5002 |
+
}
|
5003 |
+
|
5004 |
+
/**
|
5005 |
+
* start-element handler
|
5006 |
+
*
|
5007 |
+
* @param string $parser XML parser object
|
5008 |
+
* @param string $name element name
|
5009 |
+
* @param string $attrs associative array of attributes
|
5010 |
+
* @access private
|
5011 |
+
*/
|
5012 |
+
function start_element($parser, $name, $attrs)
|
5013 |
+
{
|
5014 |
+
if ($this->status == 'schema') {
|
5015 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
5016 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
5017 |
+
$this->currentSchema->clearDebug();
|
5018 |
+
} elseif (preg_match('/schema$/', $name)) {
|
5019 |
+
$this->debug('Parsing WSDL schema');
|
5020 |
+
// $this->debug("startElement for $name ($attrs[name]). status = $this->status (".$this->getLocalPart($name).")");
|
5021 |
+
$this->status = 'schema';
|
5022 |
+
$this->currentSchema = new nusoap_xmlschema('', '', $this->namespaces);
|
5023 |
+
$this->currentSchema->schemaStartElement($parser, $name, $attrs);
|
5024 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
5025 |
+
$this->currentSchema->clearDebug();
|
5026 |
+
} else {
|
5027 |
+
// position in the total number of elements, starting from 0
|
5028 |
+
$pos = $this->position++;
|
5029 |
+
$depth = $this->depth++;
|
5030 |
+
// set self as current value for this depth
|
5031 |
+
$this->depth_array[$depth] = $pos;
|
5032 |
+
$this->message[$pos] = array('cdata' => '');
|
5033 |
+
// process attributes
|
5034 |
+
if (count($attrs) > 0) {
|
5035 |
+
// register namespace declarations
|
5036 |
+
foreach ($attrs as $k => $v) {
|
5037 |
+
if (preg_match('/^xmlns/', $k)) {
|
5038 |
+
if ($ns_prefix = substr(strrchr($k, ':'), 1)) {
|
5039 |
+
$this->namespaces[$ns_prefix] = $v;
|
5040 |
+
} else {
|
5041 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $v;
|
5042 |
+
}
|
5043 |
+
if ($v == 'http://www.w3.org/2001/XMLSchema' || $v == 'http://www.w3.org/1999/XMLSchema' || $v == 'http://www.w3.org/2000/10/XMLSchema') {
|
5044 |
+
$this->XMLSchemaVersion = $v;
|
5045 |
+
$this->namespaces['xsi'] = $v . '-instance';
|
5046 |
+
}
|
5047 |
+
}
|
5048 |
+
}
|
5049 |
+
// expand each attribute prefix to its namespace
|
5050 |
+
foreach ($attrs as $k => $v) {
|
5051 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
5052 |
+
if ($k != 'location' && $k != 'soapAction' && $k != 'namespace') {
|
5053 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
5054 |
+
}
|
5055 |
+
$eAttrs[$k] = $v;
|
5056 |
+
}
|
5057 |
+
$attrs = $eAttrs;
|
5058 |
+
} else {
|
5059 |
+
$attrs = array();
|
5060 |
+
}
|
5061 |
+
// get element prefix, namespace and name
|
5062 |
+
if (preg_match('/:/', $name)) {
|
5063 |
+
// get ns prefix
|
5064 |
+
$prefix = substr($name, 0, strpos($name, ':'));
|
5065 |
+
// get ns
|
5066 |
+
$namespace = isset($this->namespaces[$prefix]) ? $this->namespaces[$prefix] : '';
|
5067 |
+
// get unqualified name
|
5068 |
+
$name = substr(strstr($name, ':'), 1);
|
5069 |
+
}
|
5070 |
+
// process attributes, expanding any prefixes to namespaces
|
5071 |
+
// find status, register data
|
5072 |
+
switch ($this->status) {
|
5073 |
+
case 'message':
|
5074 |
+
if ($name == 'part') {
|
5075 |
+
if (isset($attrs['type'])) {
|
5076 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with type) $attrs[name]: " . implode(',', $attrs));
|
5077 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['type'];
|
5078 |
+
}
|
5079 |
+
if (isset($attrs['element'])) {
|
5080 |
+
$this->debug("msg " . $this->currentMessage . ": found part (with element) $attrs[name]: " . implode(',', $attrs));
|
5081 |
+
$this->messages[$this->currentMessage][$attrs['name']] = $attrs['element'] . '^';
|
5082 |
+
}
|
5083 |
+
}
|
5084 |
+
break;
|
5085 |
+
case 'portType':
|
5086 |
+
switch ($name) {
|
5087 |
+
case 'operation':
|
5088 |
+
$this->currentPortOperation = $attrs['name'];
|
5089 |
+
$this->debug("portType $this->currentPortType operation: $this->currentPortOperation");
|
5090 |
+
if (isset($attrs['parameterOrder'])) {
|
5091 |
+
$this->portTypes[$this->currentPortType][$attrs['name']]['parameterOrder'] = $attrs['parameterOrder'];
|
5092 |
+
}
|
5093 |
+
break;
|
5094 |
+
case 'documentation':
|
5095 |
+
$this->documentation = true;
|
5096 |
+
break;
|
5097 |
+
// merge input/output data
|
5098 |
+
default:
|
5099 |
+
$m = isset($attrs['message']) ? $this->getLocalPart($attrs['message']) : '';
|
5100 |
+
$this->portTypes[$this->currentPortType][$this->currentPortOperation][$name]['message'] = $m;
|
5101 |
+
break;
|
5102 |
+
}
|
5103 |
+
break;
|
5104 |
+
case 'binding':
|
5105 |
+
switch ($name) {
|
5106 |
+
case 'binding':
|
5107 |
+
// get ns prefix
|
5108 |
+
if (isset($attrs['style'])) {
|
5109 |
+
$this->bindings[$this->currentBinding]['prefix'] = $prefix;
|
5110 |
+
}
|
5111 |
+
$this->bindings[$this->currentBinding] = array_merge($this->bindings[$this->currentBinding], $attrs);
|
5112 |
+
break;
|
5113 |
+
case 'header':
|
5114 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus]['headers'][] = $attrs;
|
5115 |
+
break;
|
5116 |
+
case 'operation':
|
5117 |
+
if (isset($attrs['soapAction'])) {
|
5118 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['soapAction'] = $attrs['soapAction'];
|
5119 |
+
}
|
5120 |
+
if (isset($attrs['style'])) {
|
5121 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['style'] = $attrs['style'];
|
5122 |
+
}
|
5123 |
+
if (isset($attrs['name'])) {
|
5124 |
+
$this->currentOperation = $attrs['name'];
|
5125 |
+
$this->debug("current binding operation: $this->currentOperation");
|
5126 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['name'] = $attrs['name'];
|
5127 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['binding'] = $this->currentBinding;
|
5128 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation]['endpoint'] = isset($this->bindings[$this->currentBinding]['endpoint']) ? $this->bindings[$this->currentBinding]['endpoint'] : '';
|
5129 |
+
}
|
5130 |
+
break;
|
5131 |
+
case 'input':
|
5132 |
+
$this->opStatus = 'input';
|
5133 |
+
break;
|
5134 |
+
case 'output':
|
5135 |
+
$this->opStatus = 'output';
|
5136 |
+
break;
|
5137 |
+
case 'body':
|
5138 |
+
if (isset($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus])) {
|
5139 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = array_merge($this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus], $attrs);
|
5140 |
+
} else {
|
5141 |
+
$this->bindings[$this->currentBinding]['operations'][$this->currentOperation][$this->opStatus] = $attrs;
|
5142 |
+
}
|
5143 |
+
break;
|
5144 |
+
}
|
5145 |
+
break;
|
5146 |
+
case 'service':
|
5147 |
+
switch ($name) {
|
5148 |
+
case 'port':
|
5149 |
+
$this->currentPort = $attrs['name'];
|
5150 |
+
$this->debug('current port: ' . $this->currentPort);
|
5151 |
+
$this->ports[$this->currentPort]['binding'] = $this->getLocalPart($attrs['binding']);
|
5152 |
+
|
5153 |
+
break;
|
5154 |
+
case 'address':
|
5155 |
+
$this->ports[$this->currentPort]['location'] = $attrs['location'];
|
5156 |
+
$this->ports[$this->currentPort]['bindingType'] = $namespace;
|
5157 |
+
$this->bindings[$this->ports[$this->currentPort]['binding']]['bindingType'] = $namespace;
|
5158 |
+
$this->bindings[$this->ports[$this->currentPort]['binding']]['endpoint'] = $attrs['location'];
|
5159 |
+
break;
|
5160 |
+
}
|
5161 |
+
break;
|
5162 |
+
}
|
5163 |
+
// set status
|
5164 |
+
switch ($name) {
|
5165 |
+
case 'import':
|
5166 |
+
if (isset($attrs['location'])) {
|
5167 |
+
$this->import[$attrs['namespace']][] = array('location' => $attrs['location'], 'loaded' => false);
|
5168 |
+
$this->debug('parsing import ' . $attrs['namespace'] . ' - ' . $attrs['location'] . ' (' . count($this->import[$attrs['namespace']]) . ')');
|
5169 |
+
} else {
|
5170 |
+
$this->import[$attrs['namespace']][] = array('location' => '', 'loaded' => true);
|
5171 |
+
if (!$this->getPrefixFromNamespace($attrs['namespace'])) {
|
5172 |
+
$this->namespaces['ns' . (count($this->namespaces) + 1)] = $attrs['namespace'];
|
5173 |
+
}
|
5174 |
+
$this->debug('parsing import ' . $attrs['namespace'] . ' - [no location] (' . count($this->import[$attrs['namespace']]) . ')');
|
5175 |
+
}
|
5176 |
+
break;
|
5177 |
+
//wait for schema
|
5178 |
+
//case 'types':
|
5179 |
+
// $this->status = 'schema';
|
5180 |
+
// break;
|
5181 |
+
case 'message':
|
5182 |
+
$this->status = 'message';
|
5183 |
+
$this->messages[$attrs['name']] = array();
|
5184 |
+
$this->currentMessage = $attrs['name'];
|
5185 |
+
break;
|
5186 |
+
case 'portType':
|
5187 |
+
$this->status = 'portType';
|
5188 |
+
$this->portTypes[$attrs['name']] = array();
|
5189 |
+
$this->currentPortType = $attrs['name'];
|
5190 |
+
break;
|
5191 |
+
case "binding":
|
5192 |
+
if (isset($attrs['name'])) {
|
5193 |
+
// get binding name
|
5194 |
+
if (strpos($attrs['name'], ':')) {
|
5195 |
+
$this->currentBinding = $this->getLocalPart($attrs['name']);
|
5196 |
+
} else {
|
5197 |
+
$this->currentBinding = $attrs['name'];
|
5198 |
+
}
|
5199 |
+
$this->status = 'binding';
|
5200 |
+
$this->bindings[$this->currentBinding]['portType'] = $this->getLocalPart($attrs['type']);
|
5201 |
+
$this->debug("current binding: $this->currentBinding of portType: " . $attrs['type']);
|
5202 |
+
}
|
5203 |
+
break;
|
5204 |
+
case 'service':
|
5205 |
+
$this->serviceName = $attrs['name'];
|
5206 |
+
$this->status = 'service';
|
5207 |
+
$this->debug('current service: ' . $this->serviceName);
|
5208 |
+
break;
|
5209 |
+
case 'definitions':
|
5210 |
+
foreach ($attrs as $name => $value) {
|
5211 |
+
$this->wsdl_info[$name] = $value;
|
5212 |
+
}
|
5213 |
+
break;
|
5214 |
+
}
|
5215 |
+
}
|
5216 |
+
}
|
5217 |
+
|
5218 |
+
/**
|
5219 |
+
* end-element handler
|
5220 |
+
*
|
5221 |
+
* @param string $parser XML parser object
|
5222 |
+
* @param string $name element name
|
5223 |
+
* @access private
|
5224 |
+
*/
|
5225 |
+
function end_element($parser, $name)
|
5226 |
+
{
|
5227 |
+
// unset schema status
|
5228 |
+
if (/*preg_match('/types$/', $name) ||*/
|
5229 |
+
preg_match('/schema$/', $name)
|
5230 |
+
) {
|
5231 |
+
$this->status = "";
|
5232 |
+
$this->appendDebug($this->currentSchema->getDebug());
|
5233 |
+
$this->currentSchema->clearDebug();
|
5234 |
+
$this->schemas[$this->currentSchema->schemaTargetNamespace][] = $this->currentSchema;
|
5235 |
+
$this->debug('Parsing WSDL schema done');
|
5236 |
+
}
|
5237 |
+
if ($this->status == 'schema') {
|
5238 |
+
$this->currentSchema->schemaEndElement($parser, $name);
|
5239 |
+
} else {
|
5240 |
+
// bring depth down a notch
|
5241 |
+
$this->depth--;
|
5242 |
+
}
|
5243 |
+
// end documentation
|
5244 |
+
if ($this->documentation) {
|
5245 |
+
//TODO: track the node to which documentation should be assigned; it can be a part, message, etc.
|
5246 |
+
//$this->portTypes[$this->currentPortType][$this->currentPortOperation]['documentation'] = $this->documentation;
|
5247 |
+
$this->documentation = false;
|
5248 |
+
}
|
5249 |
+
}
|
5250 |
+
|
5251 |
+
/**
|
5252 |
+
* element content handler
|
5253 |
+
*
|
5254 |
+
* @param string $parser XML parser object
|
5255 |
+
* @param string $data element content
|
5256 |
+
* @access private
|
5257 |
+
*/
|
5258 |
+
function character_data($parser, $data)
|
5259 |
+
{
|
5260 |
+
$pos = isset($this->depth_array[$this->depth]) ? $this->depth_array[$this->depth] : 0;
|
5261 |
+
if (isset($this->message[$pos]['cdata'])) {
|
5262 |
+
$this->message[$pos]['cdata'] .= $data;
|
5263 |
+
}
|
5264 |
+
if ($this->documentation) {
|
5265 |
+
$this->documentation .= $data;
|
5266 |
+
}
|
5267 |
+
}
|
5268 |
+
|
5269 |
+
/**
|
5270 |
+
* if authenticating, set user credentials here
|
5271 |
+
*
|
5272 |
+
* @param string $username
|
5273 |
+
* @param string $password
|
5274 |
+
* @param string $authtype (basic|digest|certificate|ntlm)
|
5275 |
+
* @param array $certRequest (keys must be cainfofile (optional), sslcertfile, sslkeyfile, passphrase, certpassword (optional), verifypeer (optional), verifyhost (optional): see corresponding options in cURL docs)
|
5276 |
+
* @access public
|
5277 |
+
*/
|
5278 |
+
function setCredentials($username, $password, $authtype = 'basic', $certRequest = array())
|
5279 |
+
{
|
5280 |
+
$this->debug("setCredentials username=$username authtype=$authtype certRequest=");
|
5281 |
+
$this->appendDebug($this->varDump($certRequest));
|
5282 |
+
$this->username = $username;
|
5283 |
+
$this->password = $password;
|
5284 |
+
$this->authtype = $authtype;
|
5285 |
+
$this->certRequest = $certRequest;
|
5286 |
+
}
|
5287 |
+
|
5288 |
+
function getBindingData($binding)
|
5289 |
+
{
|
5290 |
+
if (is_array($this->bindings[$binding])) {
|
5291 |
+
return $this->bindings[$binding];
|
5292 |
+
}
|
5293 |
+
}
|
5294 |
+
|
5295 |
+
/**
|
5296 |
+
* returns an assoc array of operation names => operation data
|
5297 |
+
*
|
5298 |
+
* @param string $portName WSDL port name
|
5299 |
+
* @param string $bindingType eg: soap, smtp, dime (only soap and soap12 are currently supported)
|
5300 |
+
* @return array
|
5301 |
+
* @access public
|
5302 |
+
*/
|
5303 |
+
function getOperations($portName = '', $bindingType = 'soap')
|
5304 |
+
{
|
5305 |
+
$ops = array();
|
5306 |
+
if ($bindingType == 'soap') {
|
5307 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5308 |
+
} elseif ($bindingType == 'soap12') {
|
5309 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5310 |
+
} else {
|
5311 |
+
$this->debug("getOperations bindingType $bindingType may not be supported");
|
5312 |
+
}
|
5313 |
+
$this->debug("getOperations for port '$portName' bindingType $bindingType");
|
5314 |
+
// loop thru ports
|
5315 |
+
foreach ($this->ports as $port => $portData) {
|
5316 |
+
$this->debug("getOperations checking port $port bindingType " . $portData['bindingType']);
|
5317 |
+
if ($portName == '' || $port == $portName) {
|
5318 |
+
// binding type of port matches parameter
|
5319 |
+
if ($portData['bindingType'] == $bindingType) {
|
5320 |
+
$this->debug("getOperations found port $port bindingType $bindingType");
|
5321 |
+
//$this->debug("port data: " . $this->varDump($portData));
|
5322 |
+
//$this->debug("bindings: " . $this->varDump($this->bindings[ $portData['binding'] ]));
|
5323 |
+
// merge bindings
|
5324 |
+
if (isset($this->bindings[$portData['binding']]['operations'])) {
|
5325 |
+
$ops = array_merge($ops, $this->bindings[$portData['binding']]['operations']);
|
5326 |
+
}
|
5327 |
+
}
|
5328 |
+
}
|
5329 |
+
}
|
5330 |
+
if (count($ops) == 0) {
|
5331 |
+
$this->debug("getOperations found no operations for port '$portName' bindingType $bindingType");
|
5332 |
+
}
|
5333 |
+
return $ops;
|
5334 |
+
}
|
5335 |
+
|
5336 |
+
/**
|
5337 |
+
* returns an associative array of data necessary for calling an operation
|
5338 |
+
*
|
5339 |
+
* @param string $operation name of operation
|
5340 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5341 |
+
* @return array
|
5342 |
+
* @access public
|
5343 |
+
*/
|
5344 |
+
function getOperationData($operation, $bindingType = 'soap')
|
5345 |
+
{
|
5346 |
+
if ($bindingType == 'soap') {
|
5347 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5348 |
+
} elseif ($bindingType == 'soap12') {
|
5349 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5350 |
+
}
|
5351 |
+
// loop thru ports
|
5352 |
+
foreach ($this->ports as $port => $portData) {
|
5353 |
+
// binding type of port matches parameter
|
5354 |
+
if ($portData['bindingType'] == $bindingType) {
|
5355 |
+
// get binding
|
5356 |
+
//foreach($this->bindings[ $portData['binding'] ]['operations'] as $bOperation => $opData) {
|
5357 |
+
foreach (array_keys($this->bindings[$portData['binding']]['operations']) as $bOperation) {
|
5358 |
+
// note that we could/should also check the namespace here
|
5359 |
+
if ($operation == $bOperation) {
|
5360 |
+
$opData = $this->bindings[$portData['binding']]['operations'][$operation];
|
5361 |
+
return $opData;
|
5362 |
+
}
|
5363 |
+
}
|
5364 |
+
}
|
5365 |
+
}
|
5366 |
+
}
|
5367 |
+
|
5368 |
+
/**
|
5369 |
+
* returns an associative array of data necessary for calling an operation
|
5370 |
+
*
|
5371 |
+
* @param string $soapAction soapAction for operation
|
5372 |
+
* @param string $bindingType type of binding eg: soap, soap12
|
5373 |
+
* @return array
|
5374 |
+
* @access public
|
5375 |
+
*/
|
5376 |
+
function getOperationDataForSoapAction($soapAction, $bindingType = 'soap')
|
5377 |
+
{
|
5378 |
+
if ($bindingType == 'soap') {
|
5379 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap/';
|
5380 |
+
} elseif ($bindingType == 'soap12') {
|
5381 |
+
$bindingType = 'http://schemas.xmlsoap.org/wsdl/soap12/';
|
5382 |
+
}
|
5383 |
+
// loop thru ports
|
5384 |
+
foreach ($this->ports as $port => $portData) {
|
5385 |
+
// binding type of port matches parameter
|
5386 |
+
if ($portData['bindingType'] == $bindingType) {
|
5387 |
+
// loop through operations for the binding
|
5388 |
+
foreach ($this->bindings[$portData['binding']]['operations'] as $bOperation => $opData) {
|
5389 |
+
if ($opData['soapAction'] == $soapAction) {
|
5390 |
+
return $opData;
|
5391 |
+
}
|
5392 |
+
}
|
5393 |
+
}
|
5394 |
+
}
|
5395 |
+
}
|
5396 |
+
|
5397 |
+
/**
|
5398 |
+
* returns an array of information about a given type
|
5399 |
+
* returns false if no type exists by the given name
|
5400 |
+
*
|
5401 |
+
* typeDef = array(
|
5402 |
+
* 'elements' => array(), // refs to elements array
|
5403 |
+
* 'restrictionBase' => '',
|
5404 |
+
* 'phpType' => '',
|
5405 |
+
* 'order' => '(sequence|all)',
|
5406 |
+
* 'attrs' => array() // refs to attributes array
|
5407 |
+
* )
|
5408 |
+
*
|
5409 |
+
* @param string $type the type
|
5410 |
+
* @param string $ns namespace (not prefix) of the type
|
5411 |
+
* @return mixed
|
5412 |
+
* @access public
|
5413 |
+
* @see nusoap_xmlschema
|
5414 |
+
*/
|
5415 |
+
function getTypeDef($type, $ns)
|
5416 |
+
{
|
5417 |
+
$this->debug("in getTypeDef: type=$type, ns=$ns");
|
5418 |
+
if ((!$ns) && isset($this->namespaces['tns'])) {
|
5419 |
+
$ns = $this->namespaces['tns'];
|
5420 |
+
$this->debug("in getTypeDef: type namespace forced to $ns");
|
5421 |
+
}
|
5422 |
+
if (!isset($this->schemas[$ns])) {
|
5423 |
+
foreach ($this->schemas as $ns0 => $schema0) {
|
5424 |
+
if (strcasecmp($ns, $ns0) == 0) {
|
5425 |
+
$this->debug("in getTypeDef: replacing schema namespace $ns with $ns0");
|
5426 |
+
$ns = $ns0;
|
5427 |
+
break;
|
5428 |
+
}
|
5429 |
+
}
|
5430 |
+
}
|
5431 |
+
if (isset($this->schemas[$ns])) {
|
5432 |
+
$this->debug("in getTypeDef: have schema for namespace $ns");
|
5433 |
+
for ($i = 0; $i < count($this->schemas[$ns]); $i++) {
|
5434 |
+
$xs = &$this->schemas[$ns][$i];
|
5435 |
+
$t = $xs->getTypeDef($type);
|
5436 |
+
$this->appendDebug($xs->getDebug());
|
5437 |
+
$xs->clearDebug();
|
5438 |
+
if ($t) {
|
5439 |
+
$this->debug("in getTypeDef: found type $type");
|
5440 |
+
if (!isset($t['phpType'])) {
|
5441 |
+
// get info for type to tack onto the element
|
5442 |
+
$uqType = substr($t['type'], strrpos($t['type'], ':') + 1);
|
5443 |
+
$ns = substr($t['type'], 0, strrpos($t['type'], ':'));
|
5444 |
+
$etype = $this->getTypeDef($uqType, $ns);
|
5445 |
+
if ($etype) {
|
5446 |
+
$this->debug("found type for [element] $type:");
|
5447 |
+
$this->debug($this->varDump($etype));
|
5448 |
+
if (isset($etype['phpType'])) {
|
5449 |
+
$t['phpType'] = $etype['phpType'];
|
5450 |
+
}
|
5451 |
+
if (isset($etype['elements'])) {
|
5452 |
+
$t['elements'] = $etype['elements'];
|
5453 |
+
}
|
5454 |
+
if (isset($etype['attrs'])) {
|
5455 |
+
$t['attrs'] = $etype['attrs'];
|
5456 |
+
}
|
5457 |
+
} else {
|
5458 |
+
$this->debug("did not find type for [element] $type");
|
5459 |
+
}
|
5460 |
+
}
|
5461 |
+
return $t;
|
5462 |
+
}
|
5463 |
+
}
|
5464 |
+
$this->debug("in getTypeDef: did not find type $type");
|
5465 |
+
} else {
|
5466 |
+
$this->debug("in getTypeDef: do not have schema for namespace $ns");
|
5467 |
+
}
|
5468 |
+
return false;
|
5469 |
+
}
|
5470 |
+
|
5471 |
+
/**
|
5472 |
+
* prints html description of services
|
5473 |
+
*
|
5474 |
+
* @access private
|
5475 |
+
*/
|
5476 |
+
function webDescription()
|
5477 |
+
{
|
5478 |
+
global $HTTP_SERVER_VARS;
|
5479 |
+
|
5480 |
+
if (isset($_SERVER)) {
|
5481 |
+
$PHP_SELF = $_SERVER['PHP_SELF'];
|
5482 |
+
} elseif (isset($HTTP_SERVER_VARS)) {
|
5483 |
+
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
|
5484 |
+
} else {
|
5485 |
+
$this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
|
5486 |
+
}
|
5487 |
+
|
5488 |
+
$b = '
|
5489 |
+
<html><head><title>NuSOAP: ' . $this->serviceName . '</title>
|
5490 |
+
<style type="text/css">
|
5491 |
+
body { font-family: arial; color: #000000; background-color: #ffffff; margin: 0px 0px 0px 0px; }
|
5492 |
+
p { font-family: arial; color: #000000; margin-top: 0px; margin-bottom: 12px; }
|
5493 |
+
pre { background-color: silver; padding: 5px; font-family: Courier New; font-size: x-small; color: #000000;}
|
5494 |
+
ul { margin-top: 10px; margin-left: 20px; }
|
5495 |
+
li { list-style-type: none; margin-top: 10px; color: #000000; }
|
5496 |
+
.content{
|
5497 |
+
margin-left: 0px; padding-bottom: 2em; }
|
5498 |
+
.nav {
|
5499 |
+
padding-top: 10px; padding-bottom: 10px; padding-left: 15px; font-size: .70em;
|
5500 |
+
margin-top: 10px; margin-left: 0px; color: #000000;
|
5501 |
+
background-color: #ccccff; width: 20%; margin-left: 20px; margin-top: 20px; }
|
5502 |
+
.title {
|
5503 |
+
font-family: arial; font-size: 26px; color: #ffffff;
|
5504 |
+
background-color: #999999; width: 100%;
|
5505 |
+
margin-left: 0px; margin-right: 0px;
|
5506 |
+
padding-top: 10px; padding-bottom: 10px;}
|
5507 |
+
.hidden {
|
5508 |
+
position: absolute; visibility: hidden; z-index: 200; left: 250px; top: 100px;
|
5509 |
+
font-family: arial; overflow: hidden; width: 600;
|
5510 |
+
padding: 20px; font-size: 10px; background-color: #999999;
|
5511 |
+
layer-background-color:#FFFFFF; }
|
5512 |
+
a,a:active { color: charcoal; font-weight: bold; }
|
5513 |
+
a:visited { color: #666666; font-weight: bold; }
|
5514 |
+
a:hover { color: cc3300; font-weight: bold; }
|
5515 |
+
</style>
|
5516 |
+
<script language="JavaScript" type="text/javascript">
|
5517 |
+
<!--
|
5518 |
+
// POP-UP CAPTIONS...
|
5519 |
+
function lib_bwcheck(){ //Browsercheck (needed)
|
5520 |
+
this.ver=navigator.appVersion
|
5521 |
+
this.agent=navigator.userAgent
|
5522 |
+
this.dom=document.getElementById?1:0
|
5523 |
+
this.opera5=this.agent.indexOf("Opera 5")>-1
|
5524 |
+
this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0;
|
5525 |
+
this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
|
5526 |
+
this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
|
5527 |
+
this.ie=this.ie4||this.ie5||this.ie6
|
5528 |
+
this.mac=this.agent.indexOf("Mac")>-1
|
5529 |
+
this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0;
|
5530 |
+
this.ns4=(document.layers && !this.dom)?1:0;
|
5531 |
+
this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)
|
5532 |
+
return this
|
5533 |
+
}
|
5534 |
+
var bw = new lib_bwcheck()
|
5535 |
+
//Makes crossbrowser object.
|
5536 |
+
function makeObj(obj){
|
5537 |
+
this.evnt=bw.dom? document.getElementById(obj):bw.ie4?document.all[obj]:bw.ns4?document.layers[obj]:0;
|
5538 |
+
if(!this.evnt) return false
|
5539 |
+
this.css=bw.dom||bw.ie4?this.evnt.style:bw.ns4?this.evnt:0;
|
5540 |
+
this.wref=bw.dom||bw.ie4?this.evnt:bw.ns4?this.css.document:0;
|
5541 |
+
this.writeIt=b_writeIt;
|
5542 |
+
return this
|
5543 |
+
}
|
5544 |
+
// A unit of measure that will be added when setting the position of a layer.
|
5545 |
+
//var px = bw.ns4||window.opera?"":"px";
|
5546 |
+
function b_writeIt(text){
|
5547 |
+
if (bw.ns4){this.wref.write(text);this.wref.close()}
|
5548 |
+
else this.wref.innerHTML = text
|
5549 |
+
}
|
5550 |
+
//Shows the messages
|
5551 |
+
var oDesc;
|
5552 |
+
function popup(divid){
|
5553 |
+
if(oDesc = new makeObj(divid)){
|
5554 |
+
oDesc.css.visibility = "visible"
|
5555 |
+
}
|
5556 |
+
}
|
5557 |
+
function popout(){ // Hides message
|
5558 |
+
if(oDesc) oDesc.css.visibility = "hidden"
|
5559 |
+
}
|
5560 |
+
//-->
|
5561 |
+
</script>
|
5562 |
+
</head>
|
5563 |
+
<body>
|
5564 |
+
<div class=content>
|
5565 |
+
<br><br>
|
5566 |
+
<div class=title>' . $this->serviceName . '</div>
|
5567 |
+
<div class=nav>
|
5568 |
+
<p>View the <a href="' . $PHP_SELF . '?wsdl">WSDL</a> for the service.
|
5569 |
+
Click on an operation name to view it's details.</p>
|
5570 |
+
<ul>';
|
5571 |
+
foreach ($this->getOperations() as $op => $data) {
|
5572 |
+
$b .= "<li><a href='#' onclick=\"popout();popup('$op')\">$op</a></li>";
|
5573 |
+
// create hidden div
|
5574 |
+
$b .= "<div id='$op' class='hidden'>
|
5575 |
+
<a href='#' onclick='popout()'><font color='#ffffff'>Close</font></a><br><br>";
|
5576 |
+
foreach ($data as $donnie => $marie) { // loop through opdata
|
5577 |
+
if ($donnie == 'input' || $donnie == 'output') { // show input/output data
|
5578 |
+
$b .= "<font color='white'>" . ucfirst($donnie) . ':</font><br>';
|
5579 |
+
foreach ($marie as $captain => $tenille) { // loop through data
|
5580 |
+
if ($captain == 'parts') { // loop thru parts
|
5581 |
+
$b .= " $captain:<br>";
|
5582 |
+
//if(is_array($tenille)){
|
5583 |
+
foreach ($tenille as $joanie => $chachi) {
|
5584 |
+
$b .= " $joanie: $chachi<br>";
|
5585 |
+
}
|
5586 |
+
//}
|
5587 |
+
} else {
|
5588 |
+
$b .= " $captain: $tenille<br>";
|
5589 |
+
}
|
5590 |
+
}
|
5591 |
+
} else {
|
5592 |
+
$b .= "<font color='white'>" . ucfirst($donnie) . ":</font> $marie<br>";
|
5593 |
+
}
|
5594 |
+
}
|
5595 |
+
$b .= '</div>';
|
5596 |
+
}
|
5597 |
+
$b .= '
|
5598 |
+
<ul>
|
5599 |
+
</div>
|
5600 |
+
</div></body></html>';
|
5601 |
+
return $b;
|
5602 |
+
}
|
5603 |
+
|
5604 |
+
/**
|
5605 |
+
* serialize the parsed wsdl
|
5606 |
+
*
|
5607 |
+
* @param mixed $debug whether to put debug=1 in endpoint URL
|
5608 |
+
* @return string serialization of WSDL
|
5609 |
+
* @access public
|
5610 |
+
*/
|
5611 |
+
function serialize($debug = 0)
|
5612 |
+
{
|
5613 |
+
$xml = '<?xml version="1.0" encoding="ISO-8859-1"?>';
|
5614 |
+
$xml .= "\n<definitions";
|
5615 |
+
foreach ($this->namespaces as $k => $v) {
|
5616 |
+
$xml .= " xmlns:$k=\"$v\"";
|
5617 |
+
}
|
5618 |
+
// 10.9.02 - add poulter fix for wsdl and tns declarations
|
5619 |
+
if (isset($this->namespaces['wsdl'])) {
|
5620 |
+
$xml .= " xmlns=\"" . $this->namespaces['wsdl'] . "\"";
|
5621 |
+
}
|
5622 |
+
if (isset($this->namespaces['tns'])) {
|
5623 |
+
$xml .= " targetNamespace=\"" . $this->namespaces['tns'] . "\"";
|
5624 |
+
}
|
5625 |
+
$xml .= '>';
|
5626 |
+
// imports
|
5627 |
+
if (sizeof($this->import) > 0) {
|
5628 |
+
foreach ($this->import as $ns => $list) {
|
5629 |
+
foreach ($list as $ii) {
|
5630 |
+
if ($ii['location'] != '') {
|
5631 |
+
$xml .= '<import location="' . $ii['location'] . '" namespace="' . $ns . '" />';
|
5632 |
+
} else {
|
5633 |
+
$xml .= '<import namespace="' . $ns . '" />';
|
5634 |
+
}
|
5635 |
+
}
|
5636 |
+
}
|
5637 |
+
}
|
5638 |
+
// types
|
5639 |
+
if (count($this->schemas) >= 1) {
|
5640 |
+
$xml .= "\n<types>\n";
|
5641 |
+
foreach ($this->schemas as $ns => $list) {
|
5642 |
+
foreach ($list as $xs) {
|
5643 |
+
$xml .= $xs->serializeSchema();
|
5644 |
+
}
|
5645 |
+
}
|
5646 |
+
$xml .= '</types>';
|
5647 |
+
}
|
5648 |
+
// messages
|
5649 |
+
if (count($this->messages) >= 1) {
|
5650 |
+
foreach ($this->messages as $msgName => $msgParts) {
|
5651 |
+
$xml .= "\n<message name=\"" . $msgName . '">';
|
5652 |
+
if (is_array($msgParts)) {
|
5653 |
+
foreach ($msgParts as $partName => $partType) {
|
5654 |
+
// print 'serializing '.$partType.', sv: '.$this->XMLSchemaVersion.'<br>';
|
5655 |
+
if (strpos($partType, ':')) {
|
5656 |
+
$typePrefix = $this->getPrefixFromNamespace($this->getPrefix($partType));
|
5657 |
+
} elseif (isset($this->typemap[$this->namespaces['xsd']][$partType])) {
|
5658 |
+
// print 'checking typemap: '.$this->XMLSchemaVersion.'<br>';
|
5659 |
+
$typePrefix = 'xsd';
|
5660 |
+
} else {
|
5661 |
+
foreach ($this->typemap as $ns => $types) {
|
5662 |
+
if (isset($types[$partType])) {
|
5663 |
+
$typePrefix = $this->getPrefixFromNamespace($ns);
|
5664 |
+
}
|
5665 |
+
}
|
5666 |
+
if (!isset($typePrefix)) {
|
5667 |
+
die("$partType has no namespace!");
|
5668 |
+
}
|
5669 |
+
}
|
5670 |
+
$ns = $this->getNamespaceFromPrefix($typePrefix);
|
5671 |
+
$localPart = $this->getLocalPart($partType);
|
5672 |
+
$typeDef = $this->getTypeDef($localPart, $ns);
|
5673 |
+
if ($typeDef['typeClass'] == 'element') {
|
5674 |
+
$elementortype = 'element';
|
5675 |
+
if (substr($localPart, -1) == '^') {
|
5676 |
+
$localPart = substr($localPart, 0, -1);
|
5677 |
+
}
|
5678 |
+
} else {
|
5679 |
+
$elementortype = 'type';
|
5680 |
+
}
|
5681 |
+
$xml .= "\n" . ' <part name="' . $partName . '" ' . $elementortype . '="' . $typePrefix . ':' . $localPart . '" />';
|
5682 |
+
}
|
5683 |
+
}
|
5684 |
+
$xml .= '</message>';
|
5685 |
+
}
|
5686 |
+
}
|
5687 |
+
// bindings & porttypes
|
5688 |
+
if (count($this->bindings) >= 1) {
|
5689 |
+
$binding_xml = '';
|
5690 |
+
$portType_xml = '';
|
5691 |
+
foreach ($this->bindings as $bindingName => $attrs) {
|
5692 |
+
$binding_xml .= "\n<binding name=\"" . $bindingName . '" type="tns:' . $attrs['portType'] . '">';
|
5693 |
+
$binding_xml .= "\n" . ' <soap:binding style="' . $attrs['style'] . '" transport="' . $attrs['transport'] . '"/>';
|
5694 |
+
$portType_xml .= "\n<portType name=\"" . $attrs['portType'] . '">';
|
5695 |
+
foreach ($attrs['operations'] as $opName => $opParts) {
|
5696 |
+
$binding_xml .= "\n" . ' <operation name="' . $opName . '">';
|
5697 |
+
$binding_xml .= "\n" . ' <soap:operation soapAction="' . $opParts['soapAction'] . '" style="' . $opParts['style'] . '"/>';
|
5698 |
+
if (isset($opParts['input']['encodingStyle']) && $opParts['input']['encodingStyle'] != '') {
|
5699 |
+
$enc_style = ' encodingStyle="' . $opParts['input']['encodingStyle'] . '"';
|
5700 |
+
} else {
|
5701 |
+
$enc_style = '';
|
5702 |
+
}
|
5703 |
+
$binding_xml .= "\n" . ' <input><soap:body use="' . $opParts['input']['use'] . '" namespace="' . $opParts['input']['namespace'] . '"' . $enc_style . '/></input>';
|
5704 |
+
if (isset($opParts['output']['encodingStyle']) && $opParts['output']['encodingStyle'] != '') {
|
5705 |
+
$enc_style = ' encodingStyle="' . $opParts['output']['encodingStyle'] . '"';
|
5706 |
+
} else {
|
5707 |
+
$enc_style = '';
|
5708 |
+
}
|
5709 |
+
$binding_xml .= "\n" . ' <output><soap:body use="' . $opParts['output']['use'] . '" namespace="' . $opParts['output']['namespace'] . '"' . $enc_style . '/></output>';
|
5710 |
+
$binding_xml .= "\n" . ' </operation>';
|
5711 |
+
$portType_xml .= "\n" . ' <operation name="' . $opParts['name'] . '"';
|
5712 |
+
if (isset($opParts['parameterOrder'])) {
|
5713 |
+
$portType_xml .= ' parameterOrder="' . $opParts['parameterOrder'] . '"';
|
5714 |
+
}
|
5715 |
+
$portType_xml .= '>';
|
5716 |
+
if (isset($opParts['documentation']) && $opParts['documentation'] != '') {
|
5717 |
+
$portType_xml .= "\n" . ' <documentation>' . htmlspecialchars($opParts['documentation']) . '</documentation>';
|
5718 |
+
}
|
5719 |
+
$portType_xml .= "\n" . ' <input message="tns:' . $opParts['input']['message'] . '"/>';
|
5720 |
+
$portType_xml .= "\n" . ' <output message="tns:' . $opParts['output']['message'] . '"/>';
|
5721 |
+
$portType_xml .= "\n" . ' </operation>';
|
5722 |
+
}
|
5723 |
+
$portType_xml .= "\n" . '</portType>';
|
5724 |
+
$binding_xml .= "\n" . '</binding>';
|
5725 |
+
}
|
5726 |
+
$xml .= $portType_xml . $binding_xml;
|
5727 |
+
}
|
5728 |
+
// services
|
5729 |
+
$xml .= "\n<service name=\"" . $this->serviceName . '">';
|
5730 |
+
if (count($this->ports) >= 1) {
|
5731 |
+
foreach ($this->ports as $pName => $attrs) {
|
5732 |
+
$xml .= "\n" . ' <port name="' . $pName . '" binding="tns:' . $attrs['binding'] . '">';
|
5733 |
+
$xml .= "\n" . ' <soap:address location="' . $attrs['location'] . ($debug ? '?debug=1' : '') . '"/>';
|
5734 |
+
$xml .= "\n" . ' </port>';
|
5735 |
+
}
|
5736 |
+
}
|
5737 |
+
$xml .= "\n" . '</service>';
|
5738 |
+
return $xml . "\n</definitions>";
|
5739 |
+
}
|
5740 |
+
|
5741 |
+
/**
|
5742 |
+
* determine whether a set of parameters are unwrapped
|
5743 |
+
* when they are expect to be wrapped, Microsoft-style.
|
5744 |
+
*
|
5745 |
+
* @param string $type the type (element name) of the wrapper
|
5746 |
+
* @param array $parameters the parameter values for the SOAP call
|
5747 |
+
* @return boolean whether they parameters are unwrapped (and should be wrapped)
|
5748 |
+
* @access private
|
5749 |
+
*/
|
5750 |
+
function parametersMatchWrapped($type, &$parameters)
|
5751 |
+
{
|
5752 |
+
$this->debug("in parametersMatchWrapped type=$type, parameters=");
|
5753 |
+
$this->appendDebug($this->varDump($parameters));
|
5754 |
+
|
5755 |
+
// split type into namespace:unqualified-type
|
5756 |
+
if (strpos($type, ':')) {
|
5757 |
+
$uqType = substr($type, strrpos($type, ':') + 1);
|
5758 |
+
$ns = substr($type, 0, strrpos($type, ':'));
|
5759 |
+
$this->debug("in parametersMatchWrapped: got a prefixed type: $uqType, $ns");
|
5760 |
+
if ($this->getNamespaceFromPrefix($ns)) {
|
5761 |
+
$ns = $this->getNamespaceFromPrefix($ns);
|
5762 |
+
$this->debug("in parametersMatchWrapped: expanded prefixed type: $uqType, $ns");
|
5763 |
+
}
|
5764 |
+
} else {
|
5765 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
5766 |
+
// set to XSD if the type matches?
|
5767 |
+
$this->debug("in parametersMatchWrapped: No namespace for type $type");
|
5768 |
+
$ns = '';
|
5769 |
+
$uqType = $type;
|
5770 |
+
}
|
5771 |
+
|
5772 |
+
// get the type information
|
5773 |
+
if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
|
5774 |
+
$this->debug("in parametersMatchWrapped: $type ($uqType) is not a supported type.");
|
5775 |
+
return false;
|
5776 |
+
}
|
5777 |
+
$this->debug("in parametersMatchWrapped: found typeDef=");
|
5778 |
+
$this->appendDebug($this->varDump($typeDef));
|
5779 |
+
if (substr($uqType, -1) == '^') {
|
5780 |
+
$uqType = substr($uqType, 0, -1);
|
5781 |
+
}
|
5782 |
+
$phpType = $typeDef['phpType'];
|
5783 |
+
$arrayType = (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : '');
|
5784 |
+
$this->debug("in parametersMatchWrapped: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: $arrayType");
|
5785 |
+
|
5786 |
+
// we expect a complexType or element of complexType
|
5787 |
+
if ($phpType != 'struct') {
|
5788 |
+
$this->debug("in parametersMatchWrapped: not a struct");
|
5789 |
+
return false;
|
5790 |
+
}
|
5791 |
+
|
5792 |
+
// see whether the parameter names match the elements
|
5793 |
+
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
|
5794 |
+
$elements = 0;
|
5795 |
+
$matches = 0;
|
5796 |
+
foreach ($typeDef['elements'] as $name => $attrs) {
|
5797 |
+
if (isset($parameters[$name])) {
|
5798 |
+
$this->debug("in parametersMatchWrapped: have parameter named $name");
|
5799 |
+
$matches++;
|
5800 |
+
} else {
|
5801 |
+
$this->debug("in parametersMatchWrapped: do not have parameter named $name");
|
5802 |
+
}
|
5803 |
+
$elements++;
|
5804 |
+
}
|
5805 |
+
|
5806 |
+
$this->debug("in parametersMatchWrapped: $matches parameter names match $elements wrapped parameter names");
|
5807 |
+
if ($matches == 0) {
|
5808 |
+
return false;
|
5809 |
+
}
|
5810 |
+
return true;
|
5811 |
+
}
|
5812 |
+
|
5813 |
+
// since there are no elements for the type, if the user passed no
|
5814 |
+
// parameters, the parameters match wrapped.
|
5815 |
+
$this->debug("in parametersMatchWrapped: no elements type $ns:$uqType");
|
5816 |
+
return count($parameters) == 0;
|
5817 |
+
}
|
5818 |
+
|
5819 |
+
/**
|
5820 |
+
* serialize PHP values according to a WSDL message definition
|
5821 |
+
* contrary to the method name, this is not limited to RPC
|
5822 |
+
*
|
5823 |
+
* TODO
|
5824 |
+
* - multi-ref serialization
|
5825 |
+
* - validate PHP values against type definitions, return errors if invalid
|
5826 |
+
*
|
5827 |
+
* @param string $operation operation name
|
5828 |
+
* @param string $direction (input|output)
|
5829 |
+
* @param mixed $parameters parameter value(s)
|
5830 |
+
* @param string $bindingType (soap|soap12)
|
5831 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
5832 |
+
* @access public
|
5833 |
+
*/
|
5834 |
+
function serializeRPCParameters($operation, $direction, $parameters, $bindingType = 'soap')
|
5835 |
+
{
|
5836 |
+
$this->debug("in serializeRPCParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion, bindingType=$bindingType");
|
5837 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
5838 |
+
|
5839 |
+
if ($direction != 'input' && $direction != 'output') {
|
5840 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
5841 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
5842 |
+
return false;
|
5843 |
+
}
|
5844 |
+
if (!$opData = $this->getOperationData($operation, $bindingType)) {
|
5845 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
5846 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation . ' bindingType: ' . $bindingType);
|
5847 |
+
return false;
|
5848 |
+
}
|
5849 |
+
$this->debug('in serializeRPCParameters: opData:');
|
5850 |
+
$this->appendDebug($this->varDump($opData));
|
5851 |
+
|
5852 |
+
// Get encoding style for output and set to current
|
5853 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
5854 |
+
if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
5855 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
5856 |
+
$enc_style = $encodingStyle;
|
5857 |
+
}
|
5858 |
+
|
5859 |
+
// set input params
|
5860 |
+
$xml = '';
|
5861 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
5862 |
+
$parts = &$opData[$direction]['parts'];
|
5863 |
+
$part_count = sizeof($parts);
|
5864 |
+
$style = $opData['style'];
|
5865 |
+
$use = $opData[$direction]['use'];
|
5866 |
+
$this->debug("have $part_count part(s) to serialize using $style/$use");
|
5867 |
+
if (is_array($parameters)) {
|
5868 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
5869 |
+
$parameter_count = count($parameters);
|
5870 |
+
$this->debug("have $parameter_count parameter(s) provided as $parametersArrayType to serialize");
|
5871 |
+
// check for Microsoft-style wrapped parameters
|
5872 |
+
if ($style == 'document' && $use == 'literal' && $part_count == 1 && isset($parts['parameters'])) {
|
5873 |
+
$this->debug('check whether the caller has wrapped the parameters');
|
5874 |
+
if ($direction == 'output' && $parametersArrayType == 'arraySimple' && $parameter_count == 1) {
|
5875 |
+
// TODO: consider checking here for double-wrapping, when
|
5876 |
+
// service function wraps, then NuSOAP wraps again
|
5877 |
+
$this->debug("change simple array to associative with 'parameters' element");
|
5878 |
+
$parameters['parameters'] = $parameters[0];
|
5879 |
+
unset($parameters[0]);
|
5880 |
+
}
|
5881 |
+
if (($parametersArrayType == 'arrayStruct' || $parameter_count == 0) && !isset($parameters['parameters'])) {
|
5882 |
+
$this->debug('check whether caller\'s parameters match the wrapped ones');
|
5883 |
+
if ($this->parametersMatchWrapped($parts['parameters'], $parameters)) {
|
5884 |
+
$this->debug('wrap the parameters for the caller');
|
5885 |
+
$parameters = array('parameters' => $parameters);
|
5886 |
+
$parameter_count = 1;
|
5887 |
+
}
|
5888 |
+
}
|
5889 |
+
}
|
5890 |
+
foreach ($parts as $name => $type) {
|
5891 |
+
$this->debug("serializing part $name of type $type");
|
5892 |
+
// Track encoding style
|
5893 |
+
if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
5894 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
5895 |
+
$enc_style = $encodingStyle;
|
5896 |
+
} else {
|
5897 |
+
$enc_style = false;
|
5898 |
+
}
|
5899 |
+
// NOTE: add error handling here
|
5900 |
+
// if serializeType returns false, then catch global error and fault
|
5901 |
+
if ($parametersArrayType == 'arraySimple') {
|
5902 |
+
$p = array_shift($parameters);
|
5903 |
+
$this->debug('calling serializeType w/indexed param');
|
5904 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
5905 |
+
} elseif (isset($parameters[$name])) {
|
5906 |
+
$this->debug('calling serializeType w/named param');
|
5907 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
5908 |
+
} else {
|
5909 |
+
// TODO: only send nillable
|
5910 |
+
$this->debug('calling serializeType w/null param');
|
5911 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
5912 |
+
}
|
5913 |
+
}
|
5914 |
+
} else {
|
5915 |
+
$this->debug('no parameters passed.');
|
5916 |
+
}
|
5917 |
+
}
|
5918 |
+
$this->debug("serializeRPCParameters returning: $xml");
|
5919 |
+
return $xml;
|
5920 |
+
}
|
5921 |
+
|
5922 |
+
/**
|
5923 |
+
* serialize a PHP value according to a WSDL message definition
|
5924 |
+
*
|
5925 |
+
* TODO
|
5926 |
+
* - multi-ref serialization
|
5927 |
+
* - validate PHP values against type definitions, return errors if invalid
|
5928 |
+
*
|
5929 |
+
* @param string $operation operation name
|
5930 |
+
* @param string $direction (input|output)
|
5931 |
+
* @param mixed $parameters parameter value(s)
|
5932 |
+
* @return mixed parameters serialized as XML or false on error (e.g. operation not found)
|
5933 |
+
* @access public
|
5934 |
+
* @deprecated
|
5935 |
+
*/
|
5936 |
+
function serializeParameters($operation, $direction, $parameters)
|
5937 |
+
{
|
5938 |
+
$this->debug("in serializeParameters: operation=$operation, direction=$direction, XMLSchemaVersion=$this->XMLSchemaVersion");
|
5939 |
+
$this->appendDebug('parameters=' . $this->varDump($parameters));
|
5940 |
+
|
5941 |
+
if ($direction != 'input' && $direction != 'output') {
|
5942 |
+
$this->debug('The value of the \$direction argument needs to be either "input" or "output"');
|
5943 |
+
$this->setError('The value of the \$direction argument needs to be either "input" or "output"');
|
5944 |
+
return false;
|
5945 |
+
}
|
5946 |
+
if (!$opData = $this->getOperationData($operation)) {
|
5947 |
+
$this->debug('Unable to retrieve WSDL data for operation: ' . $operation);
|
5948 |
+
$this->setError('Unable to retrieve WSDL data for operation: ' . $operation);
|
5949 |
+
return false;
|
5950 |
+
}
|
5951 |
+
$this->debug('opData:');
|
5952 |
+
$this->appendDebug($this->varDump($opData));
|
5953 |
+
|
5954 |
+
// Get encoding style for output and set to current
|
5955 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
5956 |
+
if (($direction == 'input') && isset($opData['output']['encodingStyle']) && ($opData['output']['encodingStyle'] != $encodingStyle)) {
|
5957 |
+
$encodingStyle = $opData['output']['encodingStyle'];
|
5958 |
+
$enc_style = $encodingStyle;
|
5959 |
+
}
|
5960 |
+
|
5961 |
+
// set input params
|
5962 |
+
$xml = '';
|
5963 |
+
if (isset($opData[$direction]['parts']) && sizeof($opData[$direction]['parts']) > 0) {
|
5964 |
+
|
5965 |
+
$use = $opData[$direction]['use'];
|
5966 |
+
$this->debug("use=$use");
|
5967 |
+
$this->debug('got ' . count($opData[$direction]['parts']) . ' part(s)');
|
5968 |
+
if (is_array($parameters)) {
|
5969 |
+
$parametersArrayType = $this->isArraySimpleOrStruct($parameters);
|
5970 |
+
$this->debug('have ' . $parametersArrayType . ' parameters');
|
5971 |
+
foreach ($opData[$direction]['parts'] as $name => $type) {
|
5972 |
+
$this->debug('serializing part "' . $name . '" of type "' . $type . '"');
|
5973 |
+
// Track encoding style
|
5974 |
+
if (isset($opData[$direction]['encodingStyle']) && $encodingStyle != $opData[$direction]['encodingStyle']) {
|
5975 |
+
$encodingStyle = $opData[$direction]['encodingStyle'];
|
5976 |
+
$enc_style = $encodingStyle;
|
5977 |
+
} else {
|
5978 |
+
$enc_style = false;
|
5979 |
+
}
|
5980 |
+
// NOTE: add error handling here
|
5981 |
+
// if serializeType returns false, then catch global error and fault
|
5982 |
+
if ($parametersArrayType == 'arraySimple') {
|
5983 |
+
$p = array_shift($parameters);
|
5984 |
+
$this->debug('calling serializeType w/indexed param');
|
5985 |
+
$xml .= $this->serializeType($name, $type, $p, $use, $enc_style);
|
5986 |
+
} elseif (isset($parameters[$name])) {
|
5987 |
+
$this->debug('calling serializeType w/named param');
|
5988 |
+
$xml .= $this->serializeType($name, $type, $parameters[$name], $use, $enc_style);
|
5989 |
+
} else {
|
5990 |
+
// TODO: only send nillable
|
5991 |
+
$this->debug('calling serializeType w/null param');
|
5992 |
+
$xml .= $this->serializeType($name, $type, null, $use, $enc_style);
|
5993 |
+
}
|
5994 |
+
}
|
5995 |
+
} else {
|
5996 |
+
$this->debug('no parameters passed.');
|
5997 |
+
}
|
5998 |
+
}
|
5999 |
+
$this->debug("serializeParameters returning: $xml");
|
6000 |
+
return $xml;
|
6001 |
+
}
|
6002 |
+
|
6003 |
+
/**
|
6004 |
+
* serializes a PHP value according a given type definition
|
6005 |
+
*
|
6006 |
+
* @param string $name name of value (part or element)
|
6007 |
+
* @param string $type XML schema type of value (type or element)
|
6008 |
+
* @param mixed $value a native PHP value (parameter value)
|
6009 |
+
* @param string $use use for part (encoded|literal)
|
6010 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
6011 |
+
* @param boolean $unqualified a kludge for what should be XML namespace form handling
|
6012 |
+
* @return string value serialized as an XML string
|
6013 |
+
* @access private
|
6014 |
+
*/
|
6015 |
+
function serializeType($name, $type, $value, $use = 'encoded', $encodingStyle = false, $unqualified = false)
|
6016 |
+
{
|
6017 |
+
$this->debug("in serializeType: name=$name, type=$type, use=$use, encodingStyle=$encodingStyle, unqualified=" . ($unqualified ? "unqualified" : "qualified"));
|
6018 |
+
$this->appendDebug("value=" . $this->varDump($value));
|
6019 |
+
if ($use == 'encoded' && $encodingStyle) {
|
6020 |
+
$encodingStyle = ' SOAP-ENV:encodingStyle="' . $encodingStyle . '"';
|
6021 |
+
}
|
6022 |
+
|
6023 |
+
// if a soapval has been supplied, let its type override the WSDL
|
6024 |
+
if (is_object($value) && get_class($value) == 'soapval') {
|
6025 |
+
if ($value->type_ns) {
|
6026 |
+
$type = $value->type_ns . ':' . $value->type;
|
6027 |
+
$forceType = true;
|
6028 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
6029 |
+
} elseif ($value->type) {
|
6030 |
+
$type = $value->type;
|
6031 |
+
$forceType = true;
|
6032 |
+
$this->debug("in serializeType: soapval overrides type to $type");
|
6033 |
+
} else {
|
6034 |
+
$forceType = false;
|
6035 |
+
$this->debug("in serializeType: soapval does not override type");
|
6036 |
+
}
|
6037 |
+
$attrs = $value->attributes;
|
6038 |
+
$value = $value->value;
|
6039 |
+
$this->debug("in serializeType: soapval overrides value to $value");
|
6040 |
+
if ($attrs) {
|
6041 |
+
if (!is_array($value)) {
|
6042 |
+
$value['!'] = $value;
|
6043 |
+
}
|
6044 |
+
foreach ($attrs as $n => $v) {
|
6045 |
+
$value['!' . $n] = $v;
|
6046 |
+
}
|
6047 |
+
$this->debug("in serializeType: soapval provides attributes");
|
6048 |
+
}
|
6049 |
+
} else {
|
6050 |
+
$forceType = false;
|
6051 |
+
}
|
6052 |
+
|
6053 |
+
$xml = '';
|
6054 |
+
if (strpos($type, ':')) {
|
6055 |
+
$uqType = substr($type, strrpos($type, ':') + 1);
|
6056 |
+
$ns = substr($type, 0, strrpos($type, ':'));
|
6057 |
+
$this->debug("in serializeType: got a prefixed type: $uqType, $ns");
|
6058 |
+
if ($this->getNamespaceFromPrefix($ns)) {
|
6059 |
+
$ns = $this->getNamespaceFromPrefix($ns);
|
6060 |
+
$this->debug("in serializeType: expanded prefixed type: $uqType, $ns");
|
6061 |
+
}
|
6062 |
+
|
6063 |
+
if ($ns == $this->XMLSchemaVersion || $ns == 'http://schemas.xmlsoap.org/soap/encoding/') {
|
6064 |
+
$this->debug('in serializeType: type namespace indicates XML Schema or SOAP Encoding type');
|
6065 |
+
if ($unqualified && $use == 'literal') {
|
6066 |
+
$elementNS = " xmlns=\"\"";
|
6067 |
+
} else {
|
6068 |
+
$elementNS = '';
|
6069 |
+
}
|
6070 |
+
if (is_null($value)) {
|
6071 |
+
if ($use == 'literal') {
|
6072 |
+
// TODO: depends on minOccurs
|
6073 |
+
$xml = "<$name$elementNS/>";
|
6074 |
+
} else {
|
6075 |
+
// TODO: depends on nillable, which should be checked before calling this method
|
6076 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
6077 |
+
}
|
6078 |
+
$this->debug("in serializeType: returning: $xml");
|
6079 |
+
return $xml;
|
6080 |
+
}
|
6081 |
+
if ($uqType == 'Array') {
|
6082 |
+
// JBoss/Axis does this sometimes
|
6083 |
+
return $this->serialize_val($value, $name, false, false, false, false, $use);
|
6084 |
+
}
|
6085 |
+
if ($uqType == 'boolean') {
|
6086 |
+
if ((is_string($value) && $value == 'false') || (!$value)) {
|
6087 |
+
$value = 'false';
|
6088 |
+
} else {
|
6089 |
+
$value = 'true';
|
6090 |
+
}
|
6091 |
+
}
|
6092 |
+
if ($uqType == 'string' && gettype($value) == 'string') {
|
6093 |
+
$value = $this->expandEntities($value);
|
6094 |
+
}
|
6095 |
+
if (($uqType == 'long' || $uqType == 'unsignedLong') && gettype($value) == 'double') {
|
6096 |
+
$value = sprintf("%.0lf", $value);
|
6097 |
+
}
|
6098 |
+
// it's a scalar
|
6099 |
+
// TODO: what about null/nil values?
|
6100 |
+
// check type isn't a custom type extending xmlschema namespace
|
6101 |
+
if (!$this->getTypeDef($uqType, $ns)) {
|
6102 |
+
if ($use == 'literal') {
|
6103 |
+
if ($forceType) {
|
6104 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
6105 |
+
} else {
|
6106 |
+
$xml = "<$name$elementNS>$value</$name>";
|
6107 |
+
}
|
6108 |
+
} else {
|
6109 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
6110 |
+
}
|
6111 |
+
$this->debug("in serializeType: returning: $xml");
|
6112 |
+
return $xml;
|
6113 |
+
}
|
6114 |
+
$this->debug('custom type extends XML Schema or SOAP Encoding namespace (yuck)');
|
6115 |
+
} elseif ($ns == 'http://xml.apache.org/xml-soap') {
|
6116 |
+
$this->debug('in serializeType: appears to be Apache SOAP type');
|
6117 |
+
if ($uqType == 'Map') {
|
6118 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
6119 |
+
if (!$tt_prefix) {
|
6120 |
+
$this->debug('in serializeType: Add namespace for Apache SOAP type');
|
6121 |
+
$tt_prefix = 'ns' . rand(1000, 9999);
|
6122 |
+
$this->namespaces[$tt_prefix] = 'http://xml.apache.org/xml-soap';
|
6123 |
+
// force this to be added to usedNamespaces
|
6124 |
+
$tt_prefix = $this->getPrefixFromNamespace('http://xml.apache.org/xml-soap');
|
6125 |
+
}
|
6126 |
+
$contents = '';
|
6127 |
+
foreach ($value as $k => $v) {
|
6128 |
+
$this->debug("serializing map element: key $k, value $v");
|
6129 |
+
$contents .= '<item>';
|
6130 |
+
$contents .= $this->serialize_val($k, 'key', false, false, false, false, $use);
|
6131 |
+
$contents .= $this->serialize_val($v, 'value', false, false, false, false, $use);
|
6132 |
+
$contents .= '</item>';
|
6133 |
+
}
|
6134 |
+
if ($use == 'literal') {
|
6135 |
+
if ($forceType) {
|
6136 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\">$contents</$name>";
|
6137 |
+
} else {
|
6138 |
+
$xml = "<$name>$contents</$name>";
|
6139 |
+
}
|
6140 |
+
} else {
|
6141 |
+
$xml = "<$name xsi:type=\"" . $tt_prefix . ":$uqType\"$encodingStyle>$contents</$name>";
|
6142 |
+
}
|
6143 |
+
$this->debug("in serializeType: returning: $xml");
|
6144 |
+
return $xml;
|
6145 |
+
}
|
6146 |
+
$this->debug('in serializeType: Apache SOAP type, but only support Map');
|
6147 |
+
}
|
6148 |
+
} else {
|
6149 |
+
// TODO: should the type be compared to types in XSD, and the namespace
|
6150 |
+
// set to XSD if the type matches?
|
6151 |
+
$this->debug("in serializeType: No namespace for type $type");
|
6152 |
+
$ns = '';
|
6153 |
+
$uqType = $type;
|
6154 |
+
}
|
6155 |
+
if (!$typeDef = $this->getTypeDef($uqType, $ns)) {
|
6156 |
+
$this->setError("$type ($uqType) is not a supported type.");
|
6157 |
+
$this->debug("in serializeType: $type ($uqType) is not a supported type.");
|
6158 |
+
return false;
|
6159 |
+
} else {
|
6160 |
+
$this->debug("in serializeType: found typeDef");
|
6161 |
+
$this->appendDebug('typeDef=' . $this->varDump($typeDef));
|
6162 |
+
if (substr($uqType, -1) == '^') {
|
6163 |
+
$uqType = substr($uqType, 0, -1);
|
6164 |
+
}
|
6165 |
+
}
|
6166 |
+
if (!isset($typeDef['phpType'])) {
|
6167 |
+
$this->setError("$type ($uqType) has no phpType.");
|
6168 |
+
$this->debug("in serializeType: $type ($uqType) has no phpType.");
|
6169 |
+
return false;
|
6170 |
+
}
|
6171 |
+
$phpType = $typeDef['phpType'];
|
6172 |
+
$this->debug("in serializeType: uqType: $uqType, ns: $ns, phptype: $phpType, arrayType: " . (isset($typeDef['arrayType']) ? $typeDef['arrayType'] : ''));
|
6173 |
+
// if php type == struct, map value to the <all> element names
|
6174 |
+
if ($phpType == 'struct') {
|
6175 |
+
if (isset($typeDef['typeClass']) && $typeDef['typeClass'] == 'element') {
|
6176 |
+
$elementName = $uqType;
|
6177 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6178 |
+
$elementNS = " xmlns=\"$ns\"";
|
6179 |
+
} else {
|
6180 |
+
$elementNS = " xmlns=\"\"";
|
6181 |
+
}
|
6182 |
+
} else {
|
6183 |
+
$elementName = $name;
|
6184 |
+
if ($unqualified) {
|
6185 |
+
$elementNS = " xmlns=\"\"";
|
6186 |
+
} else {
|
6187 |
+
$elementNS = '';
|
6188 |
+
}
|
6189 |
+
}
|
6190 |
+
if (is_null($value)) {
|
6191 |
+
if ($use == 'literal') {
|
6192 |
+
// TODO: depends on minOccurs and nillable
|
6193 |
+
$xml = "<$elementName$elementNS/>";
|
6194 |
+
} else {
|
6195 |
+
$xml = "<$elementName$elementNS xsi:nil=\"true\" xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"/>";
|
6196 |
+
}
|
6197 |
+
$this->debug("in serializeType: returning: $xml");
|
6198 |
+
return $xml;
|
6199 |
+
}
|
6200 |
+
if (is_object($value)) {
|
6201 |
+
$value = get_object_vars($value);
|
6202 |
+
}
|
6203 |
+
if (is_array($value)) {
|
6204 |
+
$elementAttrs = $this->serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType);
|
6205 |
+
if ($use == 'literal') {
|
6206 |
+
if ($forceType) {
|
6207 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">";
|
6208 |
+
} else {
|
6209 |
+
$xml = "<$elementName$elementNS$elementAttrs>";
|
6210 |
+
}
|
6211 |
+
} else {
|
6212 |
+
$xml = "<$elementName$elementNS$elementAttrs xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>";
|
6213 |
+
}
|
6214 |
+
|
6215 |
+
if (isset($typeDef['simpleContent']) && $typeDef['simpleContent'] == 'true') {
|
6216 |
+
if (isset($value['!'])) {
|
6217 |
+
$xml .= $value['!'];
|
6218 |
+
$this->debug("in serializeType: serialized simpleContent for type $type");
|
6219 |
+
} else {
|
6220 |
+
$this->debug("in serializeType: no simpleContent to serialize for type $type");
|
6221 |
+
}
|
6222 |
+
} else {
|
6223 |
+
// complexContent
|
6224 |
+
$xml .= $this->serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use, $encodingStyle);
|
6225 |
+
}
|
6226 |
+
$xml .= "</$elementName>";
|
6227 |
+
} else {
|
6228 |
+
$this->debug("in serializeType: phpType is struct, but value is not an array");
|
6229 |
+
$this->setError("phpType is struct, but value is not an array: see debug output for details");
|
6230 |
+
$xml = '';
|
6231 |
+
}
|
6232 |
+
} elseif ($phpType == 'array') {
|
6233 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6234 |
+
$elementNS = " xmlns=\"$ns\"";
|
6235 |
+
} else {
|
6236 |
+
if ($unqualified) {
|
6237 |
+
$elementNS = " xmlns=\"\"";
|
6238 |
+
} else {
|
6239 |
+
$elementNS = '';
|
6240 |
+
}
|
6241 |
+
}
|
6242 |
+
if (is_null($value)) {
|
6243 |
+
if ($use == 'literal') {
|
6244 |
+
// TODO: depends on minOccurs
|
6245 |
+
$xml = "<$name$elementNS/>";
|
6246 |
+
} else {
|
6247 |
+
$xml = "<$name$elementNS xsi:nil=\"true\" xsi:type=\"" .
|
6248 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
6249 |
+
":Array\" " .
|
6250 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') .
|
6251 |
+
':arrayType="' .
|
6252 |
+
$this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType'])) .
|
6253 |
+
':' .
|
6254 |
+
$this->getLocalPart($typeDef['arrayType']) . "[0]\"/>";
|
6255 |
+
}
|
6256 |
+
$this->debug("in serializeType: returning: $xml");
|
6257 |
+
return $xml;
|
6258 |
+
}
|
6259 |
+
if (isset($typeDef['multidimensional'])) {
|
6260 |
+
$nv = array();
|
6261 |
+
foreach ($value as $v) {
|
6262 |
+
$cols = ',' . sizeof($v);
|
6263 |
+
$nv = array_merge($nv, $v);
|
6264 |
+
}
|
6265 |
+
$value = $nv;
|
6266 |
+
} else {
|
6267 |
+
$cols = '';
|
6268 |
+
}
|
6269 |
+
if (is_array($value) && sizeof($value) >= 1) {
|
6270 |
+
$rows = sizeof($value);
|
6271 |
+
$contents = '';
|
6272 |
+
foreach ($value as $k => $v) {
|
6273 |
+
$this->debug("serializing array element: $k, " . (is_array($v) ? "array" : $v) . " of type: $typeDef[arrayType]");
|
6274 |
+
//if (strpos($typeDef['arrayType'], ':') ) {
|
6275 |
+
if (!in_array($typeDef['arrayType'], $this->typemap['http://www.w3.org/2001/XMLSchema'])) {
|
6276 |
+
$contents .= $this->serializeType('item', $typeDef['arrayType'], $v, $use);
|
6277 |
+
} else {
|
6278 |
+
$contents .= $this->serialize_val($v, 'item', $typeDef['arrayType'], null, $this->XMLSchemaVersion, false, $use);
|
6279 |
+
}
|
6280 |
+
}
|
6281 |
+
} else {
|
6282 |
+
$rows = 0;
|
6283 |
+
$contents = null;
|
6284 |
+
}
|
6285 |
+
// TODO: for now, an empty value will be serialized as a zero element
|
6286 |
+
// array. Revisit this when coding the handling of null/nil values.
|
6287 |
+
if ($use == 'literal') {
|
6288 |
+
$xml = "<$name$elementNS>"
|
6289 |
+
. $contents
|
6290 |
+
. "</$name>";
|
6291 |
+
} else {
|
6292 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/') . ':Array" ' .
|
6293 |
+
$this->getPrefixFromNamespace('http://schemas.xmlsoap.org/soap/encoding/')
|
6294 |
+
. ':arrayType="'
|
6295 |
+
. $this->getPrefixFromNamespace($this->getPrefix($typeDef['arrayType']))
|
6296 |
+
. ":" . $this->getLocalPart($typeDef['arrayType']) . "[$rows$cols]\">"
|
6297 |
+
. $contents
|
6298 |
+
. "</$name>";
|
6299 |
+
}
|
6300 |
+
} elseif ($phpType == 'scalar') {
|
6301 |
+
if (isset($typeDef['form']) && ($typeDef['form'] == 'qualified')) {
|
6302 |
+
$elementNS = " xmlns=\"$ns\"";
|
6303 |
+
} else {
|
6304 |
+
if ($unqualified) {
|
6305 |
+
$elementNS = " xmlns=\"\"";
|
6306 |
+
} else {
|
6307 |
+
$elementNS = '';
|
6308 |
+
}
|
6309 |
+
}
|
6310 |
+
if ($use == 'literal') {
|
6311 |
+
if ($forceType) {
|
6312 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\">$value</$name>";
|
6313 |
+
} else {
|
6314 |
+
$xml = "<$name$elementNS>$value</$name>";
|
6315 |
+
}
|
6316 |
+
} else {
|
6317 |
+
$xml = "<$name$elementNS xsi:type=\"" . $this->getPrefixFromNamespace($ns) . ":$uqType\"$encodingStyle>$value</$name>";
|
6318 |
+
}
|
6319 |
+
}
|
6320 |
+
$this->debug("in serializeType: returning: $xml");
|
6321 |
+
return $xml;
|
6322 |
+
}
|
6323 |
+
|
6324 |
+
/**
|
6325 |
+
* serializes the attributes for a complexType
|
6326 |
+
*
|
6327 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6328 |
+
* @param mixed $value a native PHP value (parameter value)
|
6329 |
+
* @param string $ns the namespace of the type
|
6330 |
+
* @param string $uqType the local part of the type
|
6331 |
+
* @return string value serialized as an XML string
|
6332 |
+
* @access private
|
6333 |
+
*/
|
6334 |
+
function serializeComplexTypeAttributes($typeDef, $value, $ns, $uqType)
|
6335 |
+
{
|
6336 |
+
$this->debug("serializeComplexTypeAttributes for XML Schema type $ns:$uqType");
|
6337 |
+
$xml = '';
|
6338 |
+
if (isset($typeDef['extensionBase'])) {
|
6339 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
6340 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
6341 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
6342 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
6343 |
+
}
|
6344 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
6345 |
+
$this->debug("serialize attributes for extension base $nsx:$uqTypex");
|
6346 |
+
$xml .= $this->serializeComplexTypeAttributes($typeDefx, $value, $nsx, $uqTypex);
|
6347 |
+
} else {
|
6348 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
6349 |
+
}
|
6350 |
+
}
|
6351 |
+
if (isset($typeDef['attrs']) && is_array($typeDef['attrs'])) {
|
6352 |
+
$this->debug("serialize attributes for XML Schema type $ns:$uqType");
|
6353 |
+
if (is_array($value)) {
|
6354 |
+
$xvalue = $value;
|
6355 |
+
} elseif (is_object($value)) {
|
6356 |
+
$xvalue = get_object_vars($value);
|
6357 |
+
} else {
|
6358 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
6359 |
+
$xvalue = array();
|
6360 |
+
}
|
6361 |
+
foreach ($typeDef['attrs'] as $aName => $attrs) {
|
6362 |
+
if (isset($xvalue['!' . $aName])) {
|
6363 |
+
$xname = '!' . $aName;
|
6364 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
6365 |
+
} elseif (isset($xvalue[$aName])) {
|
6366 |
+
$xname = $aName;
|
6367 |
+
$this->debug("value provided for attribute $aName with key $xname");
|
6368 |
+
} elseif (isset($attrs['default'])) {
|
6369 |
+
$xname = '!' . $aName;
|
6370 |
+
$xvalue[$xname] = $attrs['default'];
|
6371 |
+
$this->debug('use default value of ' . $xvalue[$aName] . ' for attribute ' . $aName);
|
6372 |
+
} else {
|
6373 |
+
$xname = '';
|
6374 |
+
$this->debug("no value provided for attribute $aName");
|
6375 |
+
}
|
6376 |
+
if ($xname) {
|
6377 |
+
$xml .= " $aName=\"" . $this->expandEntities($xvalue[$xname]) . "\"";
|
6378 |
+
}
|
6379 |
+
}
|
6380 |
+
} else {
|
6381 |
+
$this->debug("no attributes to serialize for XML Schema type $ns:$uqType");
|
6382 |
+
}
|
6383 |
+
return $xml;
|
6384 |
+
}
|
6385 |
+
|
6386 |
+
/**
|
6387 |
+
* serializes the elements for a complexType
|
6388 |
+
*
|
6389 |
+
* @param array $typeDef our internal representation of an XML schema type (or element)
|
6390 |
+
* @param mixed $value a native PHP value (parameter value)
|
6391 |
+
* @param string $ns the namespace of the type
|
6392 |
+
* @param string $uqType the local part of the type
|
6393 |
+
* @param string $use use for part (encoded|literal)
|
6394 |
+
* @param string $encodingStyle SOAP encoding style for the value (if different than the enclosing style)
|
6395 |
+
* @return string value serialized as an XML string
|
6396 |
+
* @access private
|
6397 |
+
*/
|
6398 |
+
function serializeComplexTypeElements($typeDef, $value, $ns, $uqType, $use = 'encoded', $encodingStyle = false)
|
6399 |
+
{
|
6400 |
+
$this->debug("in serializeComplexTypeElements for XML Schema type $ns:$uqType");
|
6401 |
+
$xml = '';
|
6402 |
+
if (isset($typeDef['extensionBase'])) {
|
6403 |
+
$nsx = $this->getPrefix($typeDef['extensionBase']);
|
6404 |
+
$uqTypex = $this->getLocalPart($typeDef['extensionBase']);
|
6405 |
+
if ($this->getNamespaceFromPrefix($nsx)) {
|
6406 |
+
$nsx = $this->getNamespaceFromPrefix($nsx);
|
6407 |
+
}
|
6408 |
+
if ($typeDefx = $this->getTypeDef($uqTypex, $nsx)) {
|
6409 |
+
$this->debug("serialize elements for extension base $nsx:$uqTypex");
|
6410 |
+
$xml .= $this->serializeComplexTypeElements($typeDefx, $value, $nsx, $uqTypex, $use, $encodingStyle);
|
6411 |
+
} else {
|
6412 |
+
$this->debug("extension base $nsx:$uqTypex is not a supported type");
|
6413 |
+
}
|
6414 |
+
}
|
6415 |
+
if (isset($typeDef['elements']) && is_array($typeDef['elements'])) {
|
6416 |
+
$this->debug("in serializeComplexTypeElements, serialize elements for XML Schema type $ns:$uqType");
|
6417 |
+
if (is_array($value)) {
|
6418 |
+
$xvalue = $value;
|
6419 |
+
} elseif (is_object($value)) {
|
6420 |
+
$xvalue = get_object_vars($value);
|
6421 |
+
} else {
|
6422 |
+
$this->debug("value is neither an array nor an object for XML Schema type $ns:$uqType");
|
6423 |
+
$xvalue = array();
|
6424 |
+
}
|
6425 |
+
// toggle whether all elements are present - ideally should validate against schema
|
6426 |
+
if (count($typeDef['elements']) != count($xvalue)) {
|
6427 |
+
$optionals = true;
|
6428 |
+
}
|
6429 |
+
foreach ($typeDef['elements'] as $eName => $attrs) {
|
6430 |
+
if (!isset($xvalue[$eName])) {
|
6431 |
+
if (isset($attrs['default'])) {
|
6432 |
+
$xvalue[$eName] = $attrs['default'];
|
6433 |
+
$this->debug('use default value of ' . $xvalue[$eName] . ' for element ' . $eName);
|
6434 |
+
}
|
6435 |
+
}
|
6436 |
+
// if user took advantage of a minOccurs=0, then only serialize named parameters
|
6437 |
+
if (isset($optionals)
|
6438 |
+
&& (!isset($xvalue[$eName]))
|
6439 |
+
&& ((!isset($attrs['nillable'])) || $attrs['nillable'] != 'true')
|
6440 |
+
) {
|
6441 |
+
if (isset($attrs['minOccurs']) && $attrs['minOccurs'] <> '0') {
|
6442 |
+
$this->debug("apparent error: no value provided for element $eName with minOccurs=" . $attrs['minOccurs']);
|
6443 |
+
}
|
6444 |
+
// do nothing
|
6445 |
+
$this->debug("no value provided for complexType element $eName and element is not nillable, so serialize nothing");
|
6446 |
+
} else {
|
6447 |
+
// get value
|
6448 |
+
if (isset($xvalue[$eName])) {
|
6449 |
+
$v = $xvalue[$eName];
|
6450 |
+
} else {
|
6451 |
+
$v = null;
|
6452 |
+
}
|
6453 |
+
if (isset($attrs['form'])) {
|
6454 |
+
$unqualified = ($attrs['form'] == 'unqualified');
|
6455 |
+
} else {
|
6456 |
+
$unqualified = false;
|
6457 |
+
}
|
6458 |
+
if (isset($attrs['maxOccurs']) && ($attrs['maxOccurs'] == 'unbounded' || $attrs['maxOccurs'] > 1) && isset($v) && is_array($v) && $this->isArraySimpleOrStruct($v) == 'arraySimple') {
|
6459 |
+
$vv = $v;
|
6460 |
+
foreach ($vv as $k => $v) {
|
6461 |
+
if (isset($attrs['type']) || isset($attrs['ref'])) {
|
6462 |
+
// serialize schema-defined type
|
6463 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6464 |
+
} else {
|
6465 |
+
// serialize generic type (can this ever really happen?)
|
6466 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
6467 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
6468 |
+
}
|
6469 |
+
}
|
6470 |
+
} else {
|
6471 |
+
if (is_null($v) && isset($attrs['minOccurs']) && $attrs['minOccurs'] == '0') {
|
6472 |
+
// do nothing
|
6473 |
+
} elseif (is_null($v) && isset($attrs['nillable']) && $attrs['nillable'] == 'true') {
|
6474 |
+
// TODO: serialize a nil correctly, but for now serialize schema-defined type
|
6475 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6476 |
+
} elseif (isset($attrs['type']) || isset($attrs['ref'])) {
|
6477 |
+
// serialize schema-defined type
|
6478 |
+
$xml .= $this->serializeType($eName, isset($attrs['type']) ? $attrs['type'] : $attrs['ref'], $v, $use, $encodingStyle, $unqualified);
|
6479 |
+
} else {
|
6480 |
+
// serialize generic type (can this ever really happen?)
|
6481 |
+
$this->debug("calling serialize_val() for $v, $eName, false, false, false, false, $use");
|
6482 |
+
$xml .= $this->serialize_val($v, $eName, false, false, false, false, $use);
|
6483 |
+
}
|
6484 |
+
}
|
6485 |
+
}
|
6486 |
+
}
|
6487 |
+
} else {
|
6488 |
+
$this->debug("no elements to serialize for XML Schema type $ns:$uqType");
|
6489 |
+
}
|
6490 |
+
return $xml;
|
6491 |
+
}
|
6492 |
+
|
6493 |
+
/**
|
6494 |
+
* adds an XML Schema complex type to the WSDL types
|
6495 |
+
*
|
6496 |
+
* @param string $name
|
6497 |
+
* @param string $typeClass (complexType|simpleType|attribute)
|
6498 |
+
* @param string $phpType currently supported are array and struct (php assoc array)
|
6499 |
+
* @param string $compositor (all|sequence|choice)
|
6500 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6501 |
+
* @param array $elements e.g. array ( name => array(name=>'',type=>'') )
|
6502 |
+
* @param array $attrs e.g. array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]'))
|
6503 |
+
* @param string $arrayType as namespace:name (xsd:string)
|
6504 |
+
* @see nusoap_xmlschema
|
6505 |
+
* @access public
|
6506 |
+
*/
|
6507 |
+
function addComplexType($name, $typeClass = 'complexType', $phpType = 'array', $compositor = '', $restrictionBase = '', $elements = array(), $attrs = array(), $arrayType = '')
|
6508 |
+
{
|
6509 |
+
if (count($elements) > 0) {
|
6510 |
+
$eElements = array();
|
6511 |
+
foreach ($elements as $n => $e) {
|
6512 |
+
// expand each element
|
6513 |
+
$ee = array();
|
6514 |
+
foreach ($e as $k => $v) {
|
6515 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
6516 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
6517 |
+
$ee[$k] = $v;
|
6518 |
+
}
|
6519 |
+
$eElements[$n] = $ee;
|
6520 |
+
}
|
6521 |
+
$elements = $eElements;
|
6522 |
+
}
|
6523 |
+
|
6524 |
+
if (count($attrs) > 0) {
|
6525 |
+
foreach ($attrs as $n => $a) {
|
6526 |
+
// expand each attribute
|
6527 |
+
foreach ($a as $k => $v) {
|
6528 |
+
$k = strpos($k, ':') ? $this->expandQname($k) : $k;
|
6529 |
+
$v = strpos($v, ':') ? $this->expandQname($v) : $v;
|
6530 |
+
$aa[$k] = $v;
|
6531 |
+
}
|
6532 |
+
$eAttrs[$n] = $aa;
|
6533 |
+
}
|
6534 |
+
$attrs = $eAttrs;
|
6535 |
+
}
|
6536 |
+
|
6537 |
+
$restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
6538 |
+
$arrayType = strpos($arrayType, ':') ? $this->expandQname($arrayType) : $arrayType;
|
6539 |
+
|
6540 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6541 |
+
$this->schemas[$typens][0]->addComplexType($name, $typeClass, $phpType, $compositor, $restrictionBase, $elements, $attrs, $arrayType);
|
6542 |
+
}
|
6543 |
+
|
6544 |
+
/**
|
6545 |
+
* adds an XML Schema simple type to the WSDL types
|
6546 |
+
*
|
6547 |
+
* @param string $name
|
6548 |
+
* @param string $restrictionBase namespace:name (http://schemas.xmlsoap.org/soap/encoding/:Array)
|
6549 |
+
* @param string $typeClass (should always be simpleType)
|
6550 |
+
* @param string $phpType (should always be scalar)
|
6551 |
+
* @param array $enumeration array of values
|
6552 |
+
* @see nusoap_xmlschema
|
6553 |
+
* @access public
|
6554 |
+
*/
|
6555 |
+
function addSimpleType($name, $restrictionBase = '', $typeClass = 'simpleType', $phpType = 'scalar', $enumeration = array())
|
6556 |
+
{
|
6557 |
+
$restrictionBase = strpos($restrictionBase, ':') ? $this->expandQname($restrictionBase) : $restrictionBase;
|
6558 |
+
|
6559 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6560 |
+
$this->schemas[$typens][0]->addSimpleType($name, $restrictionBase, $typeClass, $phpType, $enumeration);
|
6561 |
+
}
|
6562 |
+
|
6563 |
+
/**
|
6564 |
+
* adds an element to the WSDL types
|
6565 |
+
*
|
6566 |
+
* @param array $attrs attributes that must include name and type
|
6567 |
+
* @see nusoap_xmlschema
|
6568 |
+
* @access public
|
6569 |
+
*/
|
6570 |
+
function addElement($attrs)
|
6571 |
+
{
|
6572 |
+
$typens = isset($this->namespaces['types']) ? $this->namespaces['types'] : $this->namespaces['tns'];
|
6573 |
+
$this->schemas[$typens][0]->addElement($attrs);
|
6574 |
+
}
|
6575 |
+
|
6576 |
+
/**
|
6577 |
+
* register an operation with the server
|
6578 |
+
*
|
6579 |
+
* @param string $name operation (method) name
|
6580 |
+
* @param array $in assoc array of input values: key = param name, value = param type
|
6581 |
+
* @param array $out assoc array of output values: key = param name, value = param type
|
6582 |
+
* @param string $namespace optional The namespace for the operation
|
6583 |
+
* @param string $soapaction optional The soapaction for the operation
|
6584 |
+
* @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
|
6585 |
+
* @param string $use (encoded|literal) optional The use for the parameters (cannot mix right now)
|
6586 |
+
* @param string $documentation optional The description to include in the WSDL
|
6587 |
+
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
|
6588 |
+
* @access public
|
6589 |
+
*/
|
6590 |
+
function addOperation($name, $in = false, $out = false, $namespace = false, $soapaction = false, $style = 'rpc', $use = 'encoded', $documentation = '', $encodingStyle = '')
|
6591 |
+
{
|
6592 |
+
if ($use == 'encoded' && $encodingStyle == '') {
|
6593 |
+
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
|
6594 |
+
}
|
6595 |
+
|
6596 |
+
if ($style == 'document') {
|
6597 |
+
$elements = array();
|
6598 |
+
foreach ($in as $n => $t) {
|
6599 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
6600 |
+
}
|
6601 |
+
$this->addComplexType($name . 'RequestType', 'complexType', 'struct', 'all', '', $elements);
|
6602 |
+
$this->addElement(array('name' => $name, 'type' => $name . 'RequestType'));
|
6603 |
+
$in = array('parameters' => 'tns:' . $name . '^');
|
6604 |
+
|
6605 |
+
$elements = array();
|
6606 |
+
foreach ($out as $n => $t) {
|
6607 |
+
$elements[$n] = array('name' => $n, 'type' => $t, 'form' => 'unqualified');
|
6608 |
+
}
|
6609 |
+
$this->addComplexType($name . 'ResponseType', 'complexType', 'struct', 'all', '', $elements);
|
6610 |
+
$this->addElement(array('name' => $name . 'Response', 'type' => $name . 'ResponseType', 'form' => 'qualified'));
|
6611 |
+
$out = array('parameters' => 'tns:' . $name . 'Response' . '^');
|
6612 |
+
}
|
6613 |
+
|
6614 |
+
// get binding
|
6615 |
+
$this->bindings[$this->serviceName . 'Binding']['operations'][$name] =
|
6616 |
+
array(
|
6617 |
+
'name' => $name,
|
6618 |
+
'binding' => $this->serviceName . 'Binding',
|
6619 |
+
'endpoint' => $this->endpoint,
|
6620 |
+
'soapAction' => $soapaction,
|
6621 |
+
'style' => $style,
|
6622 |
+
'input' => array(
|
6623 |
+
'use' => $use,
|
6624 |
+
'namespace' => $namespace,
|
6625 |
+
'encodingStyle' => $encodingStyle,
|
6626 |
+
'message' => $name . 'Request',
|
6627 |
+
'parts' => $in),
|
6628 |
+
'output' => array(
|
6629 |
+
'use' => $use,
|
6630 |
+
'namespace' => $namespace,
|
6631 |
+
'encodingStyle' => $encodingStyle,
|
6632 |
+
'message' => $name . 'Response',
|
6633 |
+
'parts' => $out),
|
6634 |
+
'namespace' => $namespace,
|
6635 |
+
'transport' => 'http://schemas.xmlsoap.org/soap/http',
|
6636 |
+
'documentation' => $documentation);
|
6637 |
+
// add portTypes
|
6638 |
+
// add messages
|
6639 |
+
if ($in) {
|
6640 |
+
foreach ($in as $pName => $pType) {
|
6641 |
+
if (strpos($pType, ':')) {
|
6642 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
|
6643 |
+
}
|
6644 |
+
$this->messages[$name . 'Request'][$pName] = $pType;
|
6645 |
+
}
|
6646 |
+
} else {
|
6647 |
+
$this->messages[$name . 'Request'] = '0';
|
6648 |
+
}
|
6649 |
+
if ($out) {
|
6650 |
+
foreach ($out as $pName => $pType) {
|
6651 |
+
if (strpos($pType, ':')) {
|
6652 |
+
$pType = $this->getNamespaceFromPrefix($this->getPrefix($pType)) . ":" . $this->getLocalPart($pType);
|
6653 |
+
}
|
6654 |
+
$this->messages[$name . 'Response'][$pName] = $pType;
|
6655 |
+
}
|
6656 |
+
} else {
|
6657 |
+
$this->messages[$name . 'Response'] = '0';
|
6658 |
+
}
|
6659 |
+
return true;
|
6660 |
+
}
|
6661 |
+
}
|
6662 |
+
|
6663 |
+
|
6664 |
+
/**
|
6665 |
+
*
|
6666 |
+
* nusoap_parser class parses SOAP XML messages into native PHP values
|
6667 |
+
*
|
6668 |
+
* @author Dietrich Ayala <dietrich@ganx4.com>
|
6669 |
+
* @author Scott Nichol <snichol@users.sourceforge.net>
|
6670 |
+
* @version $Id: nusoap.php,v 1.123 2010/04/26 20:15:08 snichol Exp $
|
6671 |
+
* @access public
|
6672 |
+
*/
|
6673 |
+
class nusoap_parser extends nusoap_base
|
6674 |
+
{
|
6675 |
+
|
6676 |
+
var $xml = '';
|
6677 |
+
var $xml_encoding = '';
|
6678 |
+
var $method = '';
|
6679 |
+
var $root_struct = '';
|
6680 |
+
var $root_struct_name = '';
|
6681 |
+
var $root_struct_namespace = '';
|
6682 |
+
var $root_header = '';
|
6683 |
+
var $document = ''; // incoming SOAP body (text)
|
6684 |
+
// determines where in the message we are (envelope,header,body,method)
|
6685 |
+
var $status = '';
|
6686 |
+
var $position = 0;
|
6687 |
+
var $depth = 0;
|
6688 |
+
var $default_namespace = '';
|
6689 |
+
var $namespaces = array();
|
6690 |
+
var $message = array();
|
6691 |
+
var $parent = '';
|
6692 |
+
var $fault = false;
|
6693 |
+
var $fault_code = '';
|
6694 |
+
var $fault_str = '';
|
6695 |
+
var $fault_detail = '';
|
6696 |
+
var $depth_array = array();
|
6697 |
+
var $debug_flag = true;
|
6698 |
+
var $soapresponse = null; // parsed SOAP Body
|
6699 |
+
var $soapheader = null; // parsed SOAP Header
|
6700 |
+
var $responseHeaders = ''; // incoming SOAP headers (text)
|
6701 |
+
var $body_position = 0;
|
6702 |
+
// for multiref parsing:
|
6703 |
+
// array of id => pos
|
6704 |
+
var $ids = array();
|
6705 |
+
// array of id => hrefs => pos
|
6706 |
+
var $multirefs = array();
|
6707 |
+
// toggle for auto-decoding element content
|
6708 |
+
var $decode_utf8 = true;
|
6709 |
+
|
6710 |
+
/**
|
6711 |
+
* constructor that actually does the parsing
|
6712 |
+
*
|
6713 |
+
* @param string $xml SOAP message
|
6714 |
+
* @param string $encoding character encoding scheme of message
|
6715 |
+
* @param string $method method for which XML is parsed (unused?)
|
6716 |
+
* @param string $decode_utf8 whether to decode UTF-8 to ISO-8859-1
|
6717 |
+
* @access public
|
6718 |
+
*/
|
6719 |
+
function __construct($xml, $encoding = 'UTF-8', $method = '', $decode_utf8 = true)
|
6720 |
+
{
|
6721 |
+
parent::__construct();
|
6722 |
+
$this->xml = $xml;
|
6723 |
+
$this->xml_encoding = $encoding;
|
6724 |
+
$this->method = $method;
|
6725 |
+
$this->decode_utf8 = $decode_utf8;
|
6726 |
+
|
6727 |
+
// Check whether content has been read.
|
6728 |
+
if (!empty($xml)) {
|
6729 |
+
// Check XML encoding
|
6730 |
+
$pos_xml = strpos($xml, '<?xml');
|
6731 |
+
if ($pos_xml !== false) {
|
6732 |
+
$xml_decl = substr($xml, $pos_xml, strpos($xml, '?>', $pos_xml + 2) - $pos_xml + 1);
|
6733 |
+
if (preg_match("/encoding=[\"']([^\"']*)[\"']/", $xml_decl, $res)) {
|
6734 |
+
$xml_encoding = $res[1];
|
6735 |
+
if (strtoupper($xml_encoding) != $encoding) {
|
6736 |
+
$err = "Charset from HTTP Content-Type '" . $encoding . "' does not match encoding from XML declaration '" . $xml_encoding . "'";
|
6737 |
+
$this->debug($err);
|
6738 |
+
if ($encoding != 'ISO-8859-1' || strtoupper($xml_encoding) != 'UTF-8') {
|
6739 |
+
$this->setError($err);
|
6740 |
+
return;
|
6741 |
+
}
|
6742 |
+
// when HTTP says ISO-8859-1 (the default) and XML says UTF-8 (the typical), assume the other endpoint is just sloppy and proceed
|
6743 |
+
} else {
|
6744 |
+
$this->debug('Charset from HTTP Content-Type matches encoding from XML declaration');
|
6745 |
+
}
|
6746 |
+
} else {
|
6747 |
+
$this->debug('No encoding specified in XML declaration');
|
6748 |
+
}
|
6749 |
+
} else {
|
6750 |
+
$this->debug('No XML declaration');
|
6751 |
+
}
|
6752 |
+
$this->debug('Entering nusoap_parser(), length=' . strlen($xml) . ', encoding=' . $encoding);
|
6753 |
+
// Create an XML parser - why not xml_parser_create_ns?
|
6754 |
+
$this->parser = xml_parser_create($this->xml_encoding);
|
6755 |
+
// Set the options for parsing the XML data.
|
6756 |
+
//xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
6757 |
+
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
|
6758 |
+
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $this->xml_encoding);
|
6759 |
+
// Set the object for the parser.
|
6760 |
+
xml_set_object($this->parser, $this);
|
6761 |
+
// Set the element handlers for the parser.
|
6762 |
+
xml_set_element_handler($this->parser, 'start_element', 'end_element');
|
6763 |
+
xml_set_character_data_handler($this->parser, 'character_data');
|
6764 |
+
|
6765 |
+
// Parse the XML file.
|
6766 |
+
if (!xml_parse($this->parser, $xml, true)) {
|
6767 |
+
// Display an error message.
|
6768 |
+
$err = sprintf('XML error parsing SOAP payload on line %d: %s',
|
6769 |
+
xml_get_current_line_number($this->parser),
|
6770 |
+
xml_error_string(xml_get_error_code($this->parser)));
|
6771 |
+
$this->debug($err);
|
6772 |
+
$this->debug("XML payload:\n" . $xml);
|
6773 |
+
$this->setError($err);
|
6774 |
+
} else {
|
6775 |
+
$this->debug('in nusoap_parser ctor, message:');
|
6776 |
+
$this->appendDebug($this->varDump($this->message));
|
6777 |
+
$this->debug('parsed successfully, found root struct: ' . $this->root_struct . ' of name ' . $this->root_struct_name);
|
6778 |
+
// get final value
|
6779 |
+
$this->soapresponse = $this->message[$this->root_struct]['result'];
|
6780 |
+
// get header value
|
6781 |
+
if ($this->root_header != '' && isset($this->message[$this->root_header]['result'])) {
|
6782 |
+
$this->soapheader = $this->message[$this->root_header]['result'];
|
6783 |
+
}
|
6784 |
+
// resolve hrefs/ids
|
6785 |
+
if (sizeof($this->multirefs) > 0) {
|
6786 |
+
foreach ($this->multirefs as $id => $hrefs) {
|
6787 |
+
$this->debug('resolving multirefs for id: ' . $id);
|
6788 |
+
$idVal = $this->buildVal($this->ids[$id]);
|
6789 |
+
if (is_array($idVal) && isset($idVal['!id'])) {
|
6790 |
+
unset($idVal['!id']);
|
6791 |
+
}
|
6792 |
+
foreach ($hrefs as $refPos => $ref) {
|
6793 |
+
$this->debug('resolving href at pos ' . $refPos);
|
6794 |
+
$this->multirefs[$id][$refPos] = $idVal;
|
6795 |
+
}
|
6796 |
+
}
|
6797 |
+
}
|
6798 |
+
}
|
6799 |
+
xml_parser_free($this->parser);
|
6800 |
+
unset($this->parser);
|
6801 |
+
} else {
|
6802 |
+
$this->debug('xml was empty, didn\'t parse!');
|
6803 |
+
$this->setError('xml was empty, didn\'t parse!');
|
6804 |
+
}
|
6805 |
+
}
|
6806 |
+
|
6807 |
+
/**
|
6808 |
+
* start-element handler
|
6809 |
+
*
|
6810 |
+
* @param resource $parser XML parser object
|
6811 |
+
* @param string $name element name
|
6812 |
+
* @param array $attrs associative array of attributes
|
6813 |
+
* @access private
|
6814 |
+
*/
|
6815 |
+
function start_element($parser, $name, $attrs)
|
6816 |
+
{
|
6817 |
+
// position in a total number of elements, starting from 0
|
6818 |
+
// update class level pos
|
6819 |
+
$pos = $this->position++;
|
6820 |
+
// and set mine
|
6821 |
+
$this->message[$pos] = array('pos' => $pos, 'children' => '', 'cdata' => '');
|
6822 |
+
// depth = how many levels removed from root?
|
6823 |
+
// set mine as current global depth and increment global depth value
|
6824 |
+
$this->message[$pos]['depth'] = $this->depth++;
|
6825 |
+
|
6826 |
+
// else add self as child to whoever the current parent is
|
6827 |
+
if ($pos != 0) {
|
6828 |
+
$this->message[$this->parent]['children'] .= '|' . $pos;
|
6829 |
+
}
|
6830 |
+
// set my parent
|
6831 |
+
$this->message[$pos]['parent'] = $this->parent;
|
6832 |
+
// set self as current parent
|
6833 |
+
$this->parent = $pos;
|
6834 |
+
// set self as current value for this depth
|
6835 |
+
$this->depth_array[$this->depth] = $pos;
|
6836 |
+
// get element prefix
|
6837 |
+
if (strpos($name, ':')) {
|
6838 |
+
// get ns prefix
|
6839 |
+
$prefix = substr($name, 0, strpos($name, ':'));
|
6840 |
+
// get unqualified name
|
6841 |
+
$name = substr(strstr($name, ':'), 1);
|
6842 |
+
}
|
6843 |
+
// set status
|
6844 |
+
if ($name == 'Envelope' && $this->status == '') {
|
6845 |
+
$this->status = 'envelope';
|
6846 |
+
} elseif ($name == 'Header' && $this->status == 'envelope') {
|
6847 |
+
$this->root_header = $pos;
|
6848 |
+
$this->status = 'header';
|
6849 |
+
} elseif ($name == 'Body' && $this->status == 'envelope') {
|
6850 |
+
$this->status = 'body';
|
6851 |
+
$this->body_position = $pos;
|
6852 |
+
// set method
|
6853 |
+
} elseif ($this->status == 'body' && $pos == ($this->body_position + 1)) {
|
6854 |
+
$this->status = 'method';
|
6855 |
+
$this->root_struct_name = $name;
|
6856 |
+
$this->root_struct = $pos;
|
6857 |
+
$this->message[$pos]['type'] = 'struct';
|
6858 |
+
$this->debug("found root struct $this->root_struct_name, pos $this->root_struct");
|
6859 |
+
}
|
6860 |
+
// set my status
|
6861 |
+
$this->message[$pos]['status'] = $this->status;
|
6862 |
+
// set name
|
6863 |
+
$this->message[$pos]['name'] = htmlspecialchars($name);
|
6864 |
+
// set attrs
|
6865 |
+
$this->message[$pos]['attrs'] = $attrs;
|
6866 |
+
|
6867 |
+
// loop through atts, logging ns and type declarations
|
6868 |
+
$attstr = '';
|
6869 |
+
foreach ($attrs as $key => $value) {
|
6870 |
+
$key_prefix = $this->getPrefix($key);
|
6871 |
+
$key_localpart = $this->getLocalPart($key);
|
6872 |
+
// if ns declarations, add to class level array of valid namespaces
|
6873 |
+
if ($key_prefix == 'xmlns') {
|
6874 |
+
if (preg_match('/^http:\/\/www.w3.org\/[0-9]{4}\/XMLSchema$/', $value)) {
|
6875 |
+
$this->XMLSchemaVersion = $value;
|
6876 |
+
$this->namespaces['xsd'] = $this->XMLSchemaVersion;
|
6877 |
+
$this->namespaces['xsi'] = $this->XMLSchemaVersion . '-instance';
|
6878 |
+
}
|
6879 |
+
$this->namespaces[$key_localpart] = $value;
|
6880 |
+
// set method namespace
|
6881 |
+
if ($name == $this->root_struct_name) {
|
6882 |
+
$this->methodNamespace = $value;
|
6883 |
+
}
|
6884 |
+
// if it's a type declaration, set type
|
6885 |
+
} elseif ($key_localpart == 'type') {
|
6886 |
+
if (isset($this->message[$pos]['type']) && $this->message[$pos]['type'] == 'array') {
|
6887 |
+
// do nothing: already processed arrayType
|
6888 |
+
} else {
|
6889 |
+
$value_prefix = $this->getPrefix($value);
|
6890 |
+
$value_localpart = $this->getLocalPart($value);
|
6891 |
+
$this->message[$pos]['type'] = $value_localpart;
|
6892 |
+
$this->message[$pos]['typePrefix'] = $value_prefix;
|
6893 |
+
if (isset($this->namespaces[$value_prefix])) {
|
6894 |
+
$this->message[$pos]['type_namespace'] = $this->namespaces[$value_prefix];
|
6895 |
+
} elseif (isset($attrs['xmlns:' . $value_prefix])) {
|
6896 |
+
$this->message[$pos]['type_namespace'] = $attrs['xmlns:' . $value_prefix];
|
6897 |
+
}
|
6898 |
+
// should do something here with the namespace of specified type?
|
6899 |
+
}
|
6900 |
+
} elseif ($key_localpart == 'arrayType') {
|
6901 |
+
$this->message[$pos]['type'] = 'array';
|
6902 |
+
/* do arrayType ereg here
|
6903 |
+
[1] arrayTypeValue ::= atype asize
|
6904 |
+
[2] atype ::= QName rank*
|
6905 |
+
[3] rank ::= '[' (',')* ']'
|
6906 |
+
[4] asize ::= '[' length~ ']'
|
6907 |
+
[5] length ::= nextDimension* Digit+
|
6908 |
+
[6] nextDimension ::= Digit+ ','
|
6909 |
+
*/
|
6910 |
+
$expr = '/([A-Za-z0-9_]+):([A-Za-z]+[A-Za-z0-9_]+)\[([0-9]+),?([0-9]*)\]/';
|
6911 |
+
if (preg_match($expr, $value, $regs)) {
|
6912 |
+
$this->message[$pos]['typePrefix'] = $regs[1];
|
6913 |
+
$this->message[$pos]['arrayTypePrefix'] = $regs[1];
|
6914 |
+
if (isset($this->namespaces[$regs[1]])) {
|
6915 |
+
$this->message[$pos]['arrayTypeNamespace'] = $this->namespaces[$regs[1]];
|
6916 |
+
} elseif (isset($attrs['xmlns:' . $regs[1]])) {
|
6917 |
+
$this->message[$pos]['arrayTypeNamespace'] = $attrs['xmlns:' . $regs[1]];
|
6918 |
+
}
|
6919 |
+
$this->message[$pos]['arrayType'] = $regs[2];
|
6920 |
+
$this->message[$pos]['arraySize'] = $regs[3];
|
6921 |
+
$this->message[$pos]['arrayCols'] = $regs[4];
|
6922 |
+
}
|
6923 |
+
// specifies nil value (or not)
|
6924 |
+
} elseif ($key_localpart == 'nil') {
|
6925 |
+
$this->message[$pos]['nil'] = ($value == 'true' || $value == '1');
|
6926 |
+
// some other attribute
|
6927 |
+
} elseif ($key != 'href' && $key != 'xmlns' && $key_localpart != 'encodingStyle' && $key_localpart != 'root') {
|
6928 |
+
$this->message[$pos]['xattrs']['!' . $key] = $value;
|
6929 |
+
}
|
6930 |
+
|
6931 |
+
if ($key == 'xmlns') {
|
6932 |
+
$this->default_namespace = $value;
|
6933 |
+
}
|
6934 |
+
// log id
|
6935 |
+
if ($key == 'id') {
|
6936 |
+
$this->ids[$value] = $pos;
|
6937 |
+
}
|
6938 |
+
// root
|
6939 |
+
if ($key_localpart == 'root' && $value == 1) {
|
6940 |
+
$this->status = 'method';
|
6941 |
+
$this->root_struct_name = $name;
|
6942 |
+
$this->root_struct = $pos;
|
6943 |
+
$this->debug("found root struct $this->root_struct_name, pos $pos");
|
6944 |
+
}
|
6945 |
+
// for doclit
|
6946 |
+
$attstr .= " $key=\"$value\"";
|
6947 |
+
}
|
6948 |
+
// get namespace - must be done after namespace atts are processed
|
6949 |
+
if (isset($prefix)) {
|
6950 |
+
$this->message[$pos]['namespace'] = $this->namespaces[$prefix];
|
6951 |
+
$this->default_namespace = $this->namespaces[$prefix];
|
6952 |
+
} else {
|
6953 |
+
$this->message[$pos]['namespace'] = $this->default_namespace;
|
6954 |
+
}
|
6955 |
+
if ($this->status == 'header') {
|
6956 |
+
if ($this->root_header != $pos) {
|
6957 |
+
$this->responseHeaders .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
6958 |
+
}
|
6959 |
+
} elseif ($this->root_struct_name != '') {
|
6960 |
+
$this->document .= "<" . (isset($prefix) ? $prefix . ':' : '') . "$name$attstr>";
|
6961 |
+
}
|
6962 |
+
}
|
6963 |
+
|
6964 |
+
/**
|
6965 |
+
* end-element handler
|
6966 |
+
*
|
6967 |
+
* @param resource $parser XML parser object
|
6968 |
+
* @param string $name element name
|
6969 |
+
* @access private
|
6970 |
+
*/
|
6971 |
+
function end_element($parser, $name)
|
6972 |
+
{
|
6973 |
+
// position of current element is equal to the last value left in depth_array for my depth
|
6974 |
+
$pos = $this->depth_array[$this->depth--];
|
6975 |
+
|
6976 |
+
// get element prefix
|
6977 |
+
if (strpos($name, ':')) {
|
6978 |
+
// get ns prefix
|
6979 |
+
$prefix = substr($name, 0, strpos($name, ':'));
|
6980 |
+
// get unqualified name
|
6981 |
+
$name = substr(strstr($name, ':'), 1);
|
6982 |
+
}
|
6983 |
+
|
6984 |
+
// build to native type
|
6985 |
+
if (isset($this->body_position) && $pos > $this->body_position) {
|
6986 |
+
// deal w/ multirefs
|
6987 |
+
if (isset($this->message[$pos]['attrs']['href'])) {
|
6988 |
+
// get id
|
6989 |
+
$id = substr($this->message[$pos]['attrs']['href'], 1);
|
6990 |
+
// add placeholder to href array
|
6991 |
+
$this->multirefs[$id][$pos] = 'placeholder';
|
6992 |
+
// add set a reference to it as the result value
|
6993 |
+
$this->message[$pos]['result'] =& $this->multirefs[$id][$pos];
|
6994 |
+
// build complexType values
|
6995 |
+
} elseif ($this->message[$pos]['children'] != '') {
|
6996 |
+
// if result has already been generated (struct/array)
|
6997 |
+
if (!isset($this->message[$pos]['result'])) {
|
6998 |
+
$this->message[$pos]['result'] = $this->buildVal($pos);
|
6999 |
+
}
|
7000 |
+
// build complexType values of attributes and possibly simpleContent
|
7001 |
+
} elseif (isset($this->message[$pos]['xattrs'])) {
|
7002 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
7003 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
7004 |
+
} elseif (isset($this->message[$pos]['cdata']) && trim($this->message[$pos]['cdata']) != '') {
|
7005 |
+
if (isset($this->message[$pos]['type'])) {
|
7006 |
+
$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'] : '');
|
7007 |
+
} else {
|
7008 |
+
$parent = $this->message[$pos]['parent'];
|
7009 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
7010 |
+
$this->message[$pos]['xattrs']['!'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
7011 |
+
} else {
|
7012 |
+
$this->message[$pos]['xattrs']['!'] = $this->message[$pos]['cdata'];
|
7013 |
+
}
|
7014 |
+
}
|
7015 |
+
}
|
7016 |
+
$this->message[$pos]['result'] = $this->message[$pos]['xattrs'];
|
7017 |
+
// set value of simpleType (or nil complexType)
|
7018 |
+
} else {
|
7019 |
+
//$this->debug('adding data for scalar value '.$this->message[$pos]['name'].' of value '.$this->message[$pos]['cdata']);
|
7020 |
+
if (isset($this->message[$pos]['nil']) && $this->message[$pos]['nil']) {
|
7021 |
+
$this->message[$pos]['xattrs']['!'] = null;
|
7022 |
+
} elseif (isset($this->message[$pos]['type'])) {
|
7023 |
+
$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'] : '');
|
7024 |
+
} else {
|
7025 |
+
$parent = $this->message[$pos]['parent'];
|
7026 |
+
if (isset($this->message[$parent]['type']) && ($this->message[$parent]['type'] == 'array') && isset($this->message[$parent]['arrayType'])) {
|
7027 |
+
$this->message[$pos]['result'] = $this->decodeSimple($this->message[$pos]['cdata'], $this->message[$parent]['arrayType'], isset($this->message[$parent]['arrayTypeNamespace']) ? $this->message[$parent]['arrayTypeNamespace'] : '');
|
7028 |
+
} else {
|
7029 |
+
$this->message[$pos]['result'] = $this->message[$pos]['cdata'];
|
7030 |
+
}
|
7031 |
+
}
|
7032 |
+
|
7033 |
+
/* add value to parent's result, if parent is struct/array
|
7034 |
+
$parent = $this->message[$pos]['parent'];
|
7035 |
+
if($this->message[$parent]['type'] != 'map'){
|
7036 |
+
if(strtolower($this->message[$parent]['type']) == 'array'){
|
7037 |
+
$this->message[$parent]['result'][] = $this->message[$pos]['result'];
|
7038 |
+
} else {
|
7039 |
+
$this->message[$parent]['result'][$this->message[$pos]['name']] = $this->message[$pos]['result'];
|
7040 |
+
}
|
7041 |
+
}
|
7042 |
+
*/
|
7043 |
+
}
|
7044 |
+
}
|
7045 |
+
|
7046 |
+
// for doclit
|
7047 |
+
if ($this->status == 'header') {
|
7048 |
+
if ($this->root_header != $pos) {
|
7049 |
+
$this->responseHeaders .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
7050 |
+
}
|
7051 |
+
} elseif ($pos >= $this->root_struct) {
|
7052 |
+
$this->document .= "</" . (isset($prefix) ? $prefix . ':' : '') . "$name>";
|
7053 |
+
}
|
7054 |
+
// switch status
|
7055 |
+
if ($pos == $this->root_struct) {
|
7056 |
+
$this->status = 'body';
|
7057 |
+
$this->root_struct_namespace = $this->message[$pos]['namespace'];
|
7058 |
+
} elseif ($pos == $this->root_header) {
|
7059 |
+
$this->status = 'envelope';
|
7060 |
+
} elseif ($name == 'Body' && $this->status == 'body') {
|
7061 |
+
$this->status = 'envelope';
|
7062 |
+
} elseif ($name == 'Header' && $this->status == 'header') { // will never happen
|
7063 |
+
$this->status = 'envelope';
|
7064 |
+
} elseif ($name == 'Envelope' && $this->status == 'envelope') {
|
7065 |
+
$this->status = '';
|
7066 |
+
}
|
7067 |
+
// set parent back to my parent
|
7068 |
+
$this->parent = $this->message[$pos]['parent'];
|
7069 |
+
}
|
7070 |
+
|
7071 |
+
/**
|
7072 |
+
* element content handler
|
7073 |
+
*
|
7074 |
+
* @param resource $parser XML parser object
|
7075 |
+
* @param string $data element content
|
7076 |
+
* @access private
|
7077 |
+
*/
|
7078 |
+
function character_data($parser, $data)
|
7079 |
+
{
|
7080 |
+
$pos = $this->depth_array[$this->depth];
|
7081 |
+
if ($this->xml_encoding == 'UTF-8') {
|
7082 |
+
// TODO: add an option to disable this for folks who want
|
7083 |
+
// raw UTF-8 that, e.g., might not map to iso-8859-1
|
7084 |
+
// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
|
7085 |
+
if ($this->decode_utf8) {
|
7086 |
+
$data = utf8_decode($data);
|
7087 |
+
}
|
7088 |
+
}
|
7089 |
+
$this->message[$pos]['cdata'] .= $data;
|
7090 |
+
// for doclit
|
7091 |
+
if ($this->status == 'header') {
|
7092 |
+
$this->responseHeaders .= $data;
|
7093 |
+
} else {
|
7094 |
+
$this->document .= $data;
|
7095 |
+
}
|
7096 |
+
}
|
7097 |
+
|
7098 |
+
/**
|
7099 |
+
* get the parsed message (SOAP Body)
|
7100 |
+
*
|
7101 |
+
* @return mixed
|
7102 |
+
* @access public
|
7103 |
+
* @deprecated use get_soapbody instead
|
7104 |
+
*/
|
7105 |
+
function get_response()
|
7106 |
+
{
|
7107 |
+
return $this->soapresponse;
|
7108 |
+
}
|
7109 |
+
|
7110 |
+
/**
|
7111 |
+
* get the parsed SOAP Body (null if there was none)
|
7112 |
+
*
|
7113 |
+
* @return mixed
|
7114 |
+
* @access public
|
7115 |
+
*/
|
7116 |
+
function get_soapbody()
|
7117 |
+
{
|
7118 |
+
return $this->soapresponse;
|
7119 |
+
}
|
7120 |
+
|
7121 |
+
/**
|
7122 |
+
* get the parsed SOAP Header (null if there was none)
|
7123 |
+
*
|
7124 |
+
* @return mixed
|
7125 |
+
* @access public
|
7126 |
+
*/
|
7127 |
+
function get_soapheader()
|
7128 |
+
{
|
7129 |
+
return $this->soapheader;
|
7130 |
+
}
|
7131 |
+
|
7132 |
+
/**
|
7133 |
+
* get the unparsed SOAP Header
|
7134 |
+
*
|
7135 |
+
* @return string XML or empty if no Header
|
7136 |
+
* @access public
|
7137 |
+
*/
|
7138 |
+
function getHeaders()
|
7139 |
+
{
|
7140 |
+
return $this->responseHeaders;
|
7141 |
+
}
|
7142 |
+
|
7143 |
+
/**
|
7144 |
+
* decodes simple types into PHP variables
|
7145 |
+
*
|
7146 |
+
* @param string $value value to decode
|
7147 |
+
* @param string $type XML type to decode
|
7148 |
+
* @param string $typens XML type namespace to decode
|
7149 |
+
* @return mixed PHP value
|
7150 |
+
* @access private
|
7151 |
+
*/
|
7152 |
+
function decodeSimple($value, $type, $typens)
|
7153 |
+
{
|
7154 |
+
// TODO: use the namespace!
|
7155 |
+
if ((!isset($type)) || $type == 'string' || $type == 'long' || $type == 'unsignedLong') {
|
7156 |
+
return (string) $value;
|
7157 |
+
}
|
7158 |
+
if ($type == 'int' || $type == 'integer' || $type == 'short' || $type == 'byte') {
|
7159 |
+
return (int) $value;
|
7160 |
+
}
|
7161 |
+
if ($type == 'float' || $type == 'double' || $type == 'decimal') {
|
7162 |
+
return (double) $value;
|
7163 |
+
}
|
7164 |
+
if ($type == 'boolean') {
|
7165 |
+
if (strtolower($value) == 'false' || strtolower($value) == 'f') {
|
7166 |
+
return false;
|
7167 |
+
}
|
7168 |
+
return (boolean) $value;
|
7169 |
+
}
|
7170 |
+
if ($type == 'base64' || $type == 'base64Binary') {
|
7171 |
+
$this->debug('Decode base64 value');
|
7172 |
+
return base64_decode($value);
|
7173 |
+
}
|
7174 |
+
// obscure numeric types
|
7175 |
+
if ($type == 'nonPositiveInteger' || $type == 'negativeInteger'
|
7176 |
+
|| $type == 'nonNegativeInteger' || $type == 'positiveInteger'
|
7177 |
+
|| $type == 'unsignedInt'
|
7178 |
+
|| $type == 'unsignedShort' || $type == 'unsignedByte'
|
7179 |
+
) {
|
7180 |
+
return (int) $value;
|
7181 |
+
}
|
7182 |
+
// bogus: parser treats array with no elements as a simple type
|
7183 |
+
if ($type == 'array') {
|
7184 |
+
return array();
|
7185 |
+
}
|
7186 |
+
// everything else
|
7187 |
+
return (string) $value;
|
7188 |
+
}
|
7189 |
+
|
7190 |
+
/**
|
7191 |
+
* builds response structures for compound values (arrays/structs)
|
7192 |
+
* and scalars
|
7193 |
+
*
|
7194 |
+
* @param integer $pos position in node tree
|
7195 |
+
* @return mixed PHP value
|
7196 |
+
* @access private
|
7197 |
+
*/
|
7198 |
+
function buildVal($pos)
|
7199 |
+
{
|
7200 |
+
if (!isset($this->message[$pos]['type'])) {
|
7201 |
+
$this->message[$pos]['type'] = '';
|
7202 |
+
}
|
7203 |
+
$this->debug('in buildVal() for ' . $this->message[$pos]['name'] . "(pos $pos) of type " . $this->message[$pos]['type']);
|
7204 |
+
// if there are children...
|
7205 |
+
if ($this->message[$pos]['children'] != '') {
|
7206 |
+
$this->debug('in buildVal, there are children');
|
7207 |
+
$children = explode('|', $this->message[$pos]['children']);
|
7208 |
+
array_shift($children); // knoc
|