u
chenl
2018-12-18 0def1da51ab25b91755fc0138812426eeecce5dc
commit | author | age
601f79 1 <?php
G 2
3 define('IN_API', true);
4 require_once './framework/bootstrap.inc.php';
5 load()->model('reply');
6 load()->model('attachment');
7
8     load()->model('visit');
9
10 load()->app('common');
11 load()->classs('wesession');
12 $hash = $_GPC['hash'];
13 if(!empty($hash)) {
14     $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account') . " WHERE hash = :hash", array(':hash' => $hash));
15 }
16 if(!empty($_GPC['appid'])) {
17     $appid = ltrim($_GPC['appid'], '/');
18     if ($appid == 'wx570bc396a51b8ff8') {
19         $_W['account'] = array(
20             'type' => '3',
21             'key' => 'wx570bc396a51b8ff8',
22             'level' => 4,
23             'token' => 'platformtestaccount'
24         );
25     } else {
26         $id = pdo_fetchcolumn("SELECT acid FROM " . tablename('account_wechats') . " WHERE `key` = :appid", array(':appid' => $appid));
27     }
28 }
29 if(empty($id)) {
30     $id = intval($_GPC['id']);
31 }
32 if (!empty($id)) {
33     $uniacid = pdo_getcolumn('account', array('acid' => $id), 'uniacid');
34     $_W['account'] = uni_fetch($uniacid);
35 }
36 if(empty($_W['account'])) {
37     exit('initial error hash or id');
38 }
39 if(empty($_W['account']['token'])) {
40     exit('initial missing token');
41 }
42 $_W['debug'] = intval($_GPC['debug']);
43 $_W['acid'] = $_W['account']['acid'];
44 $_W['uniacid'] = $_W['account']['uniacid'];
45 $_W['uniaccount'] = uni_fetch($_W['uniacid']);
46 $_W['account']['groupid'] = $_W['uniaccount']['groupid'];
47 $_W['account']['qrcode'] = $_W['attachurl'].'qrcode_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
48 $_W['account']['avatar'] = $_W['attachurl'].'headimg_'.$_W['acid'].'.jpg?time='.$_W['timestamp'];
49 $_W['attachurl'] = attachment_set_attach_url();
50
51     visit_update_today('web', 'we7_api');
52
53
54 $engine = new WeEngine();
55 if (!empty($_W['setting']['copyright']['status'])) {
56     $engine->died('抱歉,站点已关闭,关闭原因:' . $_W['setting']['copyright']['reason']);
57 }
58 if (!empty($_W['uniaccount']['endtime']) && TIMESTAMP > $_W['uniaccount']['endtime']) {
59     $engine->died('抱歉,您的公众号已过期,请及时联系管理员');
60 }
61
62 if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 1) {
63     $engine->encrypt();
64 }
65 if($_W['isajax'] && $_W['ispost'] && $_GPC['flag'] == 2) {
66     $engine->decrypt();
67 }
68 load()->func('compat.biz');
69 $_W['isajax'] = false;
70 $engine->start();
71
72
73 class WeEngine {
74     
75     private $account = null;
76     
77     private $modules = array();
78     
79     public $keyword = array();
80     
81     public $message = array();
82
83     
84     public function __construct() {
85         global $_W;
86         $this->account = WeAccount::create($_W['account']);
87         if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
88             $_W['modules'] = uni_modules();
89             $this->modules = array_keys($_W['modules']);
90             $this->modules[] = 'cover';
91             $this->modules[] = 'default';
92             $this->modules[] = 'reply';
93             $this->modules = array_unique ($this->modules);
94         }
95     }
96
97     
98     public function encrypt() {
99         global $_W;
100         if(empty($this->account)) {
101             exit('Miss Account.');
102         }
103         $timestamp = TIMESTAMP;
104         $nonce = random(5);
105         $token = $_W['account']['token'];
106         $signkey = array($token, TIMESTAMP, $nonce);
107         sort($signkey, SORT_STRING);
108         $signString = implode($signkey);
109         $signString = sha1($signString);
110
111         $_GET['timestamp'] = $timestamp;
112         $_GET['nonce'] = $nonce;
113         $_GET['signature'] = $signString;
114         $postStr = file_get_contents('php://input');
115         if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
116             $data = $this->account->encryptMsg($postStr);
117             $array = array('encrypt_type' => 'aes', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
118         } else {
119             $data = array('', '');
120             $array = array('encrypt_type' => '', 'timestamp' => $timestamp, 'nonce' => $nonce, 'signature' => $signString, 'msg_signature' => $data[0], 'msg' => $data[1]);
121         }
122         exit(json_encode($array));
123     }
124
125     
126     public function decrypt() {
127         global $_W;
128         if(empty($this->account)) {
129             exit('Miss Account.');
130         }
131         $postStr = file_get_contents('php://input');
132         if(!empty($_W['account']['encodingaeskey']) && strlen($_W['account']['encodingaeskey']) == 43 && !empty($_W['account']['key']) && $_W['setting']['development'] != 1) {
133             $resp = $this->account->local_decryptMsg($postStr);
134         } else {
135             $resp = $postStr;
136         }
137         exit($resp);
138     }
139
140     
141     public function start() {
142         global $_W;
143         if(empty($this->account)) {
144             exit('Miss Account.');
145         }
146         if(!$this->account->checkSign()) {
147             exit('Check Sign Fail.');
148         }
149         if(strtolower($_SERVER['REQUEST_METHOD']) == 'get') {
150             $row = array();
151             $row['isconnect'] = 1;
152             pdo_update('account', $row, array('acid' => $_W['acid']));
153             cache_delete(cache_system_key('uniaccount', array('uniacid' => $_W['uniacid'])));
154             exit(htmlspecialchars($_GET['echostr']));
155         }
156         if(strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
157             $postStr = file_get_contents('php://input');
158                         if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
159                 $postStr = $this->account->decryptMsg($postStr);
160             }
161             WeUtility::logging('trace', $postStr);
162             $message = $this->account->parse($postStr);
163
164             $this->message = $message;
165             if(empty($message)) {
166                 WeUtility::logging('waring', 'Request Failed');
167                 exit('Request Failed');
168             }
169             $_W['openid'] = $message['from'];
170             $_W['fans'] = array('from_user' => $_W['openid']);
171             $this->booking($message);
172             if($message['event'] == 'unsubscribe') {
173                 $this->receive(array(), array(), array());
174                 exit();
175             }
176             $sessionid = md5($message['from'] . $message['to'] . $_W['uniacid']);
177             session_id($sessionid);
178             WeSession::start($_W['uniacid'], $_W['openid']);
179
180             $_SESSION['openid'] = $_W['openid'];
181             $pars = $this->analyze($message);
182             $pars[] = array(
183                 'message' => $message,
184                 'module' => 'default',
185                 'rule' => '-1',
186             );
187             $hitParam['rule'] = -2;
188             $hitParam['module'] = '';
189             $hitParam['message'] = $message;
190
191             $hitKeyword = array();
192             $response = array();
193             foreach($pars as $par) {
194                 if(empty($par['module'])) {
195                     continue;
196                 }
197                 $par['message'] = $message;
198                 $response = $this->process($par);
199                 if($this->isValidResponse($response)) {
200                     $hitParam = $par;
201                     if(!empty($par['keyword'])) {
202                         $hitKeyword = $par['keyword'];
203                     }
204                     break;
205                 }
206             }
207             $response_debug = $response;
208             $pars_debug = $pars;
209             if($hitParam['module'] == 'default' && is_array($response) && is_array($response['params'])) {
210                 foreach($response['params'] as $par) {
211                     if(empty($par['module'])) {
212                         continue;
213                     }
214                     $response = $this->process($par);
215                     if($this->isValidResponse($response)) {
216                         $hitParam = $par;
217                         if(!empty($par['keyword'])) {
218                             $hitKeyword = $par['keyword'];
219                         }
220                         break;
221                     }
222                 }
223             }
224             WeUtility::logging('params', var_export($hitParam, true));
225             WeUtility::logging('response', $response);
226             $resp = $this->account->response($response);
227                         if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
228                 $resp = $this->account->encryptMsg($resp);
229                 $resp = $this->account->xmlDetract($resp);
230             }
231             if($_W['debug']) {
232                 $_W['debug_data'] = array(
233                     'resp' => $resp,
234                     'is_default' => 0
235                 );
236                 if(count($pars_debug) == 1) {
237                     $_W['debug_data']['is_default'] = 1;
238                     $_W['debug_data']['params'] = $response_debug['params'];
239                 } else {
240                     array_pop($pars_debug);
241                     $_W['debug_data']['params'] = $pars_debug;
242                 }
243                 $_W['debug_data']['hitparam'] = $hitParam;
244                 $_W['modules']['cover'] = array('title' => '入口封面', 'name' => 'cover');
245
246                 load()->web('template');
247                 $process = template('utility/emulator', TEMPLATE_FETCH);
248                 echo json_encode(array('resp' => $resp, 'process' => $process));
249                 exit();
250             }
251             if ($resp !== 'success') {
252                 $mapping = array(
253                     '[from]' => $this->message['from'],
254                     '[to]' => $this->message['to'],
255                     '[rule]' => $this->params['rule']
256                 );
257                 $resp = str_replace(array_keys($mapping), array_values($mapping), $resp);
258             }
259
260             $reply_times_info = (array)$_SESSION['__reply_times'];
261             if ($reply_times_info['content'] == $message['content']) {
262                 $new_times = intval($reply_times_info['times']) + 1;
263             } else {
264                 $new_times = 1;
265             }
266             $_SESSION['__reply_times'] = array('content' => $message['content'], 'date' => date('Y-m-d'), 'times' => $new_times);
267             ob_start();
268             echo $resp;
269             ob_start();
270             $this->receive($hitParam, $hitKeyword, $response);
271             ob_end_clean();
272             exit();
273         }
274         WeUtility::logging('waring', 'Request Failed');
275         exit('Request Failed');
276     }
277
278     private function isValidResponse($response) {
279         if ($response === 'success') {
280             return true;
281         }
282         if(is_array($response)) {
283             if($response['type'] == 'text' && !empty($response['content'])) {
284                 return true;
285             }
286             if($response['type'] == 'news' && !empty($response['items'])) {
287                 return true;
288             }
289             if(!in_array($response['type'], array('text', 'news', 'image'))) {
290                 return true;
291             }
292         }
293         return false;
294     }
295
296     
297     private function booking($message) {
298         global $_W;
299         if ($message['event'] == 'unsubscribe' || $message['event'] == 'subscribe') {
300             $todaystat = pdo_get('stat_fans', array('date' => date('Ymd'), 'uniacid' => $_W['uniacid']));
301             if ($message['event'] == 'unsubscribe') {
302                 if (empty($todaystat)) {
303                     $updatestat = array(
304                         'new' => 0,
305                         'uniacid' => $_W['uniacid'],
306                         'cancel' => 1,
307                         'cumulate' => 0,
308                         'date' => date('Ymd'),
309                     );
310                     pdo_insert('stat_fans', $updatestat);
311                 } else {
312                     $updatestat = array(
313                         'cancel' => $todaystat['cancel'] + 1,
314                     );
315                     $updatestat['cumulate'] = 0;
316                     pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
317                 }
318             } elseif ($message['event'] == 'subscribe') {
319                 if (empty($todaystat)) {
320                     $updatestat = array(
321                         'new' => 1,
322                         'uniacid' => $_W['uniacid'],
323                         'cancel' => 0,
324                         'cumulate' => 0,
325                         'date' => date('Ymd'),
326                     );
327                     pdo_insert('stat_fans', $updatestat);
328                 } else {
329                     $updatestat = array(
330                         'new' => $todaystat['new'] + 1,
331                         'cumulate' => 0,
332                     );
333                     pdo_update('stat_fans', $updatestat, array('id' => $todaystat['id']));
334                 }
335             }
336         }
337
338         load()->model('mc');
339         $setting = uni_setting($_W['uniacid'], array('passport'));
340         $fans = mc_fansinfo($message['from']);
341         $default_groupid = cache_load(cache_system_key('defaultgroupid', array('uniacid' => $_W['uniacid'])));
342         if (empty($default_groupid)) {
343             $default_groupid = pdo_fetchcolumn('SELECT groupid FROM ' .tablename('mc_groups') . ' WHERE uniacid = :uniacid AND isdefault = 1', array(':uniacid' => $_W['uniacid']));
344             cache_write(cache_system_key('defaultgroupid', array('uniacid' => $_W['uniacid'])), $default_groupid);
345         }
346         if(!empty($fans)) {
347             if ($message['event'] == 'unsubscribe') {
348                 cache_build_memberinfo($fans['uid']);
349                 pdo_update('mc_mapping_fans', array('follow' => 0, 'unfollowtime' => TIMESTAMP), array('fanid' => $fans['fanid']));
350                 pdo_delete('mc_fans_tag_mapping', array('fanid' => $fans['fanid']));
351             } elseif ($message['event'] != 'ShakearoundUserShake' && $message['type'] != 'trace') {
352                 $rec = array();
353                 if (empty($fans['follow'])) {
354                     $rec['follow'] = 1;
355                     $rec['followtime'] = $message['time'];
356                 }
357                 $member = array();
358                 if(!empty($fans['uid'])){
359                     $member = mc_fetch($fans['uid']);
360                 }
361                 if (empty($member)) {
362                     if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
363                         $data = array(
364                             'uniacid' => $_W['uniacid'],
365                             'email' => md5($message['from']).'@we7.cc',
366                             'salt' => random(8),
367                             'groupid' => $default_groupid,
368                             'createtime' => TIMESTAMP,
369                         );
370                         $data['password'] = md5($message['from'] . $data['salt'] . $_W['config']['setting']['authkey']);
371                         pdo_insert('mc_members', $data);
372                         $rec['uid'] = pdo_insertid();
373                     }
374                 }
375                 if(!empty($rec)){
376                     pdo_update('mc_mapping_fans', $rec, array('openid' => $message['from']));
377                 }
378             }
379         } else {
380             if ($message['event'] == 'subscribe' || $message['type'] == 'text' || $message['type'] == 'image') {
381                 load()->model('mc');
382                 $force_init_member = false;
383                 if (!isset($setting['passport']) || empty($setting['passport']['focusreg'])) {
384                     $force_init_member = true;
385                 }
386                 mc_init_fans_info($message['from'], $force_init_member);
387             }
388         }
389     }
390
391     private function receive($par, $keyword, $response) {
392         global $_W;
393         fastcgi_finish_request();
394
395         $subscribe = cache_load(cache_system_key('module_receive_enable'));
396         if (empty($subscribe)) {
397             $subscribe = cache_build_module_subscribe_type();
398         }
399         $modules = uni_modules();
400         $obj = WeUtility::createModuleReceiver('core');
401         $obj->message = $this->message;
402         $obj->params = $par;
403         $obj->response = $response;
404         $obj->keyword = $keyword;
405         $obj->module = 'core';
406         $obj->uniacid = $_W['uniacid'];
407         $obj->acid = $_W['acid'];
408         if(method_exists($obj, 'receive')) {
409             @$obj->receive();
410         }
411         load()->func('communication');
412         if (empty($subscribe[$this->message['type']]) && !empty($this->message['event'])) {
413             $subscribe[$this->message['type']] = $subscribe[strtolower($this->message['event'])];
414         }
415         if (!empty($subscribe[$this->message['type']])) {
416             foreach ($subscribe[$this->message['type']] as $modulename) {
417                                                                 $params = array(
418                     'i' => $GLOBALS['uniacid'],
419                     'modulename' => $modulename,
420                     'request' => json_encode($par),
421                     'response' => json_encode($response),
422                     'message' => json_encode($this->message),
423                 );
424                 $response = ihttp_request(wurl('utility/subscribe/receive'), $params, array(), 10);
425                 if (is_error($response) || $response['code'] != 200) {
426                     $response = ihttp_request($_W['siteroot'] . 'web/' . wurl('utility/subscribe/receive'), $params, array(), 10);
427                 }
428             }
429         }
430     }
431
432     
433     private function analyze(&$message) {
434         global $_W;
435         $params = array();
436         if(in_array($message['type'], array('event', 'qr'))) {
437             $params = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
438             if(!empty($params)) {
439                 return (array)$params;
440             }
441         }
442         if(!empty($_SESSION['__contextmodule']) && in_array($_SESSION['__contextmodule'], $this->modules)) {
443             if($_SESSION['__contextexpire'] > TIMESTAMP) {
444                 $params[] = array(
445                     'message' => $message,
446                     'module' => $_SESSION['__contextmodule'],
447                     'rule' => $_SESSION['__contextrule'],
448                     'priority' => $_SESSION['__contextpriority'],
449                     'context' => true
450                 );
451                 return $params;
452             } else {
453                 unset($_SESSION);
454                 session_destroy();
455             }
456         }
457
458         $reply_times_info = (array)$_SESSION['__reply_times'];
459         if (!empty($_W['account']['setting']) && !empty($reply_times_info) && intval($_W['account']['setting']['reply_setting']) > 0 && strtotime($reply_times_info['date']) >= strtotime(date('Y-m-d')) && $reply_times_info['times'] >= $_W['account']['setting']['reply_setting'] && $reply_times_info['content'] == $message['content']) {
460             exit('success');
461         }
462
463         if(method_exists($this, 'analyze' . $message['type'])) {
464             $temp = call_user_func_array(array($this, 'analyze' . $message['type']), array(&$message));
465             if(!empty($temp) && is_array($temp)){
466                 $params += $temp;
467             }
468         } else {
469             $params += $this->handler($message['type']);
470         }
471         return $params;
472     }
473
474     private function analyzeSubscribe(&$message) {
475         global $_W;
476         $params = array();
477         $message['type'] = 'text';
478         $message['redirection'] = true;
479         if(!empty($message['scene'])) {
480             $message['source'] = 'qr';
481             $sceneid = trim($message['scene']);
482             $scene_condition = '';
483             if (is_numeric($sceneid)) {
484                 $scene_condition = " `qrcid` = '{$sceneid}'";
485             }else{
486                 $scene_condition = " `scene_str` = '{$sceneid}'";
487             }
488             $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = '{$_W['uniacid']}'");
489             if(!empty($qr)) {
490                 $message['content'] = $qr['keyword'];
491                 if (!empty($qr['type']) && $qr['type'] == 'scene') {
492                     $message['msgtype'] = 'text';
493                 }
494                 $params += $this->analyzeText($message);
495                 return $params;
496             }
497         }
498         $message['source'] = 'subscribe';
499         $setting = uni_setting($_W['uniacid'], array('welcome'));
500         if(!empty($setting['welcome'])) {
501             $message['content'] = $setting['welcome'];
502             $params += $this->analyzeText($message);
503         }
504
505         return $params;
506     }
507
508     private function analyzeQR(&$message) {
509         global $_W;
510         $params = array();
511         $params = $this->handler($message['type']);
512         if (!empty($params)) {
513             return $params;
514         }
515         $message['type'] = 'text';
516         $message['redirection'] = true;
517         if(!empty($message['scene'])) {
518             $message['source'] = 'qr';
519             $sceneid = trim($message['scene']);
520             $scene_condition = '';
521             if (is_numeric($sceneid)) {
522                 $scene_condition = " `qrcid` = '{$sceneid}'";
523             }else{
524                 $scene_condition = " `scene_str` = '{$sceneid}'";
525             }
526             $qr = pdo_fetch("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE {$scene_condition} AND `uniacid` = '{$_W['uniacid']}'");
527
528         }
529         if (empty($qr) && !empty($message['ticket'])) {
530             $message['source'] = 'qr';
531             $ticket = trim($message['ticket']);
532             if(!empty($ticket)) {
533                 $qr = pdo_fetchall("SELECT `id`, `keyword` FROM " . tablename('qrcode') . " WHERE `uniacid` = '{$_W['uniacid']}' AND ticket = '{$ticket}'");
534                 if(!empty($qr)) {
535                     if(count($qr) != 1) {
536                         $qr = array();
537                     } else {
538                         $qr = $qr[0];
539                     }
540                 }
541             }
542         }
543         if(!empty($qr)) {
544             $message['content'] = $qr['keyword'];
545             if (!empty($qr['type']) && $qr['type'] == 'scene') {
546                 $message['msgtype'] = 'text';
547             }
548             $params += $this->analyzeText($message);
549         }
550         return $params;
551     }
552
553     public function analyzeText(&$message, $order = 0) {
554         global $_W;
555
556         $pars = array();
557
558         $order = intval($order);
559         if(!isset($message['content'])) {
560             return $pars;
561         }
562                 $condition = <<<EOF
563 `uniacid` IN ( 0, {$_W['uniacid']} )
564 AND
565 (
566     ( `type` = 1 AND `content` = :c1 )
567     or
568     ( `type` = 2 AND instr(:c2, `content`) )
569     or
570     ( `type` = 3 AND :c3 REGEXP `content` )
571     or
572     ( `type` = 4 )
573 )
574 AND `status`=1
575 EOF;
576
577         $params = array();
578         $params[':c1'] = $message['content'];
579         $params[':c2'] = $message['content'];
580         $params[':c3'] = $message['content'];
581
582         if (intval($order) > 0) {
583             $condition .= " AND `displayorder` > :order";
584             $params[':order'] = $order;
585         }
586
587         $keywords = reply_keywords_search($condition, $params);
588         if(empty($keywords)) {
589             return $pars;
590         }
591         foreach($keywords as $keyword) {
592             $params = array(
593                 'message' => $message,
594                 'module' => $keyword['module'],
595                 'rule' => $keyword['rid'],
596                 'priority' => $keyword['displayorder'],
597                 'keyword' => $keyword,
598                 'reply_type' => $keyword['reply_type']
599             );
600             $pars[] = $params;
601         }
602         return $pars;
603     }
604
605     private function analyzeEvent(&$message) {
606         if (strtolower($message['event']) == 'subscribe') {
607             return $this->analyzeSubscribe($message);
608         }
609         if (strtolower($message['event']) == 'click') {
610             $message['content'] = strval($message['eventkey']);
611             return $this->analyzeClick($message);
612         }
613         if (in_array($message['event'], array('pic_photo_or_album', 'pic_weixin', 'pic_sysphoto'))) {
614             pdo_delete('menu_event', array('createtime <' => $GLOBALS['_W']['timestamp'] - 100, 'openid' => $message['from']), 'OR');
615             if (!empty($message['sendpicsinfo']['count'])) {
616                 foreach ($message['sendpicsinfo']['piclist'] as $item) {
617                     pdo_insert('menu_event', array(
618                         'uniacid' => $GLOBALS['_W']['uniacid'],
619                         'keyword' => $message['eventkey'],
620                         'type' => $message['event'],
621                         'picmd5' => $item,
622                         'openid' => $message['from'],
623                         'createtime' => TIMESTAMP,
624                     ));
625                 }
626             } else {
627                 pdo_insert('menu_event', array(
628                     'uniacid' => $GLOBALS['_W']['uniacid'],
629                     'keyword' => $message['eventkey'],
630                     'type' => $message['event'],
631                     'picmd5' => $item,
632                     'openid' => $message['from'],
633                     'createtime' => TIMESTAMP,
634                 ));
635             }
636             $message['content'] = strval($message['eventkey']);
637             $message['source'] = $message['event'];
638             return $this->analyzeText($message);
639         }
640         if (!empty($message['eventkey'])) {
641             $message['content'] = strval($message['eventkey']);
642             $message['type'] = 'text';
643             $message['redirection'] = true;
644             $message['source'] = $message['event'];
645             return $this->analyzeText($message);
646         }
647         return $this->handler($message['event']);
648     }
649
650     private function analyzeClick(&$message) {
651         if(!empty($message['content']) || $message['content'] !== '') {
652             $message['type'] = 'text';
653             $message['redirection'] = true;
654             $message['source'] = 'click';
655             return $this->analyzeText($message);
656         }
657
658         return array();
659     }
660
661     private function analyzeImage(&$message) {
662         load()->func('communication');
663         if (!empty($message['picurl'])) {
664             $response = ihttp_get($message['picurl']);
665             if (!empty($response)) {
666                 $md5 = md5($response['content']);
667                 $event = pdo_get('menu_event', array('picmd5' => $md5), array('keyword', 'type'));
668                 if (!empty($event['keyword'])) {
669                     pdo_delete('menu_event', array('picmd5' => $md5));
670                 } else {
671                     $event = pdo_get('menu_event', array('openid' => $message['from']), array('keyword', 'type'));
672                 }
673                 if (!empty($event)) {
674                     $message['content'] = $event['keyword'];
675                     $message['eventkey'] = $event['keyword'];
676                     $message['type'] = 'text';
677                     $message['event'] = $event['type'];
678                     $message['redirection'] = true;
679                     $message['source'] = $event['type'];
680                     return $this->analyzeText($message);
681                 }
682             }
683             return $this->handler('image');
684         }
685     }
686
687     private function analyzeVoice(&$message) {
688         $params = $this->handler('voice');
689         if (empty($params) && !empty($message['recognition'])) {
690             $message['type'] = 'text';
691             $message['redirection'] = true;
692             $message['source'] = 'voice';
693             $message['content'] = $message['recognition'];
694             return $this->analyzeText($message);
695         } else {
696             return $params;
697         }
698     }
699
700     
701     private function handler($type) {
702         if(empty($type)) {
703             return array();
704         }
705         global $_W;
706         $params = array();
707         $setting = uni_setting($_W['uniacid'], array('default_message'));
708         $default_message = $setting['default_message'];
709         if(is_array($default_message) && !empty($default_message[$type]['type'])) {
710             if ($default_message[$type]['type'] == 'keyword') {
711                 $message = $this->message;
712                 $message['type'] = 'text';
713                 $message['redirection'] = true;
714                 $message['source'] = $type;
715                 $message['content'] = $default_message[$type]['keyword'];
716                 return $this->analyzeText($message);
717             } else {
718                 $params[] = array(
719                     'message' => $this->message,
720                     'module' => is_array($default_message[$type]) ? $default_message[$type]['module'] : $default_message[$type],
721                     'rule' => '-1',
722                 );
723                 return $params;
724             }
725         }
726         return array();
727     }
728
729     
730     private function process($param) {
731         global $_W;
732         if(empty($param['module']) || !in_array($param['module'], $this->modules)) {
733             return false;
734         }
735         if ($param['module'] == 'reply') {
736             $processor = WeUtility::createModuleProcessor('core');
737         } else {
738             $processor = WeUtility::createModuleProcessor($param['module']);
739         }
740         $processor->message = $param['message'];
741         $processor->rule = $param['rule'];
742         $processor->reply_type = $param['reply_type'];
743         $processor->priority = intval($param['priority']);
744         $processor->inContext = $param['context'] === true;
745         $response = $processor->respond();
746         if(empty($response)) {
747             return false;
748         }
749
750         return $response;
751     }
752
753     
754     public function died($content = '') {
755         global $_W, $engine;
756         if (empty($content)) {
757             exit('');
758         }
759         $response['FromUserName'] = $engine->message['to'];
760         $response['ToUserName'] = $engine->message['from'];
761         $response['MsgType'] = 'text';
762         $response['Content'] = htmlspecialchars_decode($content);
763         $response['CreateTime'] = TIMESTAMP;
764         $response['FuncFlag'] = 0;
765         $xml = array2xml($response);
766         if(!empty($_GET['encrypt_type']) && $_GET['encrypt_type'] == 'aes') {
767             $resp = $engine->account->encryptMsg($xml);
768             $resp = $engine->account->xmlDetract($resp);
769         } else {
770             $resp = $xml;
771         }
772         exit($resp);
773     }
774 }
775
776