Cleantalk_Antispam - Version 1.2.2

Version Notes

Fixed login form checking.
Changed connection test method.

Download this release

Release Info

Developer CleanTalk.Org
Extension Cleantalk_Antispam
Version 1.2.2
Comparing to
See all releases


Code changes from version 1.2.0 to 1.2.2

Files changed (23) hide show
  1. app/code/community/Cleantalk/Antispam/Block/Antispam.php +0 -0
  2. app/code/community/Cleantalk/Antispam/Block/adminhtml/Notifications.php +17 -17
  3. app/code/community/Cleantalk/Antispam/Helper/Data.php +0 -0
  4. app/code/community/Cleantalk/Antispam/Model/Api.php +1 -1
  5. app/code/community/Cleantalk/Antispam/Model/Observer.php +239 -243
  6. app/code/community/Cleantalk/Antispam/Model/Resource/Server.php +0 -0
  7. app/code/community/Cleantalk/Antispam/Model/Resource/Timelabels.php +0 -0
  8. app/code/community/Cleantalk/Antispam/Model/Review.php +0 -0
  9. app/code/community/Cleantalk/Antispam/Model/Server.php +0 -0
  10. app/code/community/Cleantalk/Antispam/Model/Timelabels.php +0 -0
  11. app/code/community/Cleantalk/Antispam/Model/error.html +53 -53
  12. app/code/community/Cleantalk/Antispam/Model/lib/JSON.php +806 -806
  13. app/code/community/Cleantalk/Antispam/Model/lib/cleantalk.class.php +1095 -1062
  14. app/code/community/Cleantalk/Antispam/controllers/Contacts/IndexController.php +0 -0
  15. app/code/community/Cleantalk/Antispam/controllers/Customer/AccountController.php +0 -0
  16. app/code/community/Cleantalk/Antispam/etc/config.xml +1 -1
  17. app/code/community/Cleantalk/Antispam/etc/system.xml +0 -0
  18. app/code/community/Cleantalk/Antispam/sql/cleantalk_antispam_setup/{install-0.9.2.php → install-1.2.1.php} +0 -0
  19. app/design/adminhtml/default/default/layout/cleantalk/antispam.xml +0 -0
  20. app/design/frontend/base/default/layout/antispam.xml +0 -0
  21. app/design/frontend/base/default/template/cleantalk/antispam/page_addon.phtml +0 -0
  22. app/etc/modules/Cleantalk_Antispam.xml +1 -1
  23. package.xml +6 -6
app/code/community/Cleantalk/Antispam/Block/Antispam.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Block/adminhtml/Notifications.php CHANGED
@@ -1,18 +1,18 @@
1
- <?php
2
- class Cleantalk_Antispam_Block_Adminhtml_Notifications extends Mage_Adminhtml_Block_Template
3
- {
4
- public function getMessage()
5
- {
6
- /*
7
- * Here you have check if there's a message to be displayed or not
8
- */
9
- $show_notice=intval(Mage::getStoreConfig('general/cleantalk/show_notice'));
10
- $message='';
11
- if($show_notice==1)
12
- {
13
- $message = "Like Anti-spam by CleanTalk? Help others learn about CleanTalk! <a target='_blank' href='http://www.magentocommerce.com/magento-connect/antispam-by-cleantalk.html'>Leave a review at the Magento Connect</a> <a href='?close_notice=1' style='float:right;'>Close</a>";
14
- }
15
- return $message;
16
- }
17
- }
18
  ?>
1
+ <?php
2
+ class Cleantalk_Antispam_Block_Adminhtml_Notifications extends Mage_Adminhtml_Block_Template
3
+ {
4
+ public function getMessage()
5
+ {
6
+ /*
7
+ * Here you have check if there's a message to be displayed or not
8
+ */
9
+ $show_notice=intval(Mage::getStoreConfig('general/cleantalk/show_notice'));
10
+ $message='';
11
+ if($show_notice==1)
12
+ {
13
+ $message = "Like Anti-spam by CleanTalk? Help others learn about CleanTalk! <a target='_blank' href='http://www.magentocommerce.com/magento-connect/antispam-by-cleantalk.html'>Leave a review at the Magento Connect</a> <a href='?close_notice=1' style='float:right;'>Close</a>";
14
+ }
15
+ return $message;
16
+ }
17
+ }
18
  ?>
app/code/community/Cleantalk/Antispam/Helper/Data.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/Api.php CHANGED
@@ -114,7 +114,7 @@ ctSetCookie("%s", "%s");
114
  $ct_request->sender_email = isset($arEntity['sender_email']) ? $arEntity['sender_email'] : '';
115
  $ct_request->sender_nickname = isset($arEntity['sender_nickname']) ? $arEntity['sender_nickname'] : '';
116
  $ct_request->sender_ip = isset($arEntity['sender_ip']) ? $arEntity['sender_ip'] : $sender_ip;
117
- $ct_request->agent = 'magento-120';
118
  $ct_request->js_on = $checkjs;
119
  $ct_request->sender_info = $sender_info;
120
 
114
  $ct_request->sender_email = isset($arEntity['sender_email']) ? $arEntity['sender_email'] : '';
115
  $ct_request->sender_nickname = isset($arEntity['sender_nickname']) ? $arEntity['sender_nickname'] : '';
116
  $ct_request->sender_ip = isset($arEntity['sender_ip']) ? $arEntity['sender_ip'] : $sender_ip;
117
+ $ct_request->agent = 'magento-122';
118
  $ct_request->js_on = $checkjs;
119
  $ct_request->sender_info = $sender_info;
120
 
app/code/community/Cleantalk/Antispam/Model/Observer.php CHANGED
@@ -1,244 +1,240 @@
1
- <?php
2
-
3
- class Cleantalk_Antispam_Model_Observer
4
- {
5
- public function interceptOutput(Varien_Event_Observer $observer)
6
- {
7
- $transport = $observer->getTransport();
8
- $html = $transport->getHtml();
9
- if(strpos($html,'<div class="middle"')!==false&&isset($_GET['cleantalk_message']))
10
- {
11
- $html=str_replace('<div class="middle"','<div class="notification-global notification-global-error"><b>CleanTalk error: '.$_GET['cleantalk_message'].'</b></div><div class="middle"',$html);
12
- $transport->setHtml($html);
13
- }
14
- $show_notice=intval(Mage::getStoreConfig('general/cleantalk/show_notice'));
15
- if(strpos($html,'<div class="middle"')!==false&&$show_notice==1)
16
- {
17
- $message = "Like Anti-spam by CleanTalk? Help others learn about CleanTalk! <a target='_blank' href='http://www.magentocommerce.com/magento-connect/antispam-by-cleantalk.html'>Leave a review at the Magento Connect</a> <a href='?close_notice=1' style='float:right;'>Close</a>";
18
- $html=str_replace('<div class="middle"','<div class="notification-global notification-global-notice">'.$message.'</div><div class="middle"',$html);
19
- $transport->setHtml($html);
20
- }
21
- if(strpos($html,'%LINK_TEXT%')!==false)
22
- {
23
- $api_key = Mage::getStoreConfig('general/cleantalk/api_key');
24
- if(trim($api_key)=='')
25
- {
26
- Mage::app()->cleanCache();
27
- $admin_email=Mage::getStoreConfig('trans_email/ident_general/email');
28
- $button="<input type='button' style='margin-top:5px;-webkit-border-bottom-left-radius: 5px;-webkit-border-bottom-right-radius: 5px;-webkit-border-radius: 5px;-webkit-border-top-left-radius: 5px;-webkit-border-top-right-radius: 5px;background: #3399FF;border-radius: 5px;box-sizing: border-box;color: #FFFFFF;font: normal normal 400 14px/16.2px \"Open Sans\";padding:3px;border:0px none;cursor:pointer;' value='Get access key automatically' onclick='location.href=\"?get_auto_key=1\"'><br /><a target='_blank' href='https://cleantalk.org/register?platform=magento&email=".$admin_email."&website=".$_SERVER['HTTP_HOST']."'>Click here to get access key manually</a><br />Admin e-mail (".$admin_email.") will be used for registration<br /><a target='__blank' href='http://cleantalk.org/publicoffer' style='color:#e5e5e5'>License agreement</a>";
29
- $html=str_replace('%LINK_TEXT%',$button,$html);
30
- }
31
- else
32
- {
33
- $html=str_replace('%LINK_TEXT%',"<a target='__blank' href='http://cleantalk.org/my' >Click here to get anti-spam statistics</a>",$html);
34
- }
35
- $transport->setHtml($html);
36
- }
37
-
38
- }
39
- public function interceptQuery(Varien_Event_Observer $observer)
40
- {
41
- if(isset($_GET['close_notice']))
42
- {
43
- $config = new Mage_Core_Model_Config();
44
- $config->saveConfig('general/cleantalk/show_notice', 0, 'default', 0);
45
- Mage::app()->cleanCache();
46
- header('Location: .');
47
- die();
48
- }
49
-
50
- if(isset($_GET['get_auto_key']))
51
- {
52
- Mage::getSingleton('core/session', array('name'=>'adminhtml'));
53
- if(Mage::getSingleton('admin/session')->isLoggedIn())
54
- {
55
- require_once 'lib/cleantalk.class.php';
56
- $admin_email=Mage::getStoreConfig('trans_email/ident_general/email');
57
- $site=$_SERVER['HTTP_HOST'];
58
- $result = getAutoKey($admin_email,$site,'magento');
59
- if ($result)
60
- {
61
- $result = json_decode($result, true);
62
- if (isset($result['data']) && is_array($result['data']))
63
- {
64
- $result = $result['data'];
65
- }
66
- else if(isset($result['error_no']))
67
- {
68
- header('Location: ?cleantalk_message='.$result['error_message']);
69
- die();
70
- }
71
- if(isset($result['auth_key']))
72
- {
73
- Mage::app()->cleanCache();
74
- $config = new Mage_Core_Model_Config();
75
- $config->saveConfig('general/cleantalk/api_key', $result['auth_key'], 'default', 0);
76
- Cleantalk_Antispam_Model_Observer::CleantalkTestMessage($result['auth_key']);
77
- }
78
- header('Location: .');
79
- die();
80
- }
81
- }
82
- }
83
-
84
- if(isset($_POST['groups']['cleantalk']['fields']['api_key']['value']))
85
- {
86
- $new_key=$_POST['groups']['cleantalk']['fields']['api_key']['value'];
87
- $old_key = Mage::getStoreConfig('general/cleantalk/api_key');
88
- if($old_key!=$new_key&&$new_key!='')
89
- {
90
- Cleantalk_Antispam_Model_Observer::CleantalkTestMessage($new_key);
91
- }
92
- }
93
-
94
- $isCustomForms = Mage::getStoreConfig('general/cleantalk/custom_forms');
95
- //Mage::getSingleton('core/session', array('name'=>'adminhtml'));
96
- if(isset($_COOKIE['adminhtml']))
97
- {
98
- $key=Mage::getStoreConfig('general/cleantalk/api_key');
99
- $last_checked=intval(Mage::getStoreConfig('general/cleantalk/last_checked'));
100
- $last_status=intval(Mage::getStoreConfig('general/cleantalk/is_paid'));
101
- $new_checked=time();
102
-
103
- if($key!='')
104
- {
105
- $new_status=$last_status;
106
- if($new_checked-$last_checked>3600)
107
- {
108
- require_once 'lib/cleantalk.class.php';
109
- $url = 'https://api.cleantalk.org';
110
- $dt=Array(
111
- 'auth_key'=>$key,
112
- 'method_name'=> 'get_account_status');
113
- $result=sendRawRequest($url,$dt,false);
114
- if($result!==null)
115
- {
116
- $result=json_decode($result);
117
- if(isset($result->data)&&isset($result->data->paid))
118
- {
119
- $new_status=intval($result->data->paid);
120
- if($last_status!=1&&$new_status==1)
121
- {
122
- $config = new Mage_Core_Model_Config();
123
- $config->saveConfig('general/cleantalk/is_paid', '1', 'default', 0);
124
- $config->saveConfig('general/cleantalk/show_notice', '1', 'default', 0);
125
- Mage::app()->cleanCache();
126
- }
127
- }
128
- }
129
- $config = new Mage_Core_Model_Config();
130
- $config->saveConfig('general/cleantalk/last_checked', $new_checked, 'default', 0);
131
- }
132
- }
133
- }
134
- if(!isset($_COOKIE['adminhtml'])&&$isCustomForms==1&&sizeof($_POST)>0)
135
- {
136
-
137
- $sender_email = null;
138
- $message = '';
139
- Cleantalk_Antispam_Model_Observer::cleantalkGetFields($sender_email,$message,$_POST);
140
- if($sender_email!==null)
141
- {
142
- $aMessage = array();
143
- $aMessage['type'] = 'comment';
144
- $aMessage['sender_email'] = $sender_email;
145
- $aMessage['sender_nickname'] = '';
146
- $aMessage['message_title'] = '';
147
- $aMessage['message_body'] = $message;
148
- $aMessage['example_title'] = '';
149
- $aMessage['example_body'] = '';
150
- $aMessage['example_comments'] = '';
151
-
152
- $model = Mage::getModel('antispam/api');
153
- $aResult = $model->CheckSpam($aMessage, FALSE);
154
-
155
- if(isset($aResult) && is_array($aResult))
156
- {
157
- if($aResult['errno'] == 0)
158
- {
159
- if($aResult['allow'] == 0)
160
- {
161
- if (preg_match('//u', $aResult['ct_result_comment']))
162
- {
163
- $comment_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $aResult['ct_result_comment']);
164
- $comment_str = preg_replace('/<[^<>]*>/iu', '', $comment_str);
165
- }
166
- else
167
- {
168
- $comment_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $aResult['ct_result_comment']);
169
- $comment_str = preg_replace('/<[^<>]*>/i', '', $comment_str);
170
- }
171
- Mage::getModel('antispam/api')->CleantalkDie($comment_str);
172
- }
173
- }
174
- }
175
- }
176
- }
177
- }
178
-
179
-
180
- /*
181
- * Sends test message when api key is changed
182
- */
183
- public function CleantalkTestMessage($key)
184
- {
185
- require_once 'lib/cleantalk.class.php';
186
- $url = 'http://moderate.cleantalk.org/api2.0';
187
- $dt=Array(
188
- 'auth_key'=>$key,
189
- 'method_name'=> 'check_message',
190
- 'message'=>'CleanTalk connection test',
191
- 'example'=>null,
192
- 'agent'=>'magento-120',
193
- 'sender_ip'=>$_SERVER['REMOTE_ADDR'],
194
- 'sender_email'=>'stop_email@example.com',
195
- 'sender_nickname'=>'CleanTalk',
196
- 'js_on'=>1);
197
- $result=sendRawRequest($url,$dt,true);
198
- return $result;
199
- }
200
-
201
- /**
202
- * Get all fields from array
203
- * @param string email variable
204
- * @param string message variable
205
- * @param array array, containing fields
206
- */
207
-
208
- static function cleantalkGetFields(&$email,&$message,$arr)
209
- {
210
- $is_continue=true;
211
- foreach($arr as $key=>$value)
212
- {
213
- if(strpos($key,'ct_checkjs')!==false)
214
- {
215
- $email=null;
216
- $message='';
217
- $is_continue=false;
218
- }
219
- }
220
- if($is_continue)
221
- {
222
- foreach($arr as $key=>$value)
223
- {
224
- if(!is_array($value))
225
- {
226
- if ($email === null && preg_match("/^\S+@\S+\.\S+$/", $value))
227
- {
228
- $email = $value;
229
- }
230
- else
231
- {
232
- $message.="$value\n";
233
- }
234
- }
235
- else
236
- {
237
- Cleantalk_Antispam_Model_Observer::cleantalkGetFields($email,$message,$value);
238
- }
239
- }
240
- }
241
- }
242
- }
243
-
244
  ?>
1
+ <?php
2
+
3
+ class Cleantalk_Antispam_Model_Observer
4
+ {
5
+ public function interceptOutput(Varien_Event_Observer $observer)
6
+ {
7
+ $transport = $observer->getTransport();
8
+ $html = $transport->getHtml();
9
+ if(strpos($html,'<div class="middle"')!==false&&isset($_GET['cleantalk_message']))
10
+ {
11
+ $html=str_replace('<div class="middle"','<div class="notification-global notification-global-error"><b>CleanTalk error: '.$_GET['cleantalk_message'].'</b></div><div class="middle"',$html);
12
+ $transport->setHtml($html);
13
+ }
14
+ $show_notice=intval(Mage::getStoreConfig('general/cleantalk/show_notice'));
15
+ if(strpos($html,'<div class="middle"')!==false&&$show_notice==1)
16
+ {
17
+ $message = "Like Anti-spam by CleanTalk? Help others learn about CleanTalk! <a target='_blank' href='http://www.magentocommerce.com/magento-connect/antispam-by-cleantalk.html'>Leave a review at the Magento Connect</a> <a href='?close_notice=1' style='float:right;'>Close</a>";
18
+ $html=str_replace('<div class="middle"','<div class="notification-global notification-global-notice">'.$message.'</div><div class="middle"',$html);
19
+ $transport->setHtml($html);
20
+ }
21
+ if(strpos($html,'%LINK_TEXT%')!==false)
22
+ {
23
+ $api_key = Mage::getStoreConfig('general/cleantalk/api_key');
24
+ if(trim($api_key)=='')
25
+ {
26
+ Mage::app()->cleanCache();
27
+ $admin_email=Mage::getStoreConfig('trans_email/ident_general/email');
28
+ $button="<input type='button' style='margin-top:5px;-webkit-border-bottom-left-radius: 5px;-webkit-border-bottom-right-radius: 5px;-webkit-border-radius: 5px;-webkit-border-top-left-radius: 5px;-webkit-border-top-right-radius: 5px;background: #3399FF;border-radius: 5px;box-sizing: border-box;color: #FFFFFF;font: normal normal 400 14px/16.2px \"Open Sans\";padding:3px;border:0px none;cursor:pointer;' value='Get access key automatically' onclick='location.href=\"?get_auto_key=1\"'><br /><a target='_blank' href='https://cleantalk.org/register?platform=magento&email=".$admin_email."&website=".$_SERVER['HTTP_HOST']."'>Click here to get access key manually</a><br />Admin e-mail (".$admin_email.") will be used for registration<br /><a target='__blank' href='http://cleantalk.org/publicoffer' style='color:#e5e5e5'>License agreement</a>";
29
+ $html=str_replace('%LINK_TEXT%',$button,$html);
30
+ }
31
+ else
32
+ {
33
+ $html=str_replace('%LINK_TEXT%',"<a target='__blank' href='http://cleantalk.org/my' >Click here to get anti-spam statistics</a>",$html);
34
+ }
35
+ $transport->setHtml($html);
36
+ }
37
+
38
+ }
39
+ public function interceptQuery(Varien_Event_Observer $observer)
40
+ {
41
+ if(isset($_GET['close_notice']))
42
+ {
43
+ $config = new Mage_Core_Model_Config();
44
+ $config->saveConfig('general/cleantalk/show_notice', 0, 'default', 0);
45
+ Mage::app()->cleanCache();
46
+ header('Location: .');
47
+ die();
48
+ }
49
+
50
+ if(isset($_GET['get_auto_key']))
51
+ {
52
+ Mage::getSingleton('core/session', array('name'=>'adminhtml'));
53
+ if(Mage::getSingleton('admin/session')->isLoggedIn())
54
+ {
55
+ require_once 'lib/cleantalk.class.php';
56
+ $admin_email=Mage::getStoreConfig('trans_email/ident_general/email');
57
+ $site=$_SERVER['HTTP_HOST'];
58
+ $result = getAutoKey($admin_email,$site,'magento');
59
+ if ($result)
60
+ {
61
+ $result = json_decode($result, true);
62
+ if (isset($result['data']) && is_array($result['data']))
63
+ {
64
+ $result = $result['data'];
65
+ }
66
+ else if(isset($result['error_no']))
67
+ {
68
+ header('Location: ?cleantalk_message='.$result['error_message']);
69
+ die();
70
+ }
71
+ if(isset($result['auth_key']))
72
+ {
73
+ Mage::app()->cleanCache();
74
+ $config = new Mage_Core_Model_Config();
75
+ $config->saveConfig('general/cleantalk/api_key', $result['auth_key'], 'default', 0);
76
+ Cleantalk_Antispam_Model_Observer::CleantalkTestMessage($result['auth_key']);
77
+ }
78
+ header('Location: .');
79
+ die();
80
+ }
81
+ }
82
+ }
83
+
84
+ if(isset($_POST['groups']['cleantalk']['fields']['api_key']['value']))
85
+ {
86
+ $new_key=$_POST['groups']['cleantalk']['fields']['api_key']['value'];
87
+ $old_key = Mage::getStoreConfig('general/cleantalk/api_key');
88
+ if($old_key!=$new_key&&$new_key!='')
89
+ {
90
+ Cleantalk_Antispam_Model_Observer::CleantalkTestMessage($new_key);
91
+ }
92
+ }
93
+
94
+ //Mage::getSingleton('core/session', array('name'=>'adminhtml'));
95
+ if(isset($_COOKIE['adminhtml']))
96
+ {
97
+ $key=Mage::getStoreConfig('general/cleantalk/api_key');
98
+ $last_checked=intval(Mage::getStoreConfig('general/cleantalk/last_checked'));
99
+ $last_status=intval(Mage::getStoreConfig('general/cleantalk/is_paid'));
100
+ $new_checked=time();
101
+
102
+ if($key!='')
103
+ {
104
+ $new_status=$last_status;
105
+ if($new_checked-$last_checked>3600)
106
+ {
107
+ require_once 'lib/cleantalk.class.php';
108
+ $url = 'https://api.cleantalk.org';
109
+ $dt=Array(
110
+ 'auth_key'=>$key,
111
+ 'method_name'=> 'get_account_status');
112
+ $result=sendRawRequest($url,$dt,false);
113
+ if($result!==null)
114
+ {
115
+ $result=json_decode($result);
116
+ if(isset($result->data)&&isset($result->data->paid))
117
+ {
118
+ $new_status=intval($result->data->paid);
119
+ if($last_status!=1&&$new_status==1)
120
+ {
121
+ $config = new Mage_Core_Model_Config();
122
+ $config->saveConfig('general/cleantalk/is_paid', '1', 'default', 0);
123
+ $config->saveConfig('general/cleantalk/show_notice', '1', 'default', 0);
124
+ Mage::app()->cleanCache();
125
+ }
126
+ }
127
+ }
128
+ $config = new Mage_Core_Model_Config();
129
+ $config->saveConfig('general/cleantalk/last_checked', $new_checked, 'default', 0);
130
+ }
131
+ }
132
+ }
133
+ if(!isset($_COOKIE['adminhtml'])&&sizeof($_POST)>0&&strpos($_SERVER['REQUEST_URI'],'login')===false&&strpos($_SERVER['REQUEST_URI'],'forgotpassword')===false)
134
+ {
135
+ $isCustomForms = Mage::getStoreConfig('general/cleantalk/custom_forms');
136
+ if($isCustomForms==1)
137
+ {
138
+ $sender_email = null;
139
+ $message = '';
140
+ Cleantalk_Antispam_Model_Observer::cleantalkGetFields($sender_email,$message,$_POST);
141
+ if($sender_email!==null)
142
+ {
143
+ $aMessage = array();
144
+ $aMessage['type'] = 'comment';
145
+ $aMessage['sender_email'] = $sender_email;
146
+ $aMessage['sender_nickname'] = '';
147
+ $aMessage['message_title'] = '';
148
+ $aMessage['message_body'] = $message;
149
+ $aMessage['example_title'] = '';
150
+ $aMessage['example_body'] = '';
151
+ $aMessage['example_comments'] = '';
152
+
153
+ $model = Mage::getModel('antispam/api');
154
+ $aResult = $model->CheckSpam($aMessage, FALSE);
155
+
156
+ if(isset($aResult) && is_array($aResult))
157
+ {
158
+ if($aResult['errno'] == 0)
159
+ {
160
+ if($aResult['allow'] == 0)
161
+ {
162
+ if (preg_match('//u', $aResult['ct_result_comment']))
163
+ {
164
+ $comment_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/iu', '', $aResult['ct_result_comment']);
165
+ $comment_str = preg_replace('/<[^<>]*>/iu', '', $comment_str);
166
+ }
167
+ else
168
+ {
169
+ $comment_str = preg_replace('/^[^\*]*?\*\*\*|\*\*\*[^\*]*?$/i', '', $aResult['ct_result_comment']);
170
+ $comment_str = preg_replace('/<[^<>]*>/i', '', $comment_str);
171
+ }
172
+ Mage::getModel('antispam/api')->CleantalkDie($comment_str);
173
+ }
174
+ }
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
+
182
+ /*
183
+ * Sends test message when api key is changed
184
+ */
185
+ public function CleantalkTestMessage($key)
186
+ {
187
+ require_once 'lib/cleantalk.class.php';
188
+ $url = 'http://moderate.cleantalk.org/api2.0';
189
+ $dt=Array(
190
+ 'auth_key'=>$_POST['cleantalk_authkey'],
191
+ 'method_name' => 'send_feedback',
192
+ 'feedback' => 0 . ':' . 'magento-122');
193
+ $result=sendRawRequest($url,$dt,true);
194
+ return $result;
195
+ }
196
+
197
+ /**
198
+ * Get all fields from array
199
+ * @param string email variable
200
+ * @param string message variable
201
+ * @param array array, containing fields
202
+ */
203
+
204
+ static function cleantalkGetFields(&$email,&$message,$arr)
205
+ {
206
+ $is_continue=true;
207
+ foreach($arr as $key=>$value)
208
+ {
209
+ if(strpos($key,'ct_checkjs')!==false)
210
+ {
211
+ $email=null;
212
+ $message='';
213
+ $is_continue=false;
214
+ }
215
+ }
216
+ if($is_continue)
217
+ {
218
+ foreach($arr as $key=>$value)
219
+ {
220
+ if(!is_array($value))
221
+ {
222
+ if ($email === null && preg_match("/^\S+@\S+\.\S+$/", $value))
223
+ {
224
+ $email = $value;
225
+ }
226
+ else
227
+ {
228
+ $message.="$value\n";
229
+ }
230
+ }
231
+ else
232
+ {
233
+ Cleantalk_Antispam_Model_Observer::cleantalkGetFields($email,$message,$value);
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+
 
 
 
 
240
  ?>
app/code/community/Cleantalk/Antispam/Model/Resource/Server.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/Resource/Timelabels.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/Review.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/Server.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/Timelabels.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/Model/error.html CHANGED
@@ -1,54 +1,54 @@
1
- <!DOCTYPE html>
2
- <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono
3
- -->
4
- <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
5
- <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
- <title>Blacklisted</title>
8
- <style type="text/css">
9
- html {
10
- background: #f1f1f1;
11
- }
12
- body {
13
- background: #fff;
14
- color: #444;
15
- font-family: "Open Sans", sans-serif;
16
- margin: 2em auto;
17
- padding: 1em 2em;
18
- max-width: 700px;
19
- -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
20
- box-shadow: 0 1px 3px rgba(0,0,0,0.13);
21
- }
22
- h1 {
23
- border-bottom: 1px solid #dadada;
24
- clear: both;
25
- color: #666;
26
- font: 24px "Open Sans", sans-serif;
27
- margin: 30px 0 0 0;
28
- padding: 0;
29
- padding-bottom: 7px;
30
- }
31
- #error-page {
32
- margin-top: 50px;
33
- }
34
- #error-page p {
35
- font-size: 14px;
36
- line-height: 1.5;
37
- margin: 25px 0 20px;
38
- }
39
- a {
40
- color: #21759B;
41
- text-decoration: none;
42
- }
43
- a:hover {
44
- color: #D54E21;
45
- }
46
-
47
- </style>
48
- </head>
49
- <body id="error-page">
50
- <p><center><b style="color: #49C73B;">Clean</b><b style="color: #349ebf;">Talk.</b> Spam protection</center><br><br>
51
- %ERROR_TEXT%
52
- <script>setTimeout("history.back()", 5000);</script></p>
53
- <p><a href='javascript:history.back()'>&laquo; Back</a></p></body>
54
  </html>
1
+ <!DOCTYPE html>
2
+ <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono
3
+ -->
4
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>Blacklisted</title>
8
+ <style type="text/css">
9
+ html {
10
+ background: #f1f1f1;
11
+ }
12
+ body {
13
+ background: #fff;
14
+ color: #444;
15
+ font-family: "Open Sans", sans-serif;
16
+ margin: 2em auto;
17
+ padding: 1em 2em;
18
+ max-width: 700px;
19
+ -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
20
+ box-shadow: 0 1px 3px rgba(0,0,0,0.13);
21
+ }
22
+ h1 {
23
+ border-bottom: 1px solid #dadada;
24
+ clear: both;
25
+ color: #666;
26
+ font: 24px "Open Sans", sans-serif;
27
+ margin: 30px 0 0 0;
28
+ padding: 0;
29
+ padding-bottom: 7px;
30
+ }
31
+ #error-page {
32
+ margin-top: 50px;
33
+ }
34
+ #error-page p {
35
+ font-size: 14px;
36
+ line-height: 1.5;
37
+ margin: 25px 0 20px;
38
+ }
39
+ a {
40
+ color: #21759B;
41
+ text-decoration: none;
42
+ }
43
+ a:hover {
44
+ color: #D54E21;
45
+ }
46
+
47
+ </style>
48
+ </head>
49
+ <body id="error-page">
50
+ <p><center><b style="color: #49C73B;">Clean</b><b style="color: #349ebf;">Talk.</b> Spam protection</center><br><br>
51
+ %ERROR_TEXT%
52
+ <script>setTimeout("history.back()", 5000);</script></p>
53
+ <p><a href='javascript:history.back()'>&laquo; Back</a></p></body>
54
  </html>
app/code/community/Cleantalk/Antispam/Model/lib/JSON.php CHANGED
@@ -1,806 +1,806 @@
1
- <?php
2
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
-
4
- /**
5
- * Converts to and from JSON format.
6
- *
7
- * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
- * format. It is easy for humans to read and write. It is easy for machines
9
- * to parse and generate. It is based on a subset of the JavaScript
10
- * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
- * This feature can also be found in Python. JSON is a text format that is
12
- * completely language independent but uses conventions that are familiar
13
- * to programmers of the C-family of languages, including C, C++, C#, Java,
14
- * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
- * ideal data-interchange language.
16
- *
17
- * This package provides a simple encoder and decoder for JSON notation. It
18
- * is intended for use with client-side Javascript applications that make
19
- * use of HTTPRequest to perform server communication functions - data can
20
- * be encoded into JSON notation for use in a client-side javascript, or
21
- * decoded from incoming Javascript requests. JSON format is native to
22
- * Javascript, and can be directly eval()'ed with no further parsing
23
- * overhead
24
- *
25
- * All strings should be in ASCII or UTF-8 format!
26
- *
27
- * LICENSE: Redistribution and use in source and binary forms, with or
28
- * without modification, are permitted provided that the following
29
- * conditions are met: Redistributions of source code must retain the
30
- * above copyright notice, this list of conditions and the following
31
- * disclaimer. Redistributions in binary form must reproduce the above
32
- * copyright notice, this list of conditions and the following disclaimer
33
- * in the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
- * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
- * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
- * DAMAGE.
47
- *
48
- * @category
49
- * @package Services_JSON
50
- * @author Michal Migurski <mike-json@teczno.com>
51
- * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
- * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
- * @copyright 2005 Michal Migurski
54
- * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
- * @license http://www.opensource.org/licenses/bsd-license.php
56
- * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
- */
58
-
59
- /**
60
- * Marker constant for Services_JSON::decode(), used to flag stack state
61
- */
62
- define('SERVICES_JSON_SLICE', 1);
63
-
64
- /**
65
- * Marker constant for Services_JSON::decode(), used to flag stack state
66
- */
67
- define('SERVICES_JSON_IN_STR', 2);
68
-
69
- /**
70
- * Marker constant for Services_JSON::decode(), used to flag stack state
71
- */
72
- define('SERVICES_JSON_IN_ARR', 3);
73
-
74
- /**
75
- * Marker constant for Services_JSON::decode(), used to flag stack state
76
- */
77
- define('SERVICES_JSON_IN_OBJ', 4);
78
-
79
- /**
80
- * Marker constant for Services_JSON::decode(), used to flag stack state
81
- */
82
- define('SERVICES_JSON_IN_CMT', 5);
83
-
84
- /**
85
- * Behavior switch for Services_JSON::decode()
86
- */
87
- define('SERVICES_JSON_LOOSE_TYPE', 16);
88
-
89
- /**
90
- * Behavior switch for Services_JSON::decode()
91
- */
92
- define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
-
94
- /**
95
- * Converts to and from JSON format.
96
- *
97
- * Brief example of use:
98
- *
99
- * <code>
100
- * // create a new instance of Services_JSON
101
- * $json = new Services_JSON();
102
- *
103
- * // convert a complexe value to JSON notation, and send it to the browser
104
- * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
- * $output = $json->encode($value);
106
- *
107
- * print($output);
108
- * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
- *
110
- * // accept incoming POST data, assumed to be in JSON notation
111
- * $input = file_get_contents('php://input', 1000000);
112
- * $value = $json->decode($input);
113
- * </code>
114
- */
115
- class Services_JSON
116
- {
117
- /**
118
- * constructs a new JSON instance
119
- *
120
- * @param int $use object behavior flags; combine with boolean-OR
121
- *
122
- * possible values:
123
- * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
- * "{...}" syntax creates associative arrays
125
- * instead of objects in decode().
126
- * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
- * Values which can't be encoded (e.g. resources)
128
- * appear as NULL instead of throwing errors.
129
- * By default, a deeply-nested resource will
130
- * bubble up with an error, so all return values
131
- * from encode() should be checked with isError()
132
- */
133
- function Services_JSON($use = 0)
134
- {
135
- $this->use = $use;
136
- }
137
-
138
- /**
139
- * convert a string from one UTF-16 char to one UTF-8 char
140
- *
141
- * Normally should be handled by mb_convert_encoding, but
142
- * provides a slower PHP-only method for installations
143
- * that lack the multibye string extension.
144
- *
145
- * @param string $utf16 UTF-16 character
146
- * @return string UTF-8 character
147
- * @access private
148
- */
149
- function utf162utf8($utf16)
150
- {
151
- // oh please oh please oh please oh please oh please
152
- if(function_exists('mb_convert_encoding')) {
153
- return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
- }
155
-
156
- $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
157
-
158
- switch(true) {
159
- case ((0x7F & $bytes) == $bytes):
160
- // this case should never be reached, because we are in ASCII range
161
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
- return chr(0x7F & $bytes);
163
-
164
- case (0x07FF & $bytes) == $bytes:
165
- // return a 2-byte UTF-8 character
166
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
- return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
- . chr(0x80 | ($bytes & 0x3F));
169
-
170
- case (0xFFFF & $bytes) == $bytes:
171
- // return a 3-byte UTF-8 character
172
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
- return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
- . chr(0x80 | (($bytes >> 6) & 0x3F))
175
- . chr(0x80 | ($bytes & 0x3F));
176
- }
177
-
178
- // ignoring UTF-32 for now, sorry
179
- return '';
180
- }
181
-
182
- /**
183
- * convert a string from one UTF-8 char to one UTF-16 char
184
- *
185
- * Normally should be handled by mb_convert_encoding, but
186
- * provides a slower PHP-only method for installations
187
- * that lack the multibye string extension.
188
- *
189
- * @param string $utf8 UTF-8 character
190
- * @return string UTF-16 character
191
- * @access private
192
- */
193
- function utf82utf16($utf8)
194
- {
195
- // oh please oh please oh please oh please oh please
196
- if(function_exists('mb_convert_encoding')) {
197
- return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
- }
199
-
200
- switch(strlen($utf8)) {
201
- case 1:
202
- // this case should never be reached, because we are in ASCII range
203
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
- return $utf8;
205
-
206
- case 2:
207
- // return a UTF-16 character from a 2-byte UTF-8 char
208
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
- return chr(0x07 & (ord($utf8{0}) >> 2))
210
- . chr((0xC0 & (ord($utf8{0}) << 6))
211
- | (0x3F & ord($utf8{1})));
212
-
213
- case 3:
214
- // return a UTF-16 character from a 3-byte UTF-8 char
215
- // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
- return chr((0xF0 & (ord($utf8{0}) << 4))
217
- | (0x0F & (ord($utf8{1}) >> 2)))
218
- . chr((0xC0 & (ord($utf8{1}) << 6))
219
- | (0x7F & ord($utf8{2})));
220
- }
221
-
222
- // ignoring UTF-32 for now, sorry
223
- return '';
224
- }
225
-
226
- /**
227
- * encodes an arbitrary variable into JSON format
228
- *
229
- * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
- * see argument 1 to Services_JSON() above for array-parsing behavior.
231
- * if var is a strng, note that encode() always expects it
232
- * to be in ASCII or UTF-8 format!
233
- *
234
- * @return mixed JSON string representation of input var or an error if a problem occurs
235
- * @access public
236
- */
237
- function encode($var)
238
- {
239
- switch (gettype($var)) {
240
- case 'boolean':
241
- return $var ? 'true' : 'false';
242
-
243
- case 'NULL':
244
- return 'null';
245
-
246
- case 'integer':
247
- return (int) $var;
248
-
249
- case 'double':
250
- case 'float':
251
- return (float) $var;
252
-
253
- case 'string':
254
- // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
255
- $ascii = '';
256
- $strlen_var = strlen($var);
257
-
258
- /*
259
- * Iterate over every character in the string,
260
- * escaping with a slash or encoding to UTF-8 where necessary
261
- */
262
- for ($c = 0; $c < $strlen_var; ++$c) {
263
-
264
- $ord_var_c = ord($var{$c});
265
-
266
- switch (true) {
267
- case $ord_var_c == 0x08:
268
- $ascii .= '\b';
269
- break;
270
- case $ord_var_c == 0x09:
271
- $ascii .= '\t';
272
- break;
273
- case $ord_var_c == 0x0A:
274
- $ascii .= '\n';
275
- break;
276
- case $ord_var_c == 0x0C:
277
- $ascii .= '\f';
278
- break;
279
- case $ord_var_c == 0x0D:
280
- $ascii .= '\r';
281
- break;
282
-
283
- case $ord_var_c == 0x22:
284
- case $ord_var_c == 0x2F:
285
- case $ord_var_c == 0x5C:
286
- // double quote, slash, slosh
287
- $ascii .= '\\'.$var{$c};
288
- break;
289
-
290
- case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
291
- // characters U-00000000 - U-0000007F (same as ASCII)
292
- $ascii .= $var{$c};
293
- break;
294
-
295
- case (($ord_var_c & 0xE0) == 0xC0):
296
- // characters U-00000080 - U-000007FF, mask 110XXXXX
297
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
298
- $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
299
- $c += 1;
300
- $utf16 = $this->utf82utf16($char);
301
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
302
- break;
303
-
304
- case (($ord_var_c & 0xF0) == 0xE0):
305
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
306
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
307
- $char = pack('C*', $ord_var_c,
308
- ord($var{$c + 1}),
309
- ord($var{$c + 2}));
310
- $c += 2;
311
- $utf16 = $this->utf82utf16($char);
312
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
313
- break;
314
-
315
- case (($ord_var_c & 0xF8) == 0xF0):
316
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
317
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
318
- $char = pack('C*', $ord_var_c,
319
- ord($var{$c + 1}),
320
- ord($var{$c + 2}),
321
- ord($var{$c + 3}));
322
- $c += 3;
323
- $utf16 = $this->utf82utf16($char);
324
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
325
- break;
326
-
327
- case (($ord_var_c & 0xFC) == 0xF8):
328
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
329
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
- $char = pack('C*', $ord_var_c,
331
- ord($var{$c + 1}),
332
- ord($var{$c + 2}),
333
- ord($var{$c + 3}),
334
- ord($var{$c + 4}));
335
- $c += 4;
336
- $utf16 = $this->utf82utf16($char);
337
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
338
- break;
339
-
340
- case (($ord_var_c & 0xFE) == 0xFC):
341
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
342
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
343
- $char = pack('C*', $ord_var_c,
344
- ord($var{$c + 1}),
345
- ord($var{$c + 2}),
346
- ord($var{$c + 3}),
347
- ord($var{$c + 4}),
348
- ord($var{$c + 5}));
349
- $c += 5;
350
- $utf16 = $this->utf82utf16($char);
351
- $ascii .= sprintf('\u%04s', bin2hex($utf16));
352
- break;
353
- }
354
- }
355
-
356
- return '"'.$ascii.'"';
357
-
358
- case 'array':
359
- /*
360
- * As per JSON spec if any array key is not an integer
361
- * we must treat the the whole array as an object. We
362
- * also try to catch a sparsely populated associative
363
- * array with numeric keys here because some JS engines
364
- * will create an array with empty indexes up to
365
- * max_index which can cause memory issues and because
366
- * the keys, which may be relevant, will be remapped
367
- * otherwise.
368
- *
369
- * As per the ECMA and JSON specification an object may
370
- * have any string as a property. Unfortunately due to
371
- * a hole in the ECMA specification if the key is a
372
- * ECMA reserved word or starts with a digit the
373
- * parameter is only accessible using ECMAScript's
374
- * bracket notation.
375
- */
376
-
377
- // treat as a JSON object
378
- if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
379
- $properties = array_map(array($this, 'name_value'),
380
- array_keys($var),
381
- array_values($var));
382
-
383
- foreach($properties as $property) {
384
- if(Services_JSON::isError($property)) {
385
- return $property;
386
- }
387
- }
388
-
389
- return '{' . join(',', $properties) . '}';
390
- }
391
-
392
- // treat it like a regular array
393
- $elements = array_map(array($this, 'encode'), $var);
394
-
395
- foreach($elements as $element) {
396
- if(Services_JSON::isError($element)) {
397
- return $element;
398
- }
399
- }
400
-
401
- return '[' . join(',', $elements) . ']';
402
-
403
- case 'object':
404
- $vars = get_object_vars($var);
405
-
406
- $properties = array_map(array($this, 'name_value'),
407
- array_keys($vars),
408
- array_values($vars));
409
-
410
- foreach($properties as $property) {
411
- if(Services_JSON::isError($property)) {
412
- return $property;
413
- }
414
- }
415
-
416
- return '{' . join(',', $properties) . '}';
417
-
418
- default:
419
- return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
420
- ? 'null'
421
- : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
422
- }
423
- }
424
-
425
- /**
426
- * array-walking function for use in generating JSON-formatted name-value pairs
427
- *
428
- * @param string $name name of key to use
429
- * @param mixed $value reference to an array element to be encoded
430
- *
431
- * @return string JSON-formatted name-value pair, like '"name":value'
432
- * @access private
433
- */
434
- function name_value($name, $value)
435
- {
436
- $encoded_value = $this->encode($value);
437
-
438
- if(Services_JSON::isError($encoded_value)) {
439
- return $encoded_value;
440
- }
441
-
442
- return $this->encode(strval($name)) . ':' . $encoded_value;
443
- }
444
-
445
- /**
446
- * reduce a string by removing leading and trailing comments and whitespace
447
- *
448
- * @param $str string string value to strip of comments and whitespace
449
- *
450
- * @return string string value stripped of comments and whitespace
451
- * @access private
452
- */
453
- function reduce_string($str)
454
- {
455
- $str = preg_replace(array(
456
-
457
- // eliminate single line comments in '// ...' form
458
- '#^\s*//(.+)$#m',
459
-
460
- // eliminate multi-line comments in '/* ... */' form, at start of string
461
- '#^\s*/\*(.+)\*/#Us',
462
-
463
- // eliminate multi-line comments in '/* ... */' form, at end of string
464
- '#/\*(.+)\*/\s*$#Us'
465
-
466
- ), '', $str);
467
-
468
- // eliminate extraneous space
469
- return trim($str);
470
- }
471
-
472
- /**
473
- * decodes a JSON string into appropriate variable
474
- *
475
- * @param string $str JSON-formatted string
476
- *
477
- * @return mixed number, boolean, string, array, or object
478
- * corresponding to given JSON input string.
479
- * See argument 1 to Services_JSON() above for object-output behavior.
480
- * Note that decode() always returns strings
481
- * in ASCII or UTF-8 format!
482
- * @access public
483
- */
484
- function decode($str)
485
- {
486
- $str = $this->reduce_string($str);
487
-
488
- switch (strtolower($str)) {
489
- case 'true':
490
- return true;
491
-
492
- case 'false':
493
- return false;
494
-
495
- case 'null':
496
- return null;
497
-
498
- default:
499
- $m = array();
500
-
501
- if (is_numeric($str)) {
502
- // Lookie-loo, it's a number
503
-
504
- // This would work on its own, but I'm trying to be
505
- // good about returning integers where appropriate:
506
- // return (float)$str;
507
-
508
- // Return float or int, as appropriate
509
- return ((float)$str == (integer)$str)
510
- ? (integer)$str
511
- : (float)$str;
512
-
513
- } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
514
- // STRINGS RETURNED IN UTF-8 FORMAT
515
- $delim = substr($str, 0, 1);
516
- $chrs = substr($str, 1, -1);
517
- $utf8 = '';
518
- $strlen_chrs = strlen($chrs);
519
-
520
- for ($c = 0; $c < $strlen_chrs; ++$c) {
521
-
522
- $substr_chrs_c_2 = substr($chrs, $c, 2);
523
- $ord_chrs_c = ord($chrs{$c});
524
-
525
- switch (true) {
526
- case $substr_chrs_c_2 == '\b':
527
- $utf8 .= chr(0x08);
528
- ++$c;
529
- break;
530
- case $substr_chrs_c_2 == '\t':
531
- $utf8 .= chr(0x09);
532
- ++$c;
533
- break;
534
- case $substr_chrs_c_2 == '\n':
535
- $utf8 .= chr(0x0A);
536
- ++$c;
537
- break;
538
- case $substr_chrs_c_2 == '\f':
539
- $utf8 .= chr(0x0C);
540
- ++$c;
541
- break;
542
- case $substr_chrs_c_2 == '\r':
543
- $utf8 .= chr(0x0D);
544
- ++$c;
545
- break;
546
-
547
- case $substr_chrs_c_2 == '\\"':
548
- case $substr_chrs_c_2 == '\\\'':
549
- case $substr_chrs_c_2 == '\\\\':
550
- case $substr_chrs_c_2 == '\\/':
551
- if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
552
- ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
553
- $utf8 .= $chrs{++$c};
554
- }
555
- break;
556
-
557
- case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
558
- // single, escaped unicode character
559
- $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
560
- . chr(hexdec(substr($chrs, ($c + 4), 2)));
561
- $utf8 .= $this->utf162utf8($utf16);
562
- $c += 5;
563
- break;
564
-
565
- case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
566
- $utf8 .= $chrs{$c};
567
- break;
568
-
569
- case ($ord_chrs_c & 0xE0) == 0xC0:
570
- // characters U-00000080 - U-000007FF, mask 110XXXXX
571
- //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
572
- $utf8 .= substr($chrs, $c, 2);
573
- ++$c;
574
- break;
575
-
576
- case ($ord_chrs_c & 0xF0) == 0xE0:
577
- // characters U-00000800 - U-0000FFFF, mask 1110XXXX
578
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
579
- $utf8 .= substr($chrs, $c, 3);
580
- $c += 2;
581
- break;
582
-
583
- case ($ord_chrs_c & 0xF8) == 0xF0:
584
- // characters U-00010000 - U-001FFFFF, mask 11110XXX
585
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
586
- $utf8 .= substr($chrs, $c, 4);
587
- $c += 3;
588
- break;
589
-
590
- case ($ord_chrs_c & 0xFC) == 0xF8:
591
- // characters U-00200000 - U-03FFFFFF, mask 111110XX
592
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
593
- $utf8 .= substr($chrs, $c, 5);
594
- $c += 4;
595
- break;
596
-
597
- case ($ord_chrs_c & 0xFE) == 0xFC:
598
- // characters U-04000000 - U-7FFFFFFF, mask 1111110X
599
- // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
600
- $utf8 .= substr($chrs, $c, 6);
601
- $c += 5;
602
- break;
603
-
604
- }
605
-
606
- }
607
-
608
- return $utf8;
609
-
610
- } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
611
- // array, or object notation
612
-
613
- if ($str{0} == '[') {
614
- $stk = array(SERVICES_JSON_IN_ARR);
615
- $arr = array();
616
- } else {
617
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
618
- $stk = array(SERVICES_JSON_IN_OBJ);
619
- $obj = array();
620
- } else {
621
- $stk = array(SERVICES_JSON_IN_OBJ);
622
- $obj = new stdClass();
623
- }
624
- }
625
-
626
- array_push($stk, array('what' => SERVICES_JSON_SLICE,
627
- 'where' => 0,
628
- 'delim' => false));
629
-
630
- $chrs = substr($str, 1, -1);
631
- $chrs = $this->reduce_string($chrs);
632
-
633
- if ($chrs == '') {
634
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
635
- return $arr;
636
-
637
- } else {
638
- return $obj;
639
-
640
- }
641
- }
642
-
643
- //print("\nparsing {$chrs}\n");
644
-
645
- $strlen_chrs = strlen($chrs);
646
-
647
- for ($c = 0; $c <= $strlen_chrs; ++$c) {
648
-
649
- $top = end($stk);
650
- $substr_chrs_c_2 = substr($chrs, $c, 2);
651
-
652
- if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
653
- // found a comma that is not inside a string, array, etc.,
654
- // OR we've reached the end of the character list
655
- $slice = substr($chrs, $top['where'], ($c - $top['where']));
656
- array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
657
- //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
658
-
659
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
660
- // we are in an array, so just push an element onto the stack
661
- array_push($arr, $this->decode($slice));
662
-
663
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
664
- // we are in an object, so figure
665
- // out the property name and set an
666
- // element in an associative array,
667
- // for now
668
- $parts = array();
669
-
670
- if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
671
- // "name":value pair
672
- $key = $this->decode($parts[1]);
673
- $val = $this->decode($parts[2]);
674
-
675
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
676
- $obj[$key] = $val;
677
- } else {
678
- $obj->$key = $val;
679
- }
680
- } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
681
- // name:value pair, where name is unquoted
682
- $key = $parts[1];
683
- $val = $this->decode($parts[2]);
684
-
685
- if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
686
- $obj[$key] = $val;
687
- } else {
688
- $obj->$key = $val;
689
- }
690
- }
691
-
692
- }
693
-
694
- } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
695
- // found a quote, and we are not inside a string
696
- array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
697
- //print("Found start of string at {$c}\n");
698
-
699
- } elseif (($chrs{$c} == $top['delim']) &&
700
- ($top['what'] == SERVICES_JSON_IN_STR) &&
701
- ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
702
- // found a quote, we're in a string, and it's not escaped
703
- // we know that it's not escaped becase there is _not_ an
704
- // odd number of backslashes at the end of the string so far
705
- array_pop($stk);
706
- //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
707
-
708
- } elseif (($chrs{$c} == '[') &&
709
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
710
- // found a left-bracket, and we are in an array, object, or slice
711
- array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
712
- //print("Found start of array at {$c}\n");
713
-
714
- } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
715
- // found a right-bracket, and we're in an array
716
- array_pop($stk);
717
- //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
718
-
719
- } elseif (($chrs{$c} == '{') &&
720
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
721
- // found a left-brace, and we are in an array, object, or slice
722
- array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
723
- //print("Found start of object at {$c}\n");
724
-
725
- } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
726
- // found a right-brace, and we're in an object
727
- array_pop($stk);
728
- //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
729
-
730
- } elseif (($substr_chrs_c_2 == '/*') &&
731
- in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
732
- // found a comment start, and we are in an array, object, or slice
733
- array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
734
- $c++;
735
- //print("Found start of comment at {$c}\n");
736
-
737
- } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
738
- // found a comment end, and we're in one now
739
- array_pop($stk);
740
- $c++;
741
-
742
- for ($i = $top['where']; $i <= $c; ++$i)
743
- $chrs = substr_replace($chrs, ' ', $i, 1);
744
-
745
- //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
746
-
747
- }
748
-
749
- }
750
-
751
- if (reset($stk) == SERVICES_JSON_IN_ARR) {
752
- return $arr;
753
-
754
- } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
755
- return $obj;
756
-
757
- }
758
-
759
- }
760
- }
761
- }
762
-
763
- /**
764
- * @todo Ultimately, this should just call PEAR::isError()
765
- */
766
- function isError($data, $code = null)
767
- {
768
- if (class_exists('pear')) {
769
- return PEAR::isError($data, $code);
770
- } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
771
- is_subclass_of($data, 'services_json_error'))) {
772
- return true;
773
- }
774
-
775
- return false;
776
- }
777
- }
778
-
779
- if (class_exists('PEAR_Error')) {
780
-
781
- class Services_JSON_Error extends PEAR_Error
782
- {
783
- function Services_JSON_Error($message = 'unknown error', $code = null,
784
- $mode = null, $options = null, $userinfo = null)
785
- {
786
- parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
787
- }
788
- }
789
-
790
- } else {
791
-
792
- /**
793
- * @todo Ultimately, this class shall be descended from PEAR_Error
794
- */
795
- class Services_JSON_Error
796
- {
797
- function Services_JSON_Error($message = 'unknown error', $code = null,
798
- $mode = null, $options = null, $userinfo = null)
799
- {
800
-
801
- }
802
- }
803
-
804
- }
805
-
806
- ?>
1
+ <?php
2
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
+
4
+ /**
5
+ * Converts to and from JSON format.
6
+ *
7
+ * JSON (JavaScript Object Notation) is a lightweight data-interchange
8
+ * format. It is easy for humans to read and write. It is easy for machines
9
+ * to parse and generate. It is based on a subset of the JavaScript
10
+ * Programming Language, Standard ECMA-262 3rd Edition - December 1999.
11
+ * This feature can also be found in Python. JSON is a text format that is
12
+ * completely language independent but uses conventions that are familiar
13
+ * to programmers of the C-family of languages, including C, C++, C#, Java,
14
+ * JavaScript, Perl, TCL, and many others. These properties make JSON an
15
+ * ideal data-interchange language.
16
+ *
17
+ * This package provides a simple encoder and decoder for JSON notation. It
18
+ * is intended for use with client-side Javascript applications that make
19
+ * use of HTTPRequest to perform server communication functions - data can
20
+ * be encoded into JSON notation for use in a client-side javascript, or
21
+ * decoded from incoming Javascript requests. JSON format is native to
22
+ * Javascript, and can be directly eval()'ed with no further parsing
23
+ * overhead
24
+ *
25
+ * All strings should be in ASCII or UTF-8 format!
26
+ *
27
+ * LICENSE: Redistribution and use in source and binary forms, with or
28
+ * without modification, are permitted provided that the following
29
+ * conditions are met: Redistributions of source code must retain the
30
+ * above copyright notice, this list of conditions and the following
31
+ * disclaimer. Redistributions in binary form must reproduce the above
32
+ * copyright notice, this list of conditions and the following disclaimer
33
+ * in the documentation and/or other materials provided with the
34
+ * distribution.
35
+ *
36
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
37
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
38
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
39
+ * NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
40
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
41
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
42
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
45
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46
+ * DAMAGE.
47
+ *
48
+ * @category
49
+ * @package Services_JSON
50
+ * @author Michal Migurski <mike-json@teczno.com>
51
+ * @author Matt Knapp <mdknapp[at]gmail[dot]com>
52
+ * @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
53
+ * @copyright 2005 Michal Migurski
54
+ * @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
55
+ * @license http://www.opensource.org/licenses/bsd-license.php
56
+ * @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
57
+ */
58
+
59
+ /**
60
+ * Marker constant for Services_JSON::decode(), used to flag stack state
61
+ */
62
+ define('SERVICES_JSON_SLICE', 1);
63
+
64
+ /**
65
+ * Marker constant for Services_JSON::decode(), used to flag stack state
66
+ */
67
+ define('SERVICES_JSON_IN_STR', 2);
68
+
69
+ /**
70
+ * Marker constant for Services_JSON::decode(), used to flag stack state
71
+ */
72
+ define('SERVICES_JSON_IN_ARR', 3);
73
+
74
+ /**
75
+ * Marker constant for Services_JSON::decode(), used to flag stack state
76
+ */
77
+ define('SERVICES_JSON_IN_OBJ', 4);
78
+
79
+ /**
80
+ * Marker constant for Services_JSON::decode(), used to flag stack state
81
+ */
82
+ define('SERVICES_JSON_IN_CMT', 5);
83
+
84
+ /**
85
+ * Behavior switch for Services_JSON::decode()
86
+ */
87
+ define('SERVICES_JSON_LOOSE_TYPE', 16);
88
+
89
+ /**
90
+ * Behavior switch for Services_JSON::decode()
91
+ */
92
+ define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
93
+
94
+ /**
95
+ * Converts to and from JSON format.
96
+ *
97
+ * Brief example of use:
98
+ *
99
+ * <code>
100
+ * // create a new instance of Services_JSON
101
+ * $json = new Services_JSON();
102
+ *
103
+ * // convert a complexe value to JSON notation, and send it to the browser
104
+ * $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
105
+ * $output = $json->encode($value);
106
+ *
107
+ * print($output);
108
+ * // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
109
+ *
110
+ * // accept incoming POST data, assumed to be in JSON notation
111
+ * $input = file_get_contents('php://input', 1000000);
112
+ * $value = $json->decode($input);
113
+ * </code>
114
+ */
115
+ class Services_JSON
116
+ {
117
+ /**
118
+ * constructs a new JSON instance
119
+ *
120
+ * @param int $use object behavior flags; combine with boolean-OR
121
+ *
122
+ * possible values:
123
+ * - SERVICES_JSON_LOOSE_TYPE: loose typing.
124
+ * "{...}" syntax creates associative arrays
125
+ * instead of objects in decode().
126
+ * - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
127
+ * Values which can't be encoded (e.g. resources)
128
+ * appear as NULL instead of throwing errors.
129
+ * By default, a deeply-nested resource will
130
+ * bubble up with an error, so all return values
131
+ * from encode() should be checked with isError()
132
+ */
133
+ function Services_JSON($use = 0)
134
+ {
135
+ $this->use = $use;
136
+ }
137
+
138
+ /**
139
+ * convert a string from one UTF-16 char to one UTF-8 char
140
+ *
141
+ * Normally should be handled by mb_convert_encoding, but
142
+ * provides a slower PHP-only method for installations
143
+ * that lack the multibye string extension.
144
+ *
145
+ * @param string $utf16 UTF-16 character
146
+ * @return string UTF-8 character
147
+ * @access private
148
+ */
149
+ function utf162utf8($utf16)
150
+ {
151
+ // oh please oh please oh please oh please oh please
152
+ if(function_exists('mb_convert_encoding')) {
153
+ return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
154
+ }
155
+
156
+ $bytes = (ord($utf16{0}) << 8) | ord($utf16{1});
157
+
158
+ switch(true) {
159
+ case ((0x7F & $bytes) == $bytes):
160
+ // this case should never be reached, because we are in ASCII range
161
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
162
+ return chr(0x7F & $bytes);
163
+
164
+ case (0x07FF & $bytes) == $bytes:
165
+ // return a 2-byte UTF-8 character
166
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
167
+ return chr(0xC0 | (($bytes >> 6) & 0x1F))
168
+ . chr(0x80 | ($bytes & 0x3F));
169
+
170
+ case (0xFFFF & $bytes) == $bytes:
171
+ // return a 3-byte UTF-8 character
172
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
173
+ return chr(0xE0 | (($bytes >> 12) & 0x0F))
174
+ . chr(0x80 | (($bytes >> 6) & 0x3F))
175
+ . chr(0x80 | ($bytes & 0x3F));
176
+ }
177
+
178
+ // ignoring UTF-32 for now, sorry
179
+ return '';
180
+ }
181
+
182
+ /**
183
+ * convert a string from one UTF-8 char to one UTF-16 char
184
+ *
185
+ * Normally should be handled by mb_convert_encoding, but
186
+ * provides a slower PHP-only method for installations
187
+ * that lack the multibye string extension.
188
+ *
189
+ * @param string $utf8 UTF-8 character
190
+ * @return string UTF-16 character
191
+ * @access private
192
+ */
193
+ function utf82utf16($utf8)
194
+ {
195
+ // oh please oh please oh please oh please oh please
196
+ if(function_exists('mb_convert_encoding')) {
197
+ return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
198
+ }
199
+
200
+ switch(strlen($utf8)) {
201
+ case 1:
202
+ // this case should never be reached, because we are in ASCII range
203
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
204
+ return $utf8;
205
+
206
+ case 2:
207
+ // return a UTF-16 character from a 2-byte UTF-8 char
208
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
209
+ return chr(0x07 & (ord($utf8{0}) >> 2))
210
+ . chr((0xC0 & (ord($utf8{0}) << 6))
211
+ | (0x3F & ord($utf8{1})));
212
+
213
+ case 3:
214
+ // return a UTF-16 character from a 3-byte UTF-8 char
215
+ // see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
216
+ return chr((0xF0 & (ord($utf8{0}) << 4))
217
+ | (0x0F & (ord($utf8{1}) >> 2)))
218
+ . chr((0xC0 & (ord($utf8{1}) << 6))
219
+ | (0x7F & ord($utf8{2})));
220
+ }
221
+
222
+ // ignoring UTF-32 for now, sorry
223
+ return '';
224
+ }
225
+
226
+ /**
227
+ * encodes an arbitrary variable into JSON format
228
+ *
229
+ * @param mixed $var any number, boolean, string, array, or object to be encoded.
230
+ * see argument 1 to Services_JSON() above for array-parsing behavior.
231
+ * if var is a strng, note that encode() always expects it
232
+ * to be in ASCII or UTF-8 format!
233
+ *
234
+ * @return mixed JSON string representation of input var or an error if a problem occurs
235
+ * @access public
236
+ */
237
+ function encode($var)
238
+ {
239
+ switch (gettype($var)) {
240
+ case 'boolean':
241
+ return $var ? 'true' : 'false';
242
+
243
+ case 'NULL':
244
+ return 'null';
245
+
246
+ case 'integer':
247
+ return (int) $var;
248
+
249
+ case 'double':
250
+ case 'float':
251
+ return (float) $var;
252
+
253
+ case 'string':
254
+ // STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
255
+ $ascii = '';
256
+ $strlen_var = strlen($var);
257
+
258
+ /*
259
+ * Iterate over every character in the string,
260
+ * escaping with a slash or encoding to UTF-8 where necessary
261
+ */
262
+ for ($c = 0; $c < $strlen_var; ++$c) {
263
+
264
+ $ord_var_c = ord($var{$c});
265
+
266
+ switch (true) {
267
+ case $ord_var_c == 0x08:
268
+ $ascii .= '\b';
269
+ break;
270
+ case $ord_var_c == 0x09:
271
+ $ascii .= '\t';
272
+ break;
273
+ case $ord_var_c == 0x0A:
274
+ $ascii .= '\n';
275
+ break;
276
+ case $ord_var_c == 0x0C:
277
+ $ascii .= '\f';
278
+ break;
279
+ case $ord_var_c == 0x0D:
280
+ $ascii .= '\r';
281
+ break;
282
+
283
+ case $ord_var_c == 0x22:
284
+ case $ord_var_c == 0x2F:
285
+ case $ord_var_c == 0x5C:
286
+ // double quote, slash, slosh
287
+ $ascii .= '\\'.$var{$c};
288
+ break;
289
+
290
+ case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
291
+ // characters U-00000000 - U-0000007F (same as ASCII)
292
+ $ascii .= $var{$c};
293
+ break;
294
+
295
+ case (($ord_var_c & 0xE0) == 0xC0):
296
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
297
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
298
+ $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
299
+ $c += 1;
300
+ $utf16 = $this->utf82utf16($char);
301
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
302
+ break;
303
+
304
+ case (($ord_var_c & 0xF0) == 0xE0):
305
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
306
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
307
+ $char = pack('C*', $ord_var_c,
308
+ ord($var{$c + 1}),
309
+ ord($var{$c + 2}));
310
+ $c += 2;
311
+ $utf16 = $this->utf82utf16($char);
312
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
313
+ break;
314
+
315
+ case (($ord_var_c & 0xF8) == 0xF0):
316
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
317
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
318
+ $char = pack('C*', $ord_var_c,
319
+ ord($var{$c + 1}),
320
+ ord($var{$c + 2}),
321
+ ord($var{$c + 3}));
322
+ $c += 3;
323
+ $utf16 = $this->utf82utf16($char);
324
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
325
+ break;
326
+
327
+ case (($ord_var_c & 0xFC) == 0xF8):
328
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
329
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
330
+ $char = pack('C*', $ord_var_c,
331
+ ord($var{$c + 1}),
332
+ ord($var{$c + 2}),
333
+ ord($var{$c + 3}),
334
+ ord($var{$c + 4}));
335
+ $c += 4;
336
+ $utf16 = $this->utf82utf16($char);
337
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
338
+ break;
339
+
340
+ case (($ord_var_c & 0xFE) == 0xFC):
341
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
342
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
343
+ $char = pack('C*', $ord_var_c,
344
+ ord($var{$c + 1}),
345
+ ord($var{$c + 2}),
346
+ ord($var{$c + 3}),
347
+ ord($var{$c + 4}),
348
+ ord($var{$c + 5}));
349
+ $c += 5;
350
+ $utf16 = $this->utf82utf16($char);
351
+ $ascii .= sprintf('\u%04s', bin2hex($utf16));
352
+ break;
353
+ }
354
+ }
355
+
356
+ return '"'.$ascii.'"';
357
+
358
+ case 'array':
359
+ /*
360
+ * As per JSON spec if any array key is not an integer
361
+ * we must treat the the whole array as an object. We
362
+ * also try to catch a sparsely populated associative
363
+ * array with numeric keys here because some JS engines
364
+ * will create an array with empty indexes up to
365
+ * max_index which can cause memory issues and because
366
+ * the keys, which may be relevant, will be remapped
367
+ * otherwise.
368
+ *
369
+ * As per the ECMA and JSON specification an object may
370
+ * have any string as a property. Unfortunately due to
371
+ * a hole in the ECMA specification if the key is a
372
+ * ECMA reserved word or starts with a digit the
373
+ * parameter is only accessible using ECMAScript's
374
+ * bracket notation.
375
+ */
376
+
377
+ // treat as a JSON object
378
+ if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
379
+ $properties = array_map(array($this, 'name_value'),
380
+ array_keys($var),
381
+ array_values($var));
382
+
383
+ foreach($properties as $property) {
384
+ if(Services_JSON::isError($property)) {
385
+ return $property;
386
+ }
387
+ }
388
+
389
+ return '{' . join(',', $properties) . '}';
390
+ }
391
+
392
+ // treat it like a regular array
393
+ $elements = array_map(array($this, 'encode'), $var);
394
+
395
+ foreach($elements as $element) {
396
+ if(Services_JSON::isError($element)) {
397
+ return $element;
398
+ }
399
+ }
400
+
401
+ return '[' . join(',', $elements) . ']';
402
+
403
+ case 'object':
404
+ $vars = get_object_vars($var);
405
+
406
+ $properties = array_map(array($this, 'name_value'),
407
+ array_keys($vars),
408
+ array_values($vars));
409
+
410
+ foreach($properties as $property) {
411
+ if(Services_JSON::isError($property)) {
412
+ return $property;
413
+ }
414
+ }
415
+
416
+ return '{' . join(',', $properties) . '}';
417
+
418
+ default:
419
+ return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
420
+ ? 'null'
421
+ : new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
422
+ }
423
+ }
424
+
425
+ /**
426
+ * array-walking function for use in generating JSON-formatted name-value pairs
427
+ *
428
+ * @param string $name name of key to use
429
+ * @param mixed $value reference to an array element to be encoded
430
+ *
431
+ * @return string JSON-formatted name-value pair, like '"name":value'
432
+ * @access private
433
+ */
434
+ function name_value($name, $value)
435
+ {
436
+ $encoded_value = $this->encode($value);
437
+
438
+ if(Services_JSON::isError($encoded_value)) {
439
+ return $encoded_value;
440
+ }
441
+
442
+ return $this->encode(strval($name)) . ':' . $encoded_value;
443
+ }
444
+
445
+ /**
446
+ * reduce a string by removing leading and trailing comments and whitespace
447
+ *
448
+ * @param $str string string value to strip of comments and whitespace
449
+ *
450
+ * @return string string value stripped of comments and whitespace
451
+ * @access private
452
+ */
453
+ function reduce_string($str)
454
+ {
455
+ $str = preg_replace(array(
456
+
457
+ // eliminate single line comments in '// ...' form
458
+ '#^\s*//(.+)$#m',
459
+
460
+ // eliminate multi-line comments in '/* ... */' form, at start of string
461
+ '#^\s*/\*(.+)\*/#Us',
462
+
463
+ // eliminate multi-line comments in '/* ... */' form, at end of string
464
+ '#/\*(.+)\*/\s*$#Us'
465
+
466
+ ), '', $str);
467
+
468
+ // eliminate extraneous space
469
+ return trim($str);
470
+ }
471
+
472
+ /**
473
+ * decodes a JSON string into appropriate variable
474
+ *
475
+ * @param string $str JSON-formatted string
476
+ *
477
+ * @return mixed number, boolean, string, array, or object
478
+ * corresponding to given JSON input string.
479
+ * See argument 1 to Services_JSON() above for object-output behavior.
480
+ * Note that decode() always returns strings
481
+ * in ASCII or UTF-8 format!
482
+ * @access public
483
+ */
484
+ function decode($str)
485
+ {
486
+ $str = $this->reduce_string($str);
487
+
488
+ switch (strtolower($str)) {
489
+ case 'true':
490
+ return true;
491
+
492
+ case 'false':
493
+ return false;
494
+
495
+ case 'null':
496
+ return null;
497
+
498
+ default:
499
+ $m = array();
500
+
501
+ if (is_numeric($str)) {
502
+ // Lookie-loo, it's a number
503
+
504
+ // This would work on its own, but I'm trying to be
505
+ // good about returning integers where appropriate:
506
+ // return (float)$str;
507
+
508
+ // Return float or int, as appropriate
509
+ return ((float)$str == (integer)$str)
510
+ ? (integer)$str
511
+ : (float)$str;
512
+
513
+ } elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
514
+ // STRINGS RETURNED IN UTF-8 FORMAT
515
+ $delim = substr($str, 0, 1);
516
+ $chrs = substr($str, 1, -1);
517
+ $utf8 = '';
518
+ $strlen_chrs = strlen($chrs);
519
+
520
+ for ($c = 0; $c < $strlen_chrs; ++$c) {
521
+
522
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
523
+ $ord_chrs_c = ord($chrs{$c});
524
+
525
+ switch (true) {
526
+ case $substr_chrs_c_2 == '\b':
527
+ $utf8 .= chr(0x08);
528
+ ++$c;
529
+ break;
530
+ case $substr_chrs_c_2 == '\t':
531
+ $utf8 .= chr(0x09);
532
+ ++$c;
533
+ break;
534
+ case $substr_chrs_c_2 == '\n':
535
+ $utf8 .= chr(0x0A);
536
+ ++$c;
537
+ break;
538
+ case $substr_chrs_c_2 == '\f':
539
+ $utf8 .= chr(0x0C);
540
+ ++$c;
541
+ break;
542
+ case $substr_chrs_c_2 == '\r':
543
+ $utf8 .= chr(0x0D);
544
+ ++$c;
545
+ break;
546
+
547
+ case $substr_chrs_c_2 == '\\"':
548
+ case $substr_chrs_c_2 == '\\\'':
549
+ case $substr_chrs_c_2 == '\\\\':
550
+ case $substr_chrs_c_2 == '\\/':
551
+ if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
552
+ ($delim == "'" && $substr_chrs_c_2 != '\\"')) {
553
+ $utf8 .= $chrs{++$c};
554
+ }
555
+ break;
556
+
557
+ case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
558
+ // single, escaped unicode character
559
+ $utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
560
+ . chr(hexdec(substr($chrs, ($c + 4), 2)));
561
+ $utf8 .= $this->utf162utf8($utf16);
562
+ $c += 5;
563
+ break;
564
+
565
+ case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
566
+ $utf8 .= $chrs{$c};
567
+ break;
568
+
569
+ case ($ord_chrs_c & 0xE0) == 0xC0:
570
+ // characters U-00000080 - U-000007FF, mask 110XXXXX
571
+ //see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
572
+ $utf8 .= substr($chrs, $c, 2);
573
+ ++$c;
574
+ break;
575
+
576
+ case ($ord_chrs_c & 0xF0) == 0xE0:
577
+ // characters U-00000800 - U-0000FFFF, mask 1110XXXX
578
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
579
+ $utf8 .= substr($chrs, $c, 3);
580
+ $c += 2;
581
+ break;
582
+
583
+ case ($ord_chrs_c & 0xF8) == 0xF0:
584
+ // characters U-00010000 - U-001FFFFF, mask 11110XXX
585
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
586
+ $utf8 .= substr($chrs, $c, 4);
587
+ $c += 3;
588
+ break;
589
+
590
+ case ($ord_chrs_c & 0xFC) == 0xF8:
591
+ // characters U-00200000 - U-03FFFFFF, mask 111110XX
592
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
593
+ $utf8 .= substr($chrs, $c, 5);
594
+ $c += 4;
595
+ break;
596
+
597
+ case ($ord_chrs_c & 0xFE) == 0xFC:
598
+ // characters U-04000000 - U-7FFFFFFF, mask 1111110X
599
+ // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
600
+ $utf8 .= substr($chrs, $c, 6);
601
+ $c += 5;
602
+ break;
603
+
604
+ }
605
+
606
+ }
607
+
608
+ return $utf8;
609
+
610
+ } elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
611
+ // array, or object notation
612
+
613
+ if ($str{0} == '[') {
614
+ $stk = array(SERVICES_JSON_IN_ARR);
615
+ $arr = array();
616
+ } else {
617
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
618
+ $stk = array(SERVICES_JSON_IN_OBJ);
619
+ $obj = array();
620
+ } else {
621
+ $stk = array(SERVICES_JSON_IN_OBJ);
622
+ $obj = new stdClass();
623
+ }
624
+ }
625
+
626
+ array_push($stk, array('what' => SERVICES_JSON_SLICE,
627
+ 'where' => 0,
628
+ 'delim' => false));
629
+
630
+ $chrs = substr($str, 1, -1);
631
+ $chrs = $this->reduce_string($chrs);
632
+
633
+ if ($chrs == '') {
634
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
635
+ return $arr;
636
+
637
+ } else {
638
+ return $obj;
639
+
640
+ }
641
+ }
642
+
643
+ //print("\nparsing {$chrs}\n");
644
+
645
+ $strlen_chrs = strlen($chrs);
646
+
647
+ for ($c = 0; $c <= $strlen_chrs; ++$c) {
648
+
649
+ $top = end($stk);
650
+ $substr_chrs_c_2 = substr($chrs, $c, 2);
651
+
652
+ if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
653
+ // found a comma that is not inside a string, array, etc.,
654
+ // OR we've reached the end of the character list
655
+ $slice = substr($chrs, $top['where'], ($c - $top['where']));
656
+ array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
657
+ //print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
658
+
659
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
660
+ // we are in an array, so just push an element onto the stack
661
+ array_push($arr, $this->decode($slice));
662
+
663
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
664
+ // we are in an object, so figure
665
+ // out the property name and set an
666
+ // element in an associative array,
667
+ // for now
668
+ $parts = array();
669
+
670
+ if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
671
+ // "name":value pair
672
+ $key = $this->decode($parts[1]);
673
+ $val = $this->decode($parts[2]);
674
+
675
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
676
+ $obj[$key] = $val;
677
+ } else {
678
+ $obj->$key = $val;
679
+ }
680
+ } elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
681
+ // name:value pair, where name is unquoted
682
+ $key = $parts[1];
683
+ $val = $this->decode($parts[2]);
684
+
685
+ if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
686
+ $obj[$key] = $val;
687
+ } else {
688
+ $obj->$key = $val;
689
+ }
690
+ }
691
+
692
+ }
693
+
694
+ } elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
695
+ // found a quote, and we are not inside a string
696
+ array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
697
+ //print("Found start of string at {$c}\n");
698
+
699
+ } elseif (($chrs{$c} == $top['delim']) &&
700
+ ($top['what'] == SERVICES_JSON_IN_STR) &&
701
+ ((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
702
+ // found a quote, we're in a string, and it's not escaped
703
+ // we know that it's not escaped becase there is _not_ an
704
+ // odd number of backslashes at the end of the string so far
705
+ array_pop($stk);
706
+ //print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
707
+
708
+ } elseif (($chrs{$c} == '[') &&
709
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
710
+ // found a left-bracket, and we are in an array, object, or slice
711
+ array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
712
+ //print("Found start of array at {$c}\n");
713
+
714
+ } elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
715
+ // found a right-bracket, and we're in an array
716
+ array_pop($stk);
717
+ //print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
718
+
719
+ } elseif (($chrs{$c} == '{') &&
720
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
721
+ // found a left-brace, and we are in an array, object, or slice
722
+ array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
723
+ //print("Found start of object at {$c}\n");
724
+
725
+ } elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
726
+ // found a right-brace, and we're in an object
727
+ array_pop($stk);
728
+ //print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
729
+
730
+ } elseif (($substr_chrs_c_2 == '/*') &&
731
+ in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
732
+ // found a comment start, and we are in an array, object, or slice
733
+ array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
734
+ $c++;
735
+ //print("Found start of comment at {$c}\n");
736
+
737
+ } elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
738
+ // found a comment end, and we're in one now
739
+ array_pop($stk);
740
+ $c++;
741
+
742
+ for ($i = $top['where']; $i <= $c; ++$i)
743
+ $chrs = substr_replace($chrs, ' ', $i, 1);
744
+
745
+ //print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
746
+
747
+ }
748
+
749
+ }
750
+
751
+ if (reset($stk) == SERVICES_JSON_IN_ARR) {
752
+ return $arr;
753
+
754
+ } elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
755
+ return $obj;
756
+
757
+ }
758
+
759
+ }
760
+ }
761
+ }
762
+
763
+ /**
764
+ * @todo Ultimately, this should just call PEAR::isError()
765
+ */
766
+ function isError($data, $code = null)
767
+ {
768
+ if (class_exists('pear')) {
769
+ return PEAR::isError($data, $code);
770
+ } elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
771
+ is_subclass_of($data, 'services_json_error'))) {
772
+ return true;
773
+ }
774
+
775
+ return false;
776
+ }
777
+ }
778
+
779
+ if (class_exists('PEAR_Error')) {
780
+
781
+ class Services_JSON_Error extends PEAR_Error
782
+ {
783
+ function Services_JSON_Error($message = 'unknown error', $code = null,
784
+ $mode = null, $options = null, $userinfo = null)
785
+ {
786
+ parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
787
+ }
788
+ }
789
+
790
+ } else {
791
+
792
+ /**
793
+ * @todo Ultimately, this class shall be descended from PEAR_Error
794
+ */
795
+ class Services_JSON_Error
796
+ {
797
+ function Services_JSON_Error($message = 'unknown error', $code = null,
798
+ $mode = null, $options = null, $userinfo = null)
799
+ {
800
+
801
+ }
802
+ }
803
+
804
+ }
805
+
806
+ ?>
app/code/community/Cleantalk/Antispam/Model/lib/cleantalk.class.php CHANGED
@@ -1,1062 +1,1095 @@
1
- <?php
2
- /**
3
- * Cleantalk base class
4
- *
5
- * @version 2.0
6
- * @package Cleantalk
7
- * @subpackage Base
8
- * @author Cleantalk team (welcome@cleantalk.org)
9
- * @copyright (C) 2014 CleanTalk team (http://cleantalk.org)
10
- * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html
11
- * @see https://github.com/CleanTalk/php-antispam
12
- *
13
- */
14
-
15
- /**
16
- * Load JSON functions if they are not exists
17
- */
18
- if(!function_exists('json_encode')) {
19
- require_once 'JSON.php';
20
-
21
- function json_encode($data) {
22
- $json = new Services_JSON();
23
- return( $json->encode($data) );
24
- }
25
-
26
- }
27
- if(!function_exists('json_decode')) {
28
- require_once 'JSON.php';
29
-
30
- function json_decode($data) {
31
- $json = new Services_JSON();
32
- return( $json->decode($data) );
33
- }
34
- }
35
-
36
- /**
37
- * Response class
38
- */
39
- class CleantalkResponse {
40
-
41
- /**
42
- * Is stop words
43
- * @var int
44
- */
45
- public $stop_words = null;
46
-
47
- /**
48
- * Cleantalk comment
49
- * @var string
50
- */
51
- public $comment = null;
52
-
53
- /**
54
- * Is blacklisted
55
- * @var int
56
- */
57
- public $blacklisted = null;
58
-
59
- /**
60
- * Is allow, 1|0
61
- * @var int
62
- */
63
- public $allow = null;
64
-
65
- /**
66
- * Request ID
67
- * @var int
68
- */
69
- public $id = null;
70
-
71
- /**
72
- * Request errno
73
- * @var int
74
- */
75
- public $errno = null;
76
-
77
- /**
78
- * Error string
79
- * @var string
80
- */
81
- public $errstr = null;
82
-
83
- /**
84
- * Is fast submit, 1|0
85
- * @var string
86
- */
87
- public $fast_submit = null;
88
-
89
- /**
90
- * Is spam comment
91
- * @var string
92
- */
93
- public $spam = null;
94
-
95
- /**
96
- * Is JS
97
- * @var type
98
- */
99
- public $js_disabled = null;
100
-
101
- /**
102
- * Sms check
103
- * @var type
104
- */
105
- public $sms_allow = null;
106
-
107
- /**
108
- * Sms code result
109
- * @var type
110
- */
111
- public $sms = null;
112
-
113
- /**
114
- * Sms error code
115
- * @var type
116
- */
117
- public $sms_error_code = null;
118
-
119
- /**
120
- * Sms error code
121
- * @var type
122
- */
123
- public $sms_error_text = null;
124
-
125
- /**
126
- * Stop queue message, 1|0
127
- * @var int
128
- */
129
- public $stop_queue = null;
130
-
131
- /**
132
- * Account shuld by deactivated after registration, 1|0
133
- * @var int
134
- */
135
- public $inactive = null;
136
-
137
- /**
138
- * Account status
139
- * @var int
140
- */
141
- public $account_status = -1;
142
-
143
- /**
144
- * Create server response
145
- *
146
- * @param type $response
147
- * @param type $obj
148
- */
149
- function __construct($response = null, $obj = null) {
150
- if ($response && is_array($response) && count($response) > 0) {
151
- foreach ($response as $param => $value) {
152
- $this->{$param} = $value;
153
- }
154
- } else {
155
- $this->errno = $obj->errno;
156
- $this->errstr = $obj->errstr;
157
-
158
- $this->errstr = preg_replace("/.+(\*\*\*.+\*\*\*).+/", "$1", $this->errstr);
159
-
160
- $this->stop_words = isset($obj->stop_words) ? utf8_decode($obj->stop_words) : null;
161
- $this->comment = isset($obj->comment) ? utf8_decode($obj->comment) : null;
162
- $this->blacklisted = (isset($obj->blacklisted)) ? $obj->blacklisted : null;
163
- $this->allow = (isset($obj->allow)) ? $obj->allow : 0;
164
- $this->id = (isset($obj->id)) ? $obj->id : null;
165
- $this->fast_submit = (isset($obj->fast_submit)) ? $obj->fast_submit : 0;
166
- $this->spam = (isset($obj->spam)) ? $obj->spam : 0;
167
- $this->js_disabled = (isset($obj->js_disabled)) ? $obj->js_disabled : 0;
168
- $this->sms_allow = (isset($obj->sms_allow)) ? $obj->sms_allow : null;
169
- $this->sms = (isset($obj->sms)) ? $obj->sms : null;
170
- $this->sms_error_code = (isset($obj->sms_error_code)) ? $obj->sms_error_code : null;
171
- $this->sms_error_text = (isset($obj->sms_error_text)) ? $obj->sms_error_text : null;
172
- $this->stop_queue = (isset($obj->stop_queue)) ? $obj->stop_queue : 0;
173
- $this->inactive = (isset($obj->inactive)) ? $obj->inactive : 0;
174
- $this->account_status = (isset($obj->account_status)) ? $obj->account_status : -1;
175
-
176
- if ($this->errno !== 0 && $this->errstr !== null && $this->comment === null)
177
- $this->comment = '*** ' . $this->errstr . ' Antispam service cleantalk.org ***';
178
- }
179
- }
180
-
181
- }
182
-
183
- /**
184
- * Request class
185
- */
186
- class CleantalkRequest {
187
-
188
- /**
189
- * All http request headers
190
- * @var string
191
- */
192
- public $all_headers = null;
193
-
194
- /**
195
- * User message
196
- * @var string
197
- */
198
- public $message = null;
199
-
200
- /**
201
- * Post example with last comments
202
- * @var string
203
- */
204
- public $example = null;
205
-
206
- /**
207
- * Auth key
208
- * @var string
209
- */
210
- public $auth_key = null;
211
-
212
- /**
213
- * Engine
214
- * @var string
215
- */
216
- public $agent = null;
217
-
218
- /**
219
- * Is check for stoplist,
220
- * valid are 0|1
221
- * @var int
222
- */
223
- public $stoplist_check = null;
224
-
225
- /**
226
- * Language server response,
227
- * valid are 'en' or 'ru'
228
- * @var string
229
- */
230
- public $response_lang = null;
231
-
232
- /**
233
- * User IP
234
- * @var strings
235
- */
236
- public $sender_ip = null;
237
-
238
- /**
239
- * User email
240
- * @var strings
241
- */
242
- public $sender_email = null;
243
-
244
- /**
245
- * User nickname
246
- * @var string
247
- */
248
- public $sender_nickname = null;
249
-
250
- /**
251
- * Sender info JSON string
252
- * @var string
253
- */
254
- public $sender_info = null;
255
-
256
- /**
257
- * Post info JSON string
258
- * @var string
259
- */
260
- public $post_info = null;
261
-
262
- /**
263
- * Is allow links, email and icq,
264
- * valid are 1|0
265
- * @var int
266
- */
267
- public $allow_links = null;
268
-
269
- /**
270
- * Time form filling
271
- * @var int
272
- */
273
- public $submit_time = null;
274
-
275
- /**
276
- * Is enable Java Script,
277
- * valid are 0|1|2
278
- * Status:
279
- * null - JS html code not inserted into phpBB templates
280
- * 0 - JS disabled at the client browser
281
- * 1 - JS enabled at the client broswer
282
- * @var int
283
- */
284
- public $js_on = null;
285
-
286
- /**
287
- * user time zone
288
- * @var string
289
- */
290
- public $tz = null;
291
-
292
- /**
293
- * Feedback string,
294
- * valid are 'requset_id:(1|0)'
295
- * @var string
296
- */
297
- public $feedback = null;
298
-
299
- /**
300
- * Phone number
301
- * @var type
302
- */
303
- public $phone = null;
304
-
305
- /**
306
- * Method name
307
- * @var string
308
- */
309
- public $method_name = 'check_message';
310
-
311
- /**
312
- * Fill params with constructor
313
- * @param type $params
314
- */
315
- public function __construct($params = null) {
316
- if (is_array($params) && count($params) > 0) {
317
- foreach ($params as $param => $value) {
318
- $this->{$param} = $value;
319
- }
320
- }
321
- }
322
-
323
- }
324
-
325
- /**
326
- * Cleantalk class create request
327
- */
328
- class Cleantalk {
329
-
330
- /**
331
- * Debug level
332
- * @var int
333
- */
334
- public $debug = 0;
335
-
336
- /**
337
- * Maximum data size in bytes
338
- * @var int
339
- */
340
- private $dataMaxSise = 32768;
341
-
342
- /**
343
- * Data compression rate
344
- * @var int
345
- */
346
- private $compressRate = 6;
347
-
348
- /**
349
- * Server connection timeout in seconds
350
- * @var int
351
- */
352
- private $server_timeout = 3;
353
-
354
- /**
355
- * Cleantalk server url
356
- * @var string
357
- */
358
- public $server_url = null;
359
-
360
- /**
361
- * Last work url
362
- * @var string
363
- */
364
- public $work_url = null;
365
-
366
- /**
367
- * WOrk url ttl
368
- * @var int
369
- */
370
- public $server_ttl = null;
371
-
372
- /**
373
- * Time wotk_url changer
374
- * @var int
375
- */
376
- public $server_changed = null;
377
-
378
- /**
379
- * Flag is change server url
380
- * @var bool
381
- */
382
- public $server_change = false;
383
-
384
- /**
385
- * Use TRUE when need stay on server. Example: send feedback
386
- * @var bool
387
- */
388
- public $stay_on_server = false;
389
-
390
- /**
391
- * Codepage of the data
392
- * @var bool
393
- */
394
- public $data_codepage = null;
395
-
396
- /**
397
- * API version to use
398
- * @var string
399
- */
400
- public $api_version = '/api2.0';
401
-
402
- /**
403
- * Use https connection to servers
404
- * @var bool
405
- */
406
- public $ssl_on = false;
407
-
408
- /**
409
- * Minimal server response in miliseconds to catch the server
410
- *
411
- */
412
- public $min_server_timeout = 50;
413
-
414
- /**
415
- * Function checks whether it is possible to publish the message
416
- * @param CleantalkRequest $request
417
- * @return type
418
- */
419
- public function isAllowMessage(CleantalkRequest $request) {
420
- $this->filterRequest($request);
421
- $msg = $this->createMsg('check_message', $request);
422
- return $this->httpRequest($msg);
423
- }
424
-
425
- /**
426
- * Function checks whether it is possible to publish the message
427
- * @param CleantalkRequest $request
428
- * @return type
429
- */
430
- public function isAllowUser(CleantalkRequest $request) {
431
- $this->filterRequest($request);
432
- $msg = $this->createMsg('check_newuser', $request);
433
- return $this->httpRequest($msg);
434
- }
435
-
436
- /**
437
- * Function sends the results of manual moderation
438
- *
439
- * @param CleantalkRequest $request
440
- * @return type
441
- */
442
- public function sendFeedback(CleantalkRequest $request) {
443
- $this->filterRequest($request);
444
- $msg = $this->createMsg('send_feedback', $request);
445
- return $this->httpRequest($msg);
446
- }
447
-
448
- /**
449
- * Filter request params
450
- * @param CleantalkRequest $request
451
- * @return type
452
- */
453
- private function filterRequest(CleantalkRequest &$request) {
454
- // general and optional
455
- foreach ($request as $param => $value) {
456
- if (in_array($param, array('message', 'example', 'agent',
457
- 'sender_info', 'sender_nickname', 'post_info', 'phone')) && !empty($value)) {
458
- if (!is_string($value) && !is_integer($value)) {
459
- $request->$param = NULL;
460
- }
461
- }
462
-
463
- if (in_array($param, array('stoplist_check', 'allow_links')) && !empty($value)) {
464
- if (!in_array($value, array(1, 2))) {
465
- $request->$param = NULL;
466
- }
467
- }
468
-
469
- if (in_array($param, array('js_on')) && !empty($value)) {
470
- if (!is_integer($value)) {
471
- $request->$param = NULL;
472
- }
473
- }
474
-
475
- if ($param == 'sender_ip' && !empty($value)) {
476
- if (!is_string($value)) {
477
- $request->$param = NULL;
478
- }
479
- }
480
-
481
- if ($param == 'sender_email' && !empty($value)) {
482
- if (!is_string($value)) {
483
- $request->$param = NULL;
484
- }
485
- }
486
-
487
- if ($param == 'submit_time' && !empty($value)) {
488
- if (!is_int($value)) {
489
- $request->$param = NULL;
490
- }
491
- }
492
- }
493
- }
494
-
495
- /**
496
- * Compress data and encode to base64
497
- * @param type string
498
- * @return string
499
- */
500
- private function compressData($data = null){
501
-
502
- if (strlen($data) > $this->dataMaxSise && function_exists('gzencode') && function_exists('base64_encode')){
503
-
504
- $localData = gzencode($data, $this->compressRate, FORCE_GZIP);
505
-
506
- if ($localData === false)
507
- return $data;
508
-
509
- $localData = base64_encode($localData);
510
-
511
- if ($localData === false)
512
- return $data;
513
-
514
- return $localData;
515
- }
516
-
517
- return $data;
518
- }
519
-
520
- /**
521
- * Create msg for cleantalk server
522
- * @param type $method
523
- * @param CleantalkRequest $request
524
- * @return \xmlrpcmsg
525
- */
526
- private function createMsg($method, CleantalkRequest $request) {
527
- switch ($method) {
528
- case 'check_message':
529
- // Convert strings to UTF8
530
- $request->message = $this->stringToUTF8($request->message, $this->data_codepage);
531
- $request->example = $this->stringToUTF8($request->example, $this->data_codepage);
532
- $request->sender_email = $this->stringToUTF8($request->sender_email, $this->data_codepage);
533
- $request->sender_nickname = $this->stringToUTF8($request->sender_nickname, $this->data_codepage);
534
-
535
- $request->message = $this->compressData($request->message);
536
- $request->example = $this->compressData($request->example);
537
- break;
538
-
539
- case 'check_newuser':
540
- // Convert strings to UTF8
541
- $request->sender_email = $this->stringToUTF8($request->sender_email, $this->data_codepage);
542
- $request->sender_nickname = $this->stringToUTF8($request->sender_nickname, $this->data_codepage);
543
- break;
544
-
545
- case 'send_feedback':
546
- if (is_array($request->feedback)) {
547
- $request->feedback = implode(';', $request->feedback);
548
- }
549
- break;
550
- }
551
-
552
- $request->method_name = $method;
553
-
554
- //
555
- // Removing non UTF8 characters from request, because non UTF8 or malformed characters break json_encode().
556
- //
557
- foreach ($request as $param => $value) {
558
- if (!preg_match('//u', $value)) {
559
- $request->{$param} = 'Nulled. Not UTF8 encoded or malformed.';
560
- }
561
- }
562
-
563
- return $request;
564
- }
565
-
566
- /**
567
- * Send JSON request to servers
568
- * @param $msg
569
- * @return boolean|\CleantalkResponse
570
- */
571
- private function sendRequest($data = null, $url, $server_timeout = 3) {
572
- // Convert to array
573
- $data = json_decode(json_encode($data), true);
574
-
575
- // Convert to JSON
576
- $data = json_encode($data);
577
-
578
- if (isset($this->api_version)) {
579
- $url = $url . $this->api_version;
580
- }
581
-
582
- // Switching to secure connection
583
- if ($this->ssl_on && !preg_match("/^https:/", $url)) {
584
- $url = preg_replace("/^(http)/i", "$1s", $url);
585
- }
586
-
587
- $result = false;
588
- $curl_error = null;
589
- if(function_exists('curl_init')) {
590
- $ch = curl_init();
591
- curl_setopt($ch, CURLOPT_URL, $url);
592
- curl_setopt($ch, CURLOPT_TIMEOUT, $server_timeout);
593
- curl_setopt($ch, CURLOPT_POST, 1);
594
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
595
- // receive server response ...
596
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
597
- // resolve 'Expect: 100-continue' issue
598
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
599
- // see http://stackoverflow.com/a/23322368
600
- curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
601
-
602
- // Disabling CA cert verivication
603
- // Disabling common name verification
604
- if ($this->ssl_on) {
605
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
606
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
607
- }
608
-
609
- $result = curl_exec($ch);
610
- if (!$result) {
611
- $curl_error = curl_error($ch);
612
- }
613
-
614
- curl_close($ch);
615
- }
616
-
617
- if (!$result) {
618
- $allow_url_fopen = ini_get('allow_url_fopen');
619
- if (function_exists('file_get_contents') && isset($allow_url_fopen) && $allow_url_fopen == '1') {
620
- $opts = array('http' =>
621
- array(
622
- 'method' => 'POST',
623
- 'header' => "Content-Type: text/html\r\n",
624
- 'content' => $data,
625
- 'timeout' => $server_timeout
626
- )
627
- );
628
-
629
- $context = stream_context_create($opts);
630
- $result = @file_get_contents($url, false, $context);
631
- }
632
- }
633
-
634
- if (!$result) {
635
- $response = null;
636
- $response['errno'] = 1;
637
- if ($curl_error) {
638
- $response['errstr'] = sprintf("CURL error: '%s'", $curl_error);
639
- } else {
640
- $response['errstr'] = 'No CURL support compiled in';
641
- }
642
- $response['errstr'] .= ' or disabled allow_url_fopen in php.ini.';
643
- $response = json_decode(json_encode($response));
644
-
645
- return $response;
646
- }
647
-
648
- $errstr = null;
649
- $response = json_decode($result);
650
- if ($result !== false && is_object($response)) {
651
- $response->errno = 0;
652
- $response->errstr = $errstr;
653
- } else {
654
- $errstr = 'Unknown response from ' . $url . '.' . ' ' . $result;
655
-
656
- $response = null;
657
- $response['errno'] = 1;
658
- $response['errstr'] = $errstr;
659
- $response = json_decode(json_encode($response));
660
- }
661
-
662
-
663
- return $response;
664
- }
665
-
666
- /**
667
- * httpRequest
668
- * @param $msg
669
- * @return boolean|\CleantalkResponse
670
- */
671
- private function httpRequest($msg) {
672
- $result = false;
673
- $msg->all_headers=json_encode(apache_request_headers());
674
- if (((isset($this->work_url) && $this->work_url !== '') && ($this->server_changed + $this->server_ttl > time()))
675
- || $this->stay_on_server == true) {
676
-
677
- $url = (!empty($this->work_url)) ? $this->work_url : $this->server_url;
678
-
679
- $result = $this->sendRequest($msg, $url, $this->server_timeout);
680
- }
681
-
682
- if (($result === false || $result->errno != 0) && $this->stay_on_server == false) {
683
- // Split server url to parts
684
- preg_match("@^(https?://)([^/:]+)(.*)@i", $this->server_url, $matches);
685
- $url_prefix = '';
686
- if (isset($matches[1]))
687
- $url_prefix = $matches[1];
688
-
689
- $pool = null;
690
- if (isset($matches[2]))
691
- $pool = $matches[2];
692
-
693
- $url_suffix = '';
694
- if (isset($matches[3]))
695
- $url_suffix = $matches[3];
696
-
697
- if ($url_prefix === '')
698
- $url_prefix = 'http://';
699
-
700
- if (empty($pool)) {
701
- return false;
702
- } else {
703
- // Loop until find work server
704
- foreach ($this->get_servers_ip($pool) as $server) {
705
- if ($server['host'] === 'localhost' || $server['ip'] === null) {
706
- $work_url = $server['host'];
707
- } else {
708
- $server_host = $server['ip'];
709
- $work_url = $server_host;
710
- }
711
- $work_url = $url_prefix . $work_url;
712
- if (isset($url_suffix))
713
- $work_url = $work_url . $url_suffix;
714
-
715
- $this->work_url = $work_url;
716
- $this->server_ttl = $server['ttl'];
717
-
718
- $result = $this->sendRequest($msg, $this->work_url, $this->server_timeout);
719
-
720
- if ($result !== false && $result->errno === 0) {
721
- $this->server_change = true;
722
- break;
723
- }
724
- }
725
- }
726
- }
727
-
728
- $response = new CleantalkResponse(null, $result);
729
-
730
- if (!empty($this->data_codepage) && $this->data_codepage !== 'UTF-8') {
731
- if (!empty($response->comment))
732
- $response->comment = $this->stringFromUTF8($response->comment, $this->data_codepage);
733
- if (!empty($response->errstr))
734
- $response->errstr = $this->stringFromUTF8($response->errstr, $this->data_codepage);
735
- if (!empty($response->sms_error_text))
736
- $response->sms_error_text = $this->stringFromUTF8($response->sms_error_text, $this->data_codepage);
737
- }
738
-
739
- return $response;
740
- }
741
-
742
- /**
743
- * Function DNS request
744
- * @param $host
745
- * @return array
746
- */
747
- public function get_servers_ip($host) {
748
- $response = null;
749
- if (!isset($host))
750
- return $response;
751
-
752
- if (function_exists('dns_get_record')) {
753
- $records = dns_get_record($host, DNS_A);
754
-
755
- if ($records !== FALSE) {
756
- foreach ($records as $server) {
757
- $response[] = $server;
758
- }
759
- }
760
- }
761
-
762
- if (count($response) == 0 && function_exists('gethostbynamel')) {
763
- $records = gethostbynamel($host);
764
-
765
- if ($records !== FALSE) {
766
- foreach ($records as $server) {
767
- $response[] = array("ip" => $server,
768
- "host" => $host,
769
- "ttl" => $this->server_ttl
770
- );
771
- }
772
- }
773
- }
774
-
775
- if (count($response) == 0) {
776
- $response[] = array("ip" => null,
777
- "host" => $host,
778
- "ttl" => $this->server_ttl
779
- );
780
- } else {
781
- // $i - to resolve collisions with localhost
782
- $i = 0;
783
- $r_temp = null;
784
- $fast_server_found = false;
785
- foreach ($response as $server) {
786
-
787
- // Do not test servers because fast work server found
788
- if ($fast_server_found) {
789
- $ping = $this->min_server_timeout;
790
- } else {
791
- $ping = $this->httpPing($server['ip']);
792
- $ping = $ping * 1000;
793
- }
794
-
795
- // -1 server is down, skips not reachable server
796
- if ($ping != -1) {
797
- $r_temp[$ping + $i] = $server;
798
- }
799
- $i++;
800
-
801
- if ($ping < $this->min_server_timeout) {
802
- $fast_server_found = true;
803
- }
804
- }
805
- if (count($r_temp)){
806
- ksort($r_temp);
807
- $response = $r_temp;
808
- }
809
- }
810
-
811
- return $response;
812
- }
813
-
814
- /**
815
- * Function to get the message hash from Cleantalk.ru comment
816
- * @param $message
817
- * @return null
818
- */
819
- public function getCleantalkCommentHash($message) {
820
- $matches = array();
821
- if (preg_match('/\n\n\*\*\*.+([a-z0-9]{32}).+\*\*\*$/', $message, $matches))
822
- return $matches[1];
823
- else if (preg_match('/\<br.*\>[\n]{0,1}\<br.*\>[\n]{0,1}\*\*\*.+([a-z0-9]{32}).+\*\*\*$/', $message, $matches))
824
- return $matches[1];
825
-
826
- return NULL;
827
- }
828
-
829
- /**
830
- * Function adds to the post comment Cleantalk.ru
831
- * @param $message
832
- * @param $comment
833
- * @return string
834
- */
835
- public function addCleantalkComment($message, $comment) {
836
- $comment = preg_match('/\*\*\*(.+)\*\*\*/', $comment, $matches) ? $comment : '*** ' . $comment . ' ***';
837
- return $message . "\n\n" . $comment;
838
- }
839
-
840
- /**
841
- * Function deletes the comment Cleantalk.ru
842
- * @param $message
843
- * @return mixed
844
- */
845
- public function delCleantalkComment($message) {
846
- $message = preg_replace('/\n\n\*\*\*.+\*\*\*$/', '', $message);
847
-
848
- // DLE sign cut
849
- $message = preg_replace('/<br\s?\/><br\s?\/>\*\*\*.+\*\*\*$/', '', $message);
850
-
851
- $message = preg_replace('/\<br.*\>[\n]{0,1}\<br.*\>[\n]{0,1}\*\*\*.+\*\*\*$/', '', $message);
852
-
853
- return $message;
854
- }
855
-
856
- /**
857
- * Get user IP behind proxy server
858
- */
859
- public function ct_session_ip( $data_ip ) {
860
- if (!$data_ip || !preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $data_ip)) {
861
- return $data_ip;
862
- }
863
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
864
-
865
- $forwarded_ip = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
866
-
867
- // Looking for first value in the list, it should be sender real IP address
868
- if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $forwarded_ip[0])) {
869
- return $data_ip;
870
- }
871
-
872
- $private_src_ip = false;
873
- $private_nets = array(
874
- '10.0.0.0/8',
875
- '127.0.0.0/8',
876
- '176.16.0.0/12',
877
- '192.168.0.0/16',
878
- );
879
-
880
- foreach ($private_nets as $v) {
881
-
882
- // Private IP found
883
- if ($private_src_ip) {
884
- continue;
885
- }
886
-
887
- if ($this->net_match($v, $data_ip)) {
888
- $private_src_ip = true;
889
- }
890
- }
891
- if ($private_src_ip) {
892
- // Taking first IP from the list HTTP_X_FORWARDED_FOR
893
- $data_ip = $forwarded_ip[0];
894
- }
895
- }
896
-
897
- return $data_ip;
898
- }
899
-
900
- /**
901
- * From http://php.net/manual/en/function.ip2long.php#82397
902
- */
903
- public function net_match($CIDR,$IP) {
904
- list ($net, $mask) = explode ('/', $CIDR);
905
- return ( ip2long ($IP) & ~((1 << (32 - $mask)) - 1) ) == ip2long ($net);
906
- }
907
-
908
- /**
909
- * Function to check response time
910
- * param string
911
- * @return int
912
- */
913
- function httpPing($host){
914
-
915
- // Skip localhost ping cause it raise error at fsockopen.
916
- // And return minimun value
917
- if ($host == 'localhost')
918
- return 0.001;
919
-
920
- $starttime = microtime(true);
921
- $file = @fsockopen ($host, 80, $errno, $errstr, $this->server_timeout);
922
- $stoptime = microtime(true);
923
- $status = 0;
924
- if (!$file) {
925
- $status = -1; // Site is down
926
- } else {
927
- fclose($file);
928
- $status = ($stoptime - $starttime);
929
- $status = round($status, 4);
930
- }
931
-
932
- return $status;
933
- }
934
-
935
- /**
936
- * Function convert string to UTF8 and removes non UTF8 characters
937
- * param string
938
- * param string
939
- * @return string
940
- */
941
- function stringToUTF8($str, $data_codepage = null){
942
- if (!preg_match('//u', $str) && function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) {
943
-
944
- if ($data_codepage !== null)
945
- return mb_convert_encoding($str, 'UTF-8', $data_codepage);
946
-
947
- $encoding = mb_detect_encoding($str);
948
- if ($encoding)
949
- return mb_convert_encoding($str, 'UTF-8', $encoding);
950
- }
951
-
952
- return $str;
953
- }
954
-
955
- /**
956
- * Function convert string from UTF8
957
- * param string
958
- * param string
959
- * @return string
960
- */
961
- function stringFromUTF8($str, $data_codepage = null){
962
- if (preg_match('//u', $str) && function_exists('mb_convert_encoding') && $data_codepage !== null) {
963
- return mb_convert_encoding($str, $data_codepage, 'UTF-8');
964
- }
965
-
966
- return $str;
967
- }
968
- }
969
-
970
- /**
971
- * Function gets access key automatically
972
- *
973
- * @param string website admin email
974
- * @param string website host
975
- * @param string website platform
976
- * @return type
977
- */
978
-
979
- function getAutoKey($email, $host, $platform)
980
- {
981
- $request=Array();
982
- $request['method_name'] = 'get_api_key';
983
- $request['email'] = $email;
984
- $request['website'] = $host;
985
- $request['platform'] = $platform;
986
- $url='https://api.cleantalk.org';
987
- $result=sendRawRequest($url,$request);
988
- return $result;
989
- }
990
-
991
- /**
992
- * Function gets information about renew notice
993
- *
994
- * @param string api_key
995
- * @return type
996
- */
997
-
998
- function noticePaidTill($api_key)
999
- {
1000
- $request=Array();
1001
- $request['method_name'] = 'notice_paid_till';
1002
- $request['auth_key'] = $api_key;
1003
- $url='https://api.cleantalk.org';
1004
- $result=sendRawRequest($url,$request);
1005
- return $result;
1006
- }
1007
-
1008
- /**
1009
- * Function sends raw request to API server
1010
- *
1011
- * @param string url of API server
1012
- * @param array data to send
1013
- * @param boolean is data have to be JSON encoded or not
1014
- * @param integer connect timeout
1015
- * @return type
1016
- */
1017
-
1018
- function sendRawRequest($url,$data,$isJSON=false,$timeout=3)
1019
- {
1020
- $result=null;
1021
- if(!$isJSON)
1022
- {
1023
- $data=http_build_query($data);
1024
- }
1025
- else
1026
- {
1027
- $data= json_encode($data);
1028
- }
1029
- if (function_exists('curl_init') && function_exists('json_decode'))
1030
- {
1031
-
1032
- $ch = curl_init();
1033
- curl_setopt($ch, CURLOPT_URL, $url);
1034
- curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1035
- curl_setopt($ch, CURLOPT_POST, true);
1036
- curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
1037
-
1038
- // receive server response ...
1039
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1040
- // resolve 'Expect: 100-continue' issue
1041
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
1042
-
1043
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
1044
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
1045
-
1046
- $result = curl_exec($ch);
1047
- curl_close($ch);
1048
- }
1049
- else
1050
- {
1051
- $opts = array(
1052
- 'http'=>array(
1053
- 'method'=>"POST",
1054
- 'content'=>$data)
1055
- );
1056
- $context = stream_context_create($opts);
1057
- $result = @file_get_contents($url, 0, $context);
1058
- }
1059
- return $result;
1060
- }
1061
-
1062
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Cleantalk base class
4
+ *
5
+ * @version 2.0
6
+ * @package Cleantalk
7
+ * @subpackage Base
8
+ * @author Cleantalk team (welcome@cleantalk.org)
9
+ * @copyright (C) 2014 CleanTalk team (http://cleantalk.org)
10
+ * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html
11
+ * @see https://github.com/CleanTalk/php-antispam
12
+ *
13
+ */
14
+
15
+ /**
16
+ * Load JSON functions if they are not exists
17
+ */
18
+ if(!function_exists('json_encode')) {
19
+ require_once 'JSON.php';
20
+
21
+ function json_encode($data) {
22
+ $json = new Services_JSON();
23
+ return( $json->encode($data) );
24
+ }
25
+
26
+ }
27
+ if(!function_exists('json_decode')) {
28
+ require_once 'JSON.php';
29
+
30
+ function json_decode($data) {
31
+ $json = new Services_JSON();
32
+ return( $json->decode($data) );
33
+ }
34
+ }
35
+ /**
36
+ * Response class
37
+ */
38
+ class CleantalkResponse {
39
+
40
+ /**
41
+ * Is stop words
42
+ * @var int
43
+ */
44
+ public $stop_words = null;
45
+
46
+ /**
47
+ * Cleantalk comment
48
+ * @var string
49
+ */
50
+ public $comment = null;
51
+
52
+ /**
53
+ * Is blacklisted
54
+ * @var int
55
+ */
56
+ public $blacklisted = null;
57
+
58
+ /**
59
+ * Is allow, 1|0
60
+ * @var int
61
+ */
62
+ public $allow = null;
63
+
64
+ /**
65
+ * Request ID
66
+ * @var int
67
+ */
68
+ public $id = null;
69
+
70
+ /**
71
+ * Request errno
72
+ * @var int
73
+ */
74
+ public $errno = null;
75
+
76
+ /**
77
+ * Error string
78
+ * @var string
79
+ */
80
+ public $errstr = null;
81
+
82
+ /**
83
+ * Is fast submit, 1|0
84
+ * @var string
85
+ */
86
+ public $fast_submit = null;
87
+
88
+ /**
89
+ * Is spam comment
90
+ * @var string
91
+ */
92
+ public $spam = null;
93
+
94
+ /**
95
+ * Is JS
96
+ * @var type
97
+ */
98
+ public $js_disabled = null;
99
+
100
+ /**
101
+ * Sms check
102
+ * @var type
103
+ */
104
+ public $sms_allow = null;
105
+
106
+ /**
107
+ * Sms code result
108
+ * @var type
109
+ */
110
+ public $sms = null;
111
+
112
+ /**
113
+ * Sms error code
114
+ * @var type
115
+ */
116
+ public $sms_error_code = null;
117
+
118
+ /**
119
+ * Sms error code
120
+ * @var type
121
+ */
122
+ public $sms_error_text = null;
123
+
124
+ /**
125
+ * Stop queue message, 1|0
126
+ * @var int
127
+ */
128
+ public $stop_queue = null;
129
+
130
+ /**
131
+ * Account shuld by deactivated after registration, 1|0
132
+ * @var int
133
+ */
134
+ public $inactive = null;
135
+
136
+ /**
137
+ * Account status
138
+ * @var int
139
+ */
140
+ public $account_status = -1;
141
+
142
+ /**
143
+ * Create server response
144
+ *
145
+ * @param type $response
146
+ * @param type $obj
147
+ */
148
+ function __construct($response = null, $obj = null) {
149
+ if ($response && is_array($response) && count($response) > 0) {
150
+ foreach ($response as $param => $value) {
151
+ $this->{$param} = $value;
152
+ }
153
+ } else {
154
+ $this->errno = $obj->errno;
155
+ $this->errstr = $obj->errstr;
156
+
157
+ $this->errstr = preg_replace("/.+(\*\*\*.+\*\*\*).+/", "$1", $this->errstr);
158
+
159
+ $this->stop_words = isset($obj->stop_words) ? utf8_decode($obj->stop_words) : null;
160
+ $this->comment = isset($obj->comment) ? utf8_decode($obj->comment) : null;
161
+ $this->blacklisted = (isset($obj->blacklisted)) ? $obj->blacklisted : null;
162
+ $this->allow = (isset($obj->allow)) ? $obj->allow : 0;
163
+ $this->id = (isset($obj->id)) ? $obj->id : null;
164
+ $this->fast_submit = (isset($obj->fast_submit)) ? $obj->fast_submit : 0;
165
+ $this->spam = (isset($obj->spam)) ? $obj->spam : 0;
166
+ $this->js_disabled = (isset($obj->js_disabled)) ? $obj->js_disabled : 0;
167
+ $this->sms_allow = (isset($obj->sms_allow)) ? $obj->sms_allow : null;
168
+ $this->sms = (isset($obj->sms)) ? $obj->sms : null;
169
+ $this->sms_error_code = (isset($obj->sms_error_code)) ? $obj->sms_error_code : null;
170
+ $this->sms_error_text = (isset($obj->sms_error_text)) ? $obj->sms_error_text : null;
171
+ $this->stop_queue = (isset($obj->stop_queue)) ? $obj->stop_queue : 0;
172
+ $this->inactive = (isset($obj->inactive)) ? $obj->inactive : 0;
173
+ $this->account_status = (isset($obj->account_status)) ? $obj->account_status : -1;
174
+
175
+ if ($this->errno !== 0 && $this->errstr !== null && $this->comment === null)
176
+ $this->comment = '*** ' . $this->errstr . ' Antispam service cleantalk.org ***';
177
+ }
178
+ }
179
+
180
+ }
181
+
182
+ /**
183
+ * Request class
184
+ */
185
+ class CleantalkRequest {
186
+
187
+ /**
188
+ * All http request headers
189
+ * @var string
190
+ */
191
+ public $all_headers = null;
192
+
193
+ /**
194
+ * User message
195
+ * @var string
196
+ */
197
+ public $message = null;
198
+
199
+ /**
200
+ * Post example with last comments
201
+ * @var string
202
+ */
203
+ public $example = null;
204
+
205
+ /**
206
+ * Auth key
207
+ * @var string
208
+ */
209
+ public $auth_key = null;
210
+
211
+ /**
212
+ * Engine
213
+ * @var string
214
+ */
215
+ public $agent = null;
216
+
217
+ /**
218
+ * Is check for stoplist,
219
+ * valid are 0|1
220
+ * @var int
221
+ */
222
+ public $stoplist_check = null;
223
+
224
+ /**
225
+ * Language server response,
226
+ * valid are 'en' or 'ru'
227
+ * @var string
228
+ */
229
+ public $response_lang = null;
230
+
231
+ /**
232
+ * User IP
233
+ * @var strings
234
+ */
235
+ public $sender_ip = null;
236
+
237
+ /**
238
+ * User email
239
+ * @var strings
240
+ */
241
+ public $sender_email = null;
242
+
243
+ /**
244
+ * User nickname
245
+ * @var string
246
+ */
247
+ public $sender_nickname = null;
248
+
249
+ /**
250
+ * Sender info JSON string
251
+ * @var string
252
+ */
253
+ public $sender_info = null;
254
+
255
+ /**
256
+ * Post info JSON string
257
+ * @var string
258
+ */
259
+ public $post_info = null;
260
+
261
+ /**
262
+ * Is allow links, email and icq,
263
+ * valid are 1|0
264
+ * @var int
265
+ */
266
+ public $allow_links = null;
267
+
268
+ /**
269
+ * Time form filling
270
+ * @var int
271
+ */
272
+ public $submit_time = null;
273
+
274
+ /**
275
+ * Is enable Java Script,
276
+ * valid are 0|1|2
277
+ * Status:
278
+ * null - JS html code not inserted into phpBB templates
279
+ * 0 - JS disabled at the client browser
280
+ * 1 - JS enabled at the client broswer
281
+ * @var int
282
+ */
283
+ public $js_on = null;
284
+
285
+ /**
286
+ * user time zone
287
+ * @var string
288
+ */
289
+ public $tz = null;
290
+
291
+ /**
292
+ * Feedback string,
293
+ * valid are 'requset_id:(1|0)'
294
+ * @var string
295
+ */
296
+ public $feedback = null;
297
+
298
+ /**
299
+ * Phone number
300
+ * @var type
301
+ */
302
+ public $phone = null;
303
+
304
+ /**
305
+ * Method name
306
+ * @var string
307
+ */
308
+ public $method_name = 'check_message';
309
+
310
+ /**
311
+ * Fill params with constructor
312
+ * @param type $params
313
+ */
314
+ public function __construct($params = null) {
315
+ if (is_array($params) && count($params) > 0) {
316
+ foreach ($params as $param => $value) {
317
+ $this->{$param} = $value;
318
+ }
319
+ }
320
+ }
321
+
322
+ }
323
+
324
+ /**
325
+ * Cleantalk class create request
326
+ */
327
+ class Cleantalk {
328
+
329
+ /**
330
+ * Debug level
331
+ * @var int
332
+ */
333
+ public $debug = 0;
334
+
335
+ /**
336
+ * Maximum data size in bytes
337
+ * @var int
338
+ */
339
+ private $dataMaxSise = 32768;
340
+
341
+ /**
342
+ * Data compression rate
343
+ * @var int
344
+ */
345
+ private $compressRate = 6;
346
+
347
+ /**
348
+ * Server connection timeout in seconds
349
+ * @var int
350
+ */
351
+ private $server_timeout = 3;
352
+
353
+ /**
354
+ * Cleantalk server url
355
+ * @var string
356
+ */
357
+ public $server_url = null;
358
+
359
+ /**
360
+ * Last work url
361
+ * @var string
362
+ */
363
+ public $work_url = null;
364
+
365
+ /**
366
+ * WOrk url ttl
367
+ * @var int
368
+ */
369
+ public $server_ttl = null;
370
+
371
+ /**
372
+ * Time wotk_url changer
373
+ * @var int
374
+ */
375
+ public $server_changed = null;
376
+
377
+ /**
378
+ * Flag is change server url
379
+ * @var bool
380
+ */
381
+ public $server_change = false;
382
+
383
+ /**
384
+ * Use TRUE when need stay on server. Example: send feedback
385
+ * @var bool
386
+ */
387
+ public $stay_on_server = false;
388
+
389
+ /**
390
+ * Codepage of the data
391
+ * @var bool
392
+ */
393
+ public $data_codepage = null;
394
+
395
+ /**
396
+ * API version to use
397
+ * @var string
398
+ */
399
+ public $api_version = '/api2.0';
400
+
401
+ /**
402
+ * Use https connection to servers
403
+ * @var bool
404
+ */
405
+ public $ssl_on = false;
406
+
407
+ /**
408
+ * Minimal server response in miliseconds to catch the server
409
+ *
410
+ */
411
+ public $min_server_timeout = 50;
412
+
413
+ /**
414
+ * Function checks whether it is possible to publish the message
415
+ * @param CleantalkRequest $request
416
+ * @return type
417
+ */
418
+ public function isAllowMessage(CleantalkRequest $request) {
419
+ $this->filterRequest($request);
420
+ $msg = $this->createMsg('check_message', $request);
421
+ return $this->httpRequest($msg);
422
+ }
423
+
424
+ /**
425
+ * Function checks whether it is possible to publish the message
426
+ * @param CleantalkRequest $request
427
+ * @return type
428
+ */
429
+ public function isAllowUser(CleantalkRequest $request) {
430
+ $this->filterRequest($request);
431
+ $msg = $this->createMsg('check_newuser', $request);
432
+ return $this->httpRequest($msg);
433
+ }
434
+
435
+ /**
436
+ * Function sends the results of manual moderation
437
+ *
438
+ * @param CleantalkRequest $request
439
+ * @return type
440
+ */
441
+ public function sendFeedback(CleantalkRequest $request) {
442
+ $this->filterRequest($request);
443
+ $msg = $this->createMsg('send_feedback', $request);
444
+ return $this->httpRequest($msg);
445
+ }
446
+
447
+ /**
448
+ * Filter request params
449
+ * @param CleantalkRequest $request
450
+ * @return type
451
+ */
452
+ private function filterRequest(CleantalkRequest &$request) {
453
+ // general and optional
454
+ foreach ($request as $param => $value) {
455
+ if (in_array($param, array('message', 'example', 'agent',
456
+ 'sender_info', 'sender_nickname', 'post_info', 'phone')) && !empty($value)) {
457
+ if (!is_string($value) && !is_integer($value)) {
458
+ $request->$param = NULL;
459
+ }
460
+ }
461
+
462
+ if (in_array($param, array('stoplist_check', 'allow_links')) && !empty($value)) {
463
+ if (!in_array($value, array(1, 2))) {
464
+ $request->$param = NULL;
465
+ }
466
+ }
467
+
468
+ if (in_array($param, array('js_on')) && !empty($value)) {
469
+ if (!is_integer($value)) {
470
+ $request->$param = NULL;
471
+ }
472
+ }
473
+
474
+ if ($param == 'sender_ip' && !empty($value)) {
475
+ if (!is_string($value)) {
476
+ $request->$param = NULL;
477
+ }
478
+ }
479
+
480
+ if ($param == 'sender_email' && !empty($value)) {
481
+ if (!is_string($value)) {
482
+ $request->$param = NULL;
483
+ }
484
+ }
485
+
486
+ if ($param == 'submit_time' && !empty($value)) {
487
+ if (!is_int($value)) {
488
+ $request->$param = NULL;
489
+ }
490
+ }
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Compress data and encode to base64
496
+ * @param type string
497
+ * @return string
498
+ */
499
+ private function compressData($data = null){
500
+
501
+ if (strlen($data) > $this->dataMaxSise && function_exists('gzencode') && function_exists('base64_encode')){
502
+
503
+ $localData = gzencode($data, $this->compressRate, FORCE_GZIP);
504
+
505
+ if ($localData === false)
506
+ return $data;
507
+
508
+ $localData = base64_encode($localData);
509
+
510
+ if ($localData === false)
511
+ return $data;
512
+
513
+ return $localData;
514
+ }
515
+
516
+ return $data;
517
+ }
518
+
519
+ /**
520
+ * Create msg for cleantalk server
521
+ * @param type $method
522
+ * @param CleantalkRequest $request
523
+ * @return \xmlrpcmsg
524
+ */
525
+ private function createMsg($method, CleantalkRequest $request) {
526
+ switch ($method) {
527
+ case 'check_message':
528
+ // Convert strings to UTF8
529
+ $request->message = $this->stringToUTF8($request->message, $this->data_codepage);
530
+ $request->example = $this->stringToUTF8($request->example, $this->data_codepage);
531
+ $request->sender_email = $this->stringToUTF8($request->sender_email, $this->data_codepage);
532
+ $request->sender_nickname = $this->stringToUTF8($request->sender_nickname, $this->data_codepage);
533
+
534
+ $request->message = $this->compressData($request->message);
535
+ $request->example = $this->compressData($request->example);
536
+ break;
537
+
538
+ case 'check_newuser':
539
+ // Convert strings to UTF8
540
+ $request->sender_email = $this->stringToUTF8($request->sender_email, $this->data_codepage);
541
+ $request->sender_nickname = $this->stringToUTF8($request->sender_nickname, $this->data_codepage);
542
+ break;
543
+
544
+ case 'send_feedback':
545
+ if (is_array($request->feedback)) {
546
+ $request->feedback = implode(';', $request->feedback);
547
+ }
548
+ break;
549
+ }
550
+
551
+ $request->method_name = $method;
552
+
553
+ //
554
+ // Removing non UTF8 characters from request, because non UTF8 or malformed characters break json_encode().
555
+ //
556
+ foreach ($request as $param => $value) {
557
+ if (!preg_match('//u', $value)) {
558
+ $request->{$param} = 'Nulled. Not UTF8 encoded or malformed.';
559
+ }
560
+ }
561
+
562
+ return $request;
563
+ }
564
+
565
+ /**
566
+ * Send JSON request to servers
567
+ * @param $msg
568
+ * @return boolean|\CleantalkResponse
569
+ */
570
+ private function sendRequest($data = null, $url, $server_timeout = 3) {
571
+ // Convert to array
572
+ $data = json_decode(json_encode($data), true);
573
+
574
+ // Convert to JSON
575
+ $data = json_encode($data);
576
+
577
+ if (isset($this->api_version)) {
578
+ $url = $url . $this->api_version;
579
+ }
580
+
581
+ // Switching to secure connection
582
+ if ($this->ssl_on && !preg_match("/^https:/", $url)) {
583
+ $url = preg_replace("/^(http)/i", "$1s", $url);
584
+ }
585
+
586
+ $result = false;
587
+ $curl_error = null;
588
+ if(function_exists('curl_init')) {
589
+ $ch = curl_init();
590
+ curl_setopt($ch, CURLOPT_URL, $url);
591
+ curl_setopt($ch, CURLOPT_TIMEOUT, $server_timeout);
592
+ curl_setopt($ch, CURLOPT_POST, 1);
593
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
594
+ // receive server response ...
595
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
596
+ // resolve 'Expect: 100-continue' issue
597
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
598
+ // see http://stackoverflow.com/a/23322368
599
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
600
+
601
+ // Disabling CA cert verivication
602
+ // Disabling common name verification
603
+ if ($this->ssl_on) {
604
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
605
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
606
+ }
607
+
608
+ $result = curl_exec($ch);
609
+ if (!$result) {
610
+ $curl_error = curl_error($ch);
611
+ }
612
+
613
+ curl_close($ch);
614
+ }
615
+
616
+ if (!$result) {
617
+ $allow_url_fopen = ini_get('allow_url_fopen');
618
+ if (function_exists('file_get_contents') && isset($allow_url_fopen) && $allow_url_fopen == '1') {
619
+ $opts = array('http' =>
620
+ array(
621
+ 'method' => 'POST',
622
+ 'header' => "Content-Type: text/html\r\n",
623
+ 'content' => $data,
624
+ 'timeout' => $server_timeout
625
+ )
626
+ );
627
+
628
+ $context = stream_context_create($opts);
629
+ $result = @file_get_contents($url, false, $context);
630
+ }
631
+ }
632
+
633
+ if (!$result) {
634
+ $response = null;
635
+ $response['errno'] = 1;
636
+ if ($curl_error) {
637
+ $response['errstr'] = sprintf("CURL error: '%s'", $curl_error);
638
+ } else {
639
+ $response['errstr'] = 'No CURL support compiled in';
640
+ }
641
+ $response['errstr'] .= ' or disabled allow_url_fopen in php.ini.';
642
+ $response = json_decode(json_encode($response));
643
+
644
+ return $response;
645
+ }
646
+
647
+ $errstr = null;
648
+ $response = json_decode($result);
649
+ if ($result !== false && is_object($response)) {
650
+ $response->errno = 0;
651
+ $response->errstr = $errstr;
652
+ } else {
653
+ $errstr = 'Unknown response from ' . $url . '.' . ' ' . $result;
654
+
655
+ $response = null;
656
+ $response['errno'] = 1;
657
+ $response['errstr'] = $errstr;
658
+ $response = json_decode(json_encode($response));
659
+ }
660
+
661
+
662
+ return $response;
663
+ }
664
+
665
+ /**
666
+ * httpRequest
667
+ * @param $msg
668
+ * @return boolean|\CleantalkResponse
669
+ */
670
+ private function httpRequest($msg) {
671
+ $result = false;
672
+ $msg->all_headers=json_encode(apache_request_headers());
673
+ if (((isset($this->work_url) && $this->work_url !== '') && ($this->server_changed + $this->server_ttl > time()))
674
+ || $this->stay_on_server == true) {
675
+
676
+ $url = (!empty($this->work_url)) ? $this->work_url : $this->server_url;
677
+
678
+ $result = $this->sendRequest($msg, $url, $this->server_timeout);
679
+ }
680
+
681
+ if (($result === false || $result->errno != 0) && $this->stay_on_server == false) {
682
+ // Split server url to parts
683
+ preg_match("@^(https?://)([^/:]+)(.*)@i", $this->server_url, $matches);
684
+ $url_prefix = '';
685
+ if (isset($matches[1]))
686
+ $url_prefix = $matches[1];
687
+
688
+ $pool = null;
689
+ if (isset($matches[2]))
690
+ $pool = $matches[2];
691
+
692
+ $url_suffix = '';
693
+ if (isset($matches[3]))
694
+ $url_suffix = $matches[3];
695
+
696
+ if ($url_prefix === '')
697
+ $url_prefix = 'http://';
698
+
699
+ if (empty($pool)) {
700
+ return false;
701
+ } else {
702
+ // Loop until find work server
703
+ foreach ($this->get_servers_ip($pool) as $server) {
704
+ if ($server['host'] === 'localhost' || $server['ip'] === null) {
705
+ $work_url = $server['host'];
706
+ } else {
707
+ $server_host = $server['ip'];
708
+ $work_url = $server_host;
709
+ }
710
+ $work_url = $url_prefix . $work_url;
711
+ if (isset($url_suffix))
712
+ $work_url = $work_url . $url_suffix;
713
+
714
+ $this->work_url = $work_url;
715
+ $this->server_ttl = $server['ttl'];
716
+
717
+ $result = $this->sendRequest($msg, $this->work_url, $this->server_timeout);
718
+
719
+ if ($result !== false && $result->errno === 0) {
720
+ $this->server_change = true;
721
+ break;
722
+ }
723
+ }
724
+ }
725
+ }
726
+
727
+ $response = new CleantalkResponse(null, $result);
728
+
729
+ if (!empty($this->data_codepage) && $this->data_codepage !== 'UTF-8') {
730
+ if (!empty($response->comment))
731
+ $response->comment = $this->stringFromUTF8($response->comment, $this->data_codepage);
732
+ if (!empty($response->errstr))
733
+ $response->errstr = $this->stringFromUTF8($response->errstr, $this->data_codepage);
734
+ if (!empty($response->sms_error_text))
735
+ $response->sms_error_text = $this->stringFromUTF8($response->sms_error_text, $this->data_codepage);
736
+ }
737
+
738
+ return $response;
739
+ }
740
+
741
+ /**
742
+ * Function DNS request
743
+ * @param $host
744
+ * @return array
745
+ */
746
+ public function get_servers_ip($host) {
747
+ $response = null;
748
+ if (!isset($host))
749
+ return $response;
750
+
751
+ if (function_exists('dns_get_record')) {
752
+ $records = dns_get_record($host, DNS_A);
753
+
754
+ if ($records !== FALSE) {
755
+ foreach ($records as $server) {
756
+ $response[] = $server;
757
+ }
758
+ }
759
+ }
760
+
761
+ if (count($response) == 0 && function_exists('gethostbynamel')) {
762
+ $records = gethostbynamel($host);
763
+
764
+ if ($records !== FALSE) {
765
+ foreach ($records as $server) {
766
+ $response[] = array("ip" => $server,
767
+ "host" => $host,
768
+ "ttl" => $this->server_ttl
769
+ );
770
+ }
771
+ }
772
+ }
773
+
774
+ if (count($response) == 0) {
775
+ $response[] = array("ip" => null,
776
+ "host" => $host,
777
+ "ttl" => $this->server_ttl
778
+ );
779
+ } else {
780
+ // $i - to resolve collisions with localhost
781
+ $i = 0;
782
+ $r_temp = null;
783
+ $fast_server_found = false;
784
+ foreach ($response as $server) {
785
+
786
+ // Do not test servers because fast work server found
787
+ if ($fast_server_found) {
788
+ $ping = $this->min_server_timeout;
789
+ } else {
790
+ $ping = $this->httpPing($server['ip']);
791
+ $ping = $ping * 1000;
792
+ }
793
+
794
+ // -1 server is down, skips not reachable server
795
+ if ($ping != -1) {
796
+ $r_temp[$ping + $i] = $server;
797
+ }
798
+ $i++;
799
+
800
+ if ($ping < $this->min_server_timeout) {
801
+ $fast_server_found = true;
802
+ }
803
+ }
804
+ if (count($r_temp)){
805
+ ksort($r_temp);
806
+ $response = $r_temp;
807
+ }
808
+ }
809
+
810
+ return $response;
811
+ }
812
+
813
+ /**
814
+ * Function to get the message hash from Cleantalk.ru comment
815
+ * @param $message
816
+ * @return null
817
+ */
818
+ public function getCleantalkCommentHash($message) {
819
+ $matches = array();
820
+ if (preg_match('/\n\n\*\*\*.+([a-z0-9]{32}).+\*\*\*$/', $message, $matches))
821
+ return $matches[1];
822
+ else if (preg_match('/\<br.*\>[\n]{0,1}\<br.*\>[\n]{0,1}\*\*\*.+([a-z0-9]{32}).+\*\*\*$/', $message, $matches))
823
+ return $matches[1];
824
+
825
+ return NULL;
826
+ }
827
+
828
+ /**
829
+ * Function adds to the post comment Cleantalk.ru
830
+ * @param $message
831
+ * @param $comment
832
+ * @return string
833
+ */
834
+ public function addCleantalkComment($message, $comment) {
835
+ $comment = preg_match('/\*\*\*(.+)\*\*\*/', $comment, $matches) ? $comment : '*** ' . $comment . ' ***';
836
+ return $message . "\n\n" . $comment;
837
+ }
838
+
839
+ /**
840
+ * Function deletes the comment Cleantalk.ru
841
+ * @param $message
842
+ * @return mixed
843
+ */
844
+ public function delCleantalkComment($message) {
845
+ $message = preg_replace('/\n\n\*\*\*.+\*\*\*$/', '', $message);
846
+
847
+ // DLE sign cut
848
+ $message = preg_replace('/<br\s?\/><br\s?\/>\*\*\*.+\*\*\*$/', '', $message);
849
+
850
+ $message = preg_replace('/\<br.*\>[\n]{0,1}\<br.*\>[\n]{0,1}\*\*\*.+\*\*\*$/', '', $message);
851
+
852
+ return $message;
853
+ }
854
+
855
+ /**
856
+ * Get user IP behind proxy server
857
+ */
858
+ public function ct_session_ip( $data_ip ) {
859
+ if (!$data_ip || !preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $data_ip)) {
860
+ return $data_ip;
861
+ }
862
+ if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
863
+
864
+ $forwarded_ip = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);
865
+
866
+ // Looking for first value in the list, it should be sender real IP address
867
+ if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $forwarded_ip[0])) {
868
+ return $data_ip;
869
+ }
870
+
871
+ $private_src_ip = false;
872
+ $private_nets = array(
873
+ '10.0.0.0/8',
874
+ '127.0.0.0/8',
875
+ '176.16.0.0/12',
876
+ '192.168.0.0/16',
877
+ );
878
+
879
+ foreach ($private_nets as $v) {
880
+
881
+ // Private IP found
882
+ if ($private_src_ip) {
883
+ continue;
884
+ }
885
+
886
+ if ($this->net_match($v, $data_ip)) {
887
+ $private_src_ip = true;
888
+ }
889
+ }
890
+ if ($private_src_ip) {
891
+ // Taking first IP from the list HTTP_X_FORWARDED_FOR
892
+ $data_ip = $forwarded_ip[0];
893
+ }
894
+ }
895
+
896
+ return $data_ip;
897
+ }
898
+
899
+ /**
900
+ * From http://php.net/manual/en/function.ip2long.php#82397
901
+ */
902
+ public function net_match($CIDR,$IP) {
903
+ list ($net, $mask) = explode ('/', $CIDR);
904
+ return ( ip2long ($IP) & ~((1 << (32 - $mask)) - 1) ) == ip2long ($net);
905
+ }
906
+
907
+ /**
908
+ * Function to check response time
909
+ * param string
910
+ * @return int
911
+ */
912
+ function httpPing($host){
913
+
914
+ // Skip localhost ping cause it raise error at fsockopen.
915
+ // And return minimun value
916
+ if ($host == 'localhost')
917
+ return 0.001;
918
+
919
+ $starttime = microtime(true);
920
+ $file = @fsockopen ($host, 80, $errno, $errstr, $this->server_timeout);
921
+ $stoptime = microtime(true);
922
+ $status = 0;
923
+ if (!$file) {
924
+ $status = -1; // Site is down
925
+ } else {
926
+ fclose($file);
927
+ $status = ($stoptime - $starttime);
928
+ $status = round($status, 4);
929
+ }
930
+
931
+ return $status;
932
+ }
933
+
934
+ /**
935
+ * Function convert string to UTF8 and removes non UTF8 characters
936
+ * param string
937
+ * param string
938
+ * @return string
939
+ */
940
+ function stringToUTF8($str, $data_codepage = null){
941
+ if (!preg_match('//u', $str) && function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) {
942
+
943
+ if ($data_codepage !== null)
944
+ return mb_convert_encoding($str, 'UTF-8', $data_codepage);
945
+
946
+ $encoding = mb_detect_encoding($str);
947
+ if ($encoding)
948
+ return mb_convert_encoding($str, 'UTF-8', $encoding);
949
+ }
950
+
951
+ return $str;
952
+ }
953
+
954
+ /**
955
+ * Function convert string from UTF8
956
+ * param string
957
+ * param string
958
+ * @return string
959
+ */
960
+ function stringFromUTF8($str, $data_codepage = null){
961
+ if (preg_match('//u', $str) && function_exists('mb_convert_encoding') && $data_codepage !== null) {
962
+ return mb_convert_encoding($str, $data_codepage, 'UTF-8');
963
+ }
964
+
965
+ return $str;
966
+ }
967
+ }
968
+
969
+ /**
970
+ * Function gets access key automatically
971
+ *
972
+ * @param string website admin email
973
+ * @param string website host
974
+ * @param string website platform
975
+ * @return type
976
+ */
977
+
978
+ function getAutoKey($email, $host, $platform)
979
+ {
980
+ $request=Array();
981
+ $request['method_name'] = 'get_api_key';
982
+ $request['email'] = $email;
983
+ $request['website'] = $host;
984
+ $request['platform'] = $platform;
985
+ $url='https://api.cleantalk.org';
986
+ $result=sendRawRequest($url,$request);
987
+ return $result;
988
+ }
989
+
990
+ /**
991
+ * Function gets information about renew notice
992
+ *
993
+ * @param string api_key
994
+ * @return type
995
+ */
996
+
997
+ function noticePaidTill($api_key)
998
+ {
999
+ $request=Array();
1000
+ $request['method_name'] = 'notice_paid_till';
1001
+ $request['auth_key'] = $api_key;
1002
+ $url='https://api.cleantalk.org';
1003
+ $result=sendRawRequest($url,$request);
1004
+ return $result;
1005
+ }
1006
+
1007
+ /**
1008
+ * Function sends raw request to API server
1009
+ *
1010
+ * @param string url of API server
1011
+ * @param array data to send
1012
+ * @param boolean is data have to be JSON encoded or not
1013
+ * @param integer connect timeout
1014
+ * @return type
1015
+ */
1016
+
1017
+ function sendRawRequest($url,$data,$isJSON=false,$timeout=3)
1018
+ {
1019
+ $result=null;
1020
+ if(!$isJSON)
1021
+ {
1022
+ $data=http_build_query($data);
1023
+ }
1024
+ else
1025
+ {
1026
+ $data= json_encode($data);
1027
+ }
1028
+ if (function_exists('curl_init') && function_exists('json_decode'))
1029
+ {
1030
+
1031
+ $ch = curl_init();
1032
+ curl_setopt($ch, CURLOPT_URL, $url);
1033
+ curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1034
+ curl_setopt($ch, CURLOPT_POST, true);
1035
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
1036
+
1037
+ // receive server response ...
1038
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1039
+ // resolve 'Expect: 100-continue' issue
1040
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
1041
+
1042
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
1043
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
1044
+
1045
+ $result = curl_exec($ch);
1046
+ curl_close($ch);
1047
+ }
1048
+ else
1049
+ {
1050
+ $opts = array(
1051
+ 'http'=>array(
1052
+ 'method'=>"POST",
1053
+ 'content'=>$data)
1054
+ );
1055
+ $context = stream_context_create($opts);
1056
+ $result = @file_get_contents($url, 0, $context);
1057
+ }
1058
+ return $result;
1059
+ }
1060
+
1061
+ if( !function_exists('apache_request_headers') )
1062
+ {
1063
+ function apache_request_headers()
1064
+ {
1065
+ $arh = array();
1066
+ $rx_http = '/\AHTTP_/';
1067
+ if(defined('IN_PHPBB'))
1068
+ {
1069
+ global $request;
1070
+ $request->enable_super_globals();
1071
+ }
1072
+ foreach($_SERVER as $key => $val)
1073
+ {
1074
+ if( preg_match($rx_http, $key) )
1075
+ {
1076
+ $arh_key = preg_replace($rx_http, '', $key);
1077
+ $rx_matches = array();
1078
+ $rx_matches = explode('_', $arh_key);
1079
+ if( count($rx_matches) > 0 and strlen($arh_key) > 2 )
1080
+ {
1081
+ foreach($rx_matches as $ak_key => $ak_val) $rx_matches[$ak_key] = ucfirst($ak_val);
1082
+ $arh_key = implode('-', $rx_matches);
1083
+ }
1084
+ $arh[$arh_key] = $val;
1085
+ }
1086
+ }
1087
+ if(defined('IN_PHPBB'))
1088
+ {
1089
+ global $request;
1090
+ $request->disable_super_globals();
1091
+ }
1092
+ return( $arh );
1093
+ }
1094
+ }
1095
+ ?>
app/code/community/Cleantalk/Antispam/controllers/Contacts/IndexController.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/controllers/Customer/AccountController.php CHANGED
File without changes
app/code/community/Cleantalk/Antispam/etc/config.xml CHANGED
@@ -1,7 +1,7 @@
1
  <config>
2
  <modules>
3
  <Cleantalk_Antispam>
4
- <version>1.2.0</version>
5
  </Cleantalk_Antispam>
6
  </modules>
7
  <adminhtml>
1
  <config>
2
  <modules>
3
  <Cleantalk_Antispam>
4
+ <version>1.2.2</version>
5
  </Cleantalk_Antispam>
6
  </modules>
7
  <adminhtml>
app/code/community/Cleantalk/Antispam/etc/system.xml CHANGED
File without changes
app/code/community/Cleantalk/Antispam/sql/cleantalk_antispam_setup/{install-0.9.2.php → install-1.2.1.php} RENAMED
File without changes
app/design/adminhtml/default/default/layout/cleantalk/antispam.xml CHANGED
File without changes
app/design/frontend/base/default/layout/antispam.xml CHANGED
File without changes
app/design/frontend/base/default/template/cleantalk/antispam/page_addon.phtml CHANGED
File without changes
app/etc/modules/Cleantalk_Antispam.xml CHANGED
@@ -4,7 +4,7 @@
4
  <Cleantalk_Antispam>
5
  <active>true</active>
6
  <codePool>community</codePool>
7
- <version>0.9.2</version>
8
  </Cleantalk_Antispam>
9
  </modules>
10
  </config>
4
  <Cleantalk_Antispam>
5
  <active>true</active>
6
  <codePool>community</codePool>
7
+ <version>1.2.2</version>
8
  </Cleantalk_Antispam>
9
  </modules>
10
  </config>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Cleantalk_Antispam</name>
4
- <version>1.2.0</version>
5
  <stability>stable</stability>
6
  <license>GPL</license>
7
  <channel>community</channel>
@@ -45,12 +45,12 @@ Current Magento module details:&#xD;
45
  &lt;/ul&gt;&#xD;
46
  &lt;/p&gt;&#xD;
47
  </description>
48
- <notes>Added automatic reception of API key.&#xD;
49
- Added universal anti-spam forms checking.</notes>
50
  <authors><author><name>CleanTalk.Org</name><user>cleantalk</user><email>welcome@cleantalk.org</email></author></authors>
51
- <date>2015-04-28</date>
52
- <time>18:22:19</time>
53
- <contents><target name="magecommunity"><dir name="Cleantalk"><dir name="Antispam"><dir name="Block"><file name="Antispam.php" hash="ac7ca7d7d54780fd2d10631751e510dc"/><dir name="adminhtml"><file name="Notifications.php" hash="9cd13b972137786380697bbb7efd1be3"/></dir></dir><dir name="Helper"><file name="Data.php" hash="4634f33383dea8bdc330f42a3e5163b6"/></dir><dir name="Model"><file name="Api.php" hash="054763da367bbc3c0c4d0b6ef601b320"/><file name="Observer.php" hash="9d2a3f94c10f6e4b40bf658eb295e3a5"/><dir name="Resource"><file name="Server.php" hash="32f720d8083f09a59efb1516f2680ae2"/><file name="Timelabels.php" hash="e58a95495c8f34fdf757bcbd50335b57"/></dir><file name="Review.php" hash="8000551a7573d6e8b0a12f2a1897c067"/><file name="Server.php" hash="6f95b3579c3a2541011648f3c3eb374d"/><file name="Timelabels.php" hash="02a727f13ed833c233533b2f9f99a27d"/><file name="error.html" hash="4f34620367d82f9e77cfab7f35ea9df7"/><dir name="lib"><file name="JSON.php" hash="13c254265bb582c52f96d64971ab24df"/><file name="cleantalk.class.php" hash="6fc472296f93668473076523347eb2aa"/></dir></dir><dir name="controllers"><dir name="Contacts"><file name="IndexController.php" hash="ca35c9c50546bbe678920a1149b68c33"/></dir><dir name="Customer"><file name="AccountController.php" hash="b959e7e8e979dbafd3480565d5fd99a9"/></dir></dir><dir name="etc"><file name="config.xml" hash="7f88bac21bcfe51e648b6fa2333e3efd"/><file name="system.xml" hash="341390544fc21d544a38cf1570a0f975"/></dir><dir name="sql"><dir name="cleantalk_antispam_setup"><file name="install-0.9.2.php" hash="a3f233fdf6c1987962cc7d579b555ab3"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="antispam.xml" hash="f2bd6b5e52407255d1ad1ce443bde0b2"/></dir><dir name="template"><dir name="cleantalk"><dir name="antispam"><file name="page_addon.phtml" hash="0feda49e1149f0416cfe787b5a93eec4"/></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="cleantalk"><file name="antispam.xml" hash="b4d926a64fc9d459acc3ed3618ac4a92"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Cleantalk_Antispam.xml" hash="13a000f250a4c856aa9e9eb18bd4a827"/></dir></target></contents>
54
  <compatible/>
55
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
56
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Cleantalk_Antispam</name>
4
+ <version>1.2.2</version>
5
  <stability>stable</stability>
6
  <license>GPL</license>
7
  <channel>community</channel>
45
  &lt;/ul&gt;&#xD;
46
  &lt;/p&gt;&#xD;
47
  </description>
48
+ <notes>Fixed login form checking.&#xD;
49
+ Changed connection test method.</notes>
50
  <authors><author><name>CleanTalk.Org</name><user>cleantalk</user><email>welcome@cleantalk.org</email></author></authors>
51
+ <date>2016-07-25</date>
52
+ <time>23:21:51</time>
53
+ <contents><target name="magecommunity"><dir name="Cleantalk"><dir name="Antispam"><dir name="Block"><file name="Antispam.php" hash="ac7ca7d7d54780fd2d10631751e510dc"/><dir name="adminhtml"><file name="Notifications.php" hash="9cd13b972137786380697bbb7efd1be3"/></dir></dir><dir name="Helper"><file name="Data.php" hash="4634f33383dea8bdc330f42a3e5163b6"/></dir><dir name="Model"><file name="Api.php" hash="054763da367bbc3c0c4d0b6ef601b320"/><file name="Observer.php" hash="7695c105097fc888791e10ac9ffb0ef6"/><dir name="Resource"><file name="Server.php" hash="32f720d8083f09a59efb1516f2680ae2"/><file name="Timelabels.php" hash="e58a95495c8f34fdf757bcbd50335b57"/></dir><file name="Review.php" hash="8000551a7573d6e8b0a12f2a1897c067"/><file name="Server.php" hash="6f95b3579c3a2541011648f3c3eb374d"/><file name="Timelabels.php" hash="02a727f13ed833c233533b2f9f99a27d"/><file name="error.html" hash="4f34620367d82f9e77cfab7f35ea9df7"/><dir name="lib"><file name="JSON.php" hash="13c254265bb582c52f96d64971ab24df"/><file name="cleantalk.class.php" hash="6fc472296f93668473076523347eb2aa"/></dir></dir><dir name="controllers"><dir name="Contacts"><file name="IndexController.php" hash="ca35c9c50546bbe678920a1149b68c33"/></dir><dir name="Customer"><file name="AccountController.php" hash="b959e7e8e979dbafd3480565d5fd99a9"/></dir></dir><dir name="etc"><file name="config.xml" hash="7f88bac21bcfe51e648b6fa2333e3efd"/><file name="system.xml" hash="341390544fc21d544a38cf1570a0f975"/></dir><dir name="sql"><dir name="cleantalk_antispam_setup"><file name="install-1.2.1.php" hash="a3f233fdf6c1987962cc7d579b555ab3"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="antispam.xml" hash="f2bd6b5e52407255d1ad1ce443bde0b2"/></dir><dir name="template"><dir name="cleantalk"><dir name="antispam"><file name="page_addon.phtml" hash="0feda49e1149f0416cfe787b5a93eec4"/></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="cleantalk"><file name="antispam.xml" hash="b4d926a64fc9d459acc3ed3618ac4a92"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Cleantalk_Antispam.xml" hash="13a000f250a4c856aa9e9eb18bd4a827"/></dir></target></contents>
54
  <compatible/>
55
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
56
  </package>