mobile.class.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: mobile.class.php 36332 2016-12-30 01:44:19Z nemohou $
  7. */
  8. define("MOBILE_PLUGIN_VERSION", "4");
  9. define("REQUEST_METHOD_DOMAIN", 'http://wsq.discuz.com');
  10. class mobile_core {
  11. public static function result($result) {
  12. global $_G;
  13. ob_end_clean();
  14. function_exists('ob_gzhandler') ? ob_start('ob_gzhandler') : ob_start();
  15. header("Content-type: application/json");
  16. mobile_core::make_cors($_SERVER['REQUEST_METHOD'], REQUEST_METHOD_DOMAIN);
  17. $result = mobile_core::json(mobile_core::format($result));
  18. if(defined('FORMHASH')) {
  19. echo empty($_GET['jsoncallback_'.FORMHASH]) ? $result : $_GET['jsoncallback_'.FORMHASH].'('.$result.')';
  20. } else {
  21. echo $result;
  22. }
  23. exit;
  24. }
  25. public static function format($result) {
  26. switch (gettype($result)) {
  27. case 'array':
  28. foreach($result as $_k => $_v) {
  29. $result[$_k] = mobile_core::format($_v);
  30. }
  31. break;
  32. case 'boolean':
  33. case 'integer':
  34. case 'double':
  35. case 'float':
  36. $result = (string)$result;
  37. break;
  38. }
  39. return $result;
  40. }
  41. public static function json($encode) {
  42. if(!empty($_GET['debug']) && defined('DISCUZ_DEBUG') && DISCUZ_DEBUG) {
  43. return debug($encode);
  44. }
  45. require_once 'source/plugin/mobile/json.class.php';
  46. return CJSON::encode($encode);
  47. }
  48. public static function getvalues($variables, $keys, $subkeys = array()) {
  49. $return = array();
  50. foreach($variables as $key => $value) {
  51. foreach($keys as $k) {
  52. if($k{0} == '/' && preg_match($k, $key) || $key == $k) {
  53. if($subkeys) {
  54. $return[$key] = mobile_core::getvalues($value, $subkeys);
  55. } else {
  56. if(!empty($value) || !empty($_GET['debug']) || (is_numeric($value) && intval($value) === 0 )) {
  57. $return[$key] = is_array($value) ? mobile_core::arraystring($value) : (string)$value;
  58. }
  59. }
  60. }
  61. }
  62. }
  63. return $return;
  64. }
  65. static function arraystring($array) {
  66. foreach($array as $k => $v) {
  67. $array[$k] = is_array($v) ? mobile_core::arraystring($v) : (string)$v;
  68. }
  69. return $array;
  70. }
  71. static function variable($variables = array()) {
  72. global $_G;
  73. if(in_array('mobileoem', $_G['setting']['plugins']['available'])) {
  74. $check = C::t('#mobileoem#mobileoem_member')->fetch($_G['uid']);
  75. }
  76. $globals = array(
  77. 'cookiepre' => $_G['config']['cookie']['cookiepre'],
  78. 'auth' => $_G['cookie']['auth'],
  79. 'saltkey' => $_G['cookie']['saltkey'],
  80. 'member_uid' => $_G['member']['uid'],
  81. 'member_username' => $_G['member']['username'],
  82. 'member_avatar' => avatar($_G['member']['uid'], 'small', true),
  83. 'groupid' => $_G['groupid'],
  84. 'formhash' => FORMHASH,
  85. 'ismoderator' => $_G['forum']['ismoderator'],
  86. 'readaccess' => $_G['group']['readaccess'],
  87. 'notice' => array(
  88. 'newpush' => $check['newpush'] ? 1 : 0,
  89. 'newpm' => dintval($_G['member']['newpm']),
  90. 'newprompt' => dintval(($_G['member']['newprompt'] - $_G['member']['category_num']['mypost']) >= 0 ? ($_G['member']['newprompt'] - $_G['member']['category_num']['mypost']) : 0),
  91. 'newmypost' => dintval($_G['member']['category_num']['mypost']),
  92. )
  93. );
  94. if(!empty($_GET['submodule']) == 'checkpost') {
  95. $apifile = 'source/plugin/mobile/api/'.$_GET['version'].'/sub_checkpost.php';
  96. if(file_exists($apifile)) {
  97. require_once $apifile;
  98. $globals = $globals + mobile_api_sub::getvariable();
  99. }
  100. }
  101. $pluginvariables = array();
  102. if(!empty($_G['setting']['mobileapihook'])) {
  103. $mobileapihook = unserialize($_G['setting']['mobileapihook']);
  104. if(!empty($mobileapihook[$_GET['module']])) {
  105. if(!empty($mobileapihook[$_GET['module']]['variables'])) {
  106. mobile_core::activeHook($_GET['module'], $mobileapihook, $variables, true);
  107. unset($mobileapihook[$_GET['module']]['variables']);
  108. }
  109. if(!empty($mobileapihook[$_GET['module']])) {
  110. $param = array();
  111. $pluginvariables = mobile_core::activeHook($_GET['module'], $mobileapihook, $param);
  112. }
  113. }
  114. }
  115. $xml = array(
  116. 'Version' => $_GET['version'],
  117. 'Charset' => strtoupper($_G['charset']),
  118. 'Variables' => array_merge($globals, $variables),
  119. );
  120. if($pluginvariables) {
  121. $xml['pluginVariables'] = $pluginvariables;
  122. }
  123. if(!empty($_G['messageparam'])) {
  124. $message_result = lang('plugin/mobile', $_G['messageparam'][0], $_G['messageparam'][2]);
  125. if($message_result == $_G['messageparam'][0]) {
  126. $vars = explode(':', $_G['messageparam'][0]);
  127. if (count($vars) == 2) {
  128. $message_result = lang('plugin/' . $vars[0], $vars[1], $_G['messageparam'][2]);
  129. $_G['messageparam'][0] = $vars[1];
  130. } else {
  131. $message_result = lang('message', $_G['messageparam'][0], $_G['messageparam'][2]);
  132. }
  133. }
  134. $message_result = strip_tags($message_result);
  135. if(defined('IS_WEBVIEW') && IS_WEBVIEW && in_array('mobileoem', $_G['setting']['plugins']['available'])) {
  136. include_once DISCUZ_ROOT.'./source/plugin/mobileoem/discuzcode.func.php';
  137. include mobileoem_template('common/showmessage');
  138. if(!empty($_GET['debug'])) {
  139. exit;
  140. }
  141. $content = ob_get_contents();
  142. ob_end_clean();
  143. $xml['Variables']['datatype'] = -1;
  144. $xml['Variables']['webview_page'] = $content;
  145. return $xml;
  146. }
  147. if($_G['messageparam'][4]) {
  148. $_G['messageparam'][0] = "custom";
  149. }
  150. if ($_G['messageparam'][3]['login'] && !$_G['uid']) {
  151. $_G['messageparam'][0] .= '//' . $_G['messageparam'][3]['login'];
  152. }
  153. $xml['Message'] = array("messageval" => $_G['messageparam'][0], "messagestr" => $message_result);
  154. if($_GET['mobilemessage']) {
  155. $return = mobile_core::json($xml);
  156. header("HTTP/1.1 301 Moved Permanently");
  157. header("Location:discuz://" . rawurlencode($_G['messageparam'][0]) . "//" . rawurlencode(diconv($message_result, $_G['charset'], "utf-8")) . ($return ? "//" . rawurlencode($return) : '' ));
  158. exit;
  159. }
  160. }
  161. return $xml;
  162. }
  163. public static function diconv_array($variables, $in_charset, $out_charset) {
  164. foreach($variables as $_k => $_v) {
  165. if(is_array($_v)) {
  166. $variables[$_k] = mobile_core::diconv_array($_v, $in_charset, $out_charset);
  167. } elseif(is_string($_v)) {
  168. $variables[$_k] = diconv($_v, $in_charset, $out_charset);
  169. }
  170. }
  171. return $variables;
  172. }
  173. public static function make_cors($request_method, $origin = '') {
  174. $origin = $origin ? $origin : REQUEST_METHOD_DOMAIN;
  175. if ($request_method === 'OPTIONS') {
  176. header('Access-Control-Allow-Origin:'.$origin);
  177. header('Access-Control-Allow-Credentials:true');
  178. header('Access-Control-Allow-Methods:GET, POST, OPTIONS');
  179. header('Access-Control-Max-Age:1728000');
  180. header('Content-Type:text/plain charset=UTF-8');
  181. header("status: 204");
  182. header('HTTP/1.0 204 No Content');
  183. header('Content-Length: 0',true);
  184. flush();
  185. }
  186. if ($request_method === 'POST') {
  187. header('Access-Control-Allow-Origin:'.$origin);
  188. header('Access-Control-Allow-Credentials:true');
  189. header('Access-Control-Allow-Methods:GET, POST, OPTIONS');
  190. }
  191. if ($request_method === 'GET') {
  192. header('Access-Control-Allow-Origin:'.$origin);
  193. header('Access-Control-Allow-Credentials:true');
  194. header('Access-Control-Allow-Methods:GET, POST, OPTIONS');
  195. }
  196. }
  197. public static function usergroupIconId($groupid) {
  198. global $_G;
  199. if($_G['cache']['usergroupIconId']) {
  200. return $_G['cache']['usergroupIconId']['variable'][$groupid];
  201. }
  202. loadcache('usergroupIconId');
  203. if(!$_G['cache']['usergroupIconId'] || TIMESTAMP - $_G['cache']['usergroupIconId']['expiration'] > 3600) {
  204. loadcache('usergroups');
  205. $memberi = 0;
  206. $return = array();
  207. foreach($_G['cache']['usergroups'] as $groupid => $data) {
  208. if($data['type'] == 'member') {
  209. if(!$memberi && $groupid == $_G['setting']['newusergroupid']) {
  210. $memberi = 1;
  211. }
  212. if($memberi > 0) {
  213. $return[$groupid] = $memberi++;
  214. }
  215. } elseif($data['type'] == 'system' && $groupid < 4) {
  216. $return[$groupid] = 'admin';
  217. } elseif($data['type'] == 'special') {
  218. $return[$groupid] = 'special';
  219. }
  220. }
  221. savecache('usergroupIconId', array('variable' => $return, 'expiration' => TIMESTAMP));
  222. return $return[$groupid];
  223. } else {
  224. return $_G['cache']['usergroupIconId']['variable'][$groupid];
  225. }
  226. }
  227. public static function activeHook($module, $mobileapihook, &$param, $isavariables = false) {
  228. global $_G;
  229. if($isavariables) {
  230. $mobileapihook[$module] = array(
  231. 'variables' => $mobileapihook[$module]['variables']
  232. );
  233. }
  234. foreach($mobileapihook[$module] as $hookname => $hooks) {
  235. foreach($hooks as $plugin => $hook) {
  236. if(!$hook['allow'] || !in_array($plugin, $_G['setting']['plugins']['available'])) {
  237. continue;
  238. }
  239. if(!preg_match('/^[\w\_\.]+\.php$/i', $hook['include'])) {
  240. continue;
  241. }
  242. include_once DISCUZ_ROOT . 'source/plugin/' . $plugin . '/' . $hook['include'];
  243. if(!class_exists($hook['class'], false)) {
  244. continue;
  245. }
  246. if(!isset($pluginclasses[$hook['class']])) {
  247. $pluginclasses[$hook['class']] = new $hook['class'];
  248. }
  249. if(!method_exists($pluginclasses[$hook['class']], $hook['method'])) {
  250. continue;
  251. }
  252. if(!$isavariables) {
  253. $value[$module.'_'.$hookname][$plugin] = call_user_func(array($pluginclasses[$hook['class']], $hook['method']), $param);
  254. } else {
  255. call_user_func(array($pluginclasses[$hook['class']], $hook['method']), $param);
  256. }
  257. }
  258. }
  259. if(!$isavariables) {
  260. return $value;
  261. }
  262. }
  263. }
  264. class base_plugin_mobile {
  265. function common() {
  266. global $_G;
  267. if(!defined('IN_MOBILE_API')) {
  268. return;
  269. }
  270. if(!$_G['setting']['mobile']['allowmobile']) {
  271. mobile_core::result(array('error' => 'mobile_is_closed'));
  272. }
  273. if(!empty($_GET['tpp'])) {
  274. $_G['tpp'] = intval($_GET['tpp']);
  275. }
  276. if(!empty($_GET['ppp'])) {
  277. $_G['ppp'] = intval($_GET['ppp']);
  278. }
  279. $_G['pluginrunlist'] = array('mobile', 'qqconnect', 'wechat');
  280. $_G['siteurl'] = preg_replace('/api\/mobile\/$/', '', $_G['siteurl']);
  281. $_G['setting']['msgforward'] = '';
  282. $_G['setting']['cacheindexlife'] = $_G['setting']['cachethreadlife'] = false;
  283. if(!$_G['setting']['mobile']['nomobileurl'] && function_exists('diconv') && !empty($_GET['charset'])) {
  284. $_GET = mobile_core::diconv_array($_GET, $_GET['charset'], $_G['charset']);
  285. }
  286. if($_GET['_auth']) {
  287. require_once DISCUZ_ROOT.'./source/plugin/wechat/wsq.class.php';
  288. $uid = wsq::decodeauth($_GET['_auth']);
  289. $disablesec = false;
  290. if($uid) {
  291. require_once libfile('function/member');
  292. $member = getuserbyuid($uid, 1);
  293. if($_GET['module'] != 'login') {
  294. setloginstatus($member, 1296000);
  295. $disablesec = true;
  296. } else {
  297. $disablesec = logincheck($member['username']);
  298. }
  299. } elseif($_GET['module'] == 'login') {
  300. $disablesec = logincheck($_GET['username']);
  301. }
  302. if($disablesec) {
  303. $_G['setting']['seccodedata'] = array();
  304. $_G['setting']['seccodestatus'] = 0;
  305. $_G['setting']['secqaa'] = array();
  306. unset($_GET['force']);
  307. define('IN_MOBILE_AUTH', $uid);
  308. if($_SERVER['REQUEST_METHOD'] == 'POST') {
  309. $_GET['formhash'] = $_G['formhash'];
  310. }
  311. }
  312. }
  313. if(class_exists('mobile_api', false) && method_exists('mobile_api', 'common')) {
  314. mobile_api::common();
  315. }
  316. }
  317. function discuzcode($param) {
  318. if(!defined('IN_MOBILE_API') || $param['caller'] != 'discuzcode') {
  319. return;
  320. }
  321. global $_G;
  322. if(defined('IS_WEBVIEW') && IS_WEBVIEW && in_array('mobileoem', $_G['setting']['plugins']['available'])) {
  323. include_once DISCUZ_ROOT.'./source/plugin/mobileoem/discuzcode.func.php';
  324. include_once mobileoem_template('forum/discuzcode');
  325. $_G['discuzcodemessage'] = mobileoem_discuzcode($param['param']);
  326. } elseif($_GET['version'] == 4) {
  327. include_once 'discuzcode.func.php';
  328. $_G['discuzcodemessage'] = mobile_discuzcode($param['param']);
  329. } else {
  330. $_G['discuzcodemessage'] = preg_replace(array(
  331. "/\[size=(\d{1,2}?)\]/i",
  332. "/\[size=(\d{1,2}(\.\d{1,2}+)?(px|pt)+?)\]/i",
  333. "/\[\/size]/i",
  334. ), '', $_G['discuzcodemessage']);
  335. }
  336. if(in_array('soso_smilies', $_G['setting']['plugins']['available'])) {
  337. $sosoclass = DISCUZ_ROOT.'./source/plugin/soso_smilies/soso.class.php';
  338. if(file_exists($sosoclass)) {
  339. include_once $sosoclass;
  340. $soso_class = new plugin_soso_smilies;
  341. $soso_class->discuzcode($param);
  342. }
  343. }
  344. }
  345. function global_mobile() {
  346. if(!defined('IN_MOBILE_API')) {
  347. return;
  348. }
  349. if(class_exists('mobile_api', false) && method_exists('mobile_api', 'output')) {
  350. mobile_api::output();
  351. }
  352. }
  353. }
  354. class base_plugin_mobile_forum extends base_plugin_mobile {
  355. function post_mobile_message($param) {
  356. if(!defined('IN_MOBILE_API')) {
  357. return;
  358. }
  359. if(class_exists('mobile_api', false) && method_exists('mobile_api', 'post_mobile_message')) {
  360. list($message, $url_forward, $values, $extraparam, $custom) = $param['param'];
  361. mobile_api::post_mobile_message($message, $url_forward, $values, $extraparam, $custom);
  362. }
  363. }
  364. function misc_mobile_message($param) {
  365. if(!defined('IN_MOBILE_API')) {
  366. return;
  367. }
  368. if(class_exists('mobile_api', false) && method_exists('mobile_api', 'misc_mobile_message')) {
  369. list($message, $url_forward, $values, $extraparam, $custom) = $param['param'];
  370. mobile_api::misc_mobile_message($message, $url_forward, $values, $extraparam, $custom);
  371. }
  372. }
  373. function viewthread_postbottom_output() {
  374. global $_G, $postlist;
  375. foreach($postlist as $k => $post) {
  376. if($post['mobiletype'] == 1) {
  377. $post['message'] .= lang('plugin/mobile', 'mobile_fromtype_ios');
  378. } elseif($post['mobiletype'] == 2) {
  379. $post['message'] .= lang('plugin/mobile', 'mobile_fromtype_android');
  380. } elseif($post['mobiletype'] == 3) {
  381. $post['message'] .= lang('plugin/mobile', 'mobile_fromtype_windowsphone');
  382. } elseif($post['mobiletype'] == 5) {
  383. $threadmessage = $_G['setting']['wechatviewpluginid'] ? lang('plugin/'.$_G['setting']['wechatviewpluginid'], 'lang_wechat_threadmessage', array('tid' => $_G['tid'], 'pid' => $post['pid'])) : array();
  384. $post['message'] .= $threadmessage ? $threadmessage : '';
  385. }
  386. $postlist[$k] = $post;
  387. }
  388. return array();
  389. }
  390. }
  391. class base_plugin_mobile_misc extends base_plugin_mobile {
  392. function mobile() {
  393. global $_G;
  394. if(empty($_GET['view']) && !defined('MOBILE_API_OUTPUT')) {
  395. if(in_array('mobileoem', $_G['setting']['plugins']['available'])) {
  396. loadcache('mobileoem_data');
  397. }
  398. $_G['setting']['pluginhooks'] = array();
  399. $qrfile = DISCUZ_ROOT.'./data/cache/mobile_siteqrcode.png';
  400. if(!file_exists($qrfile) || $_G['adminid'] == 1) {
  401. require_once DISCUZ_ROOT.'source/plugin/mobile/qrcode.class.php';
  402. QRcode::png($_G['siteurl'], $qrfile);
  403. }
  404. define('MOBILE_API_OUTPUT', 1);
  405. $_G['disabledwidthauto'] = 1;
  406. define('TPL_DEFAULT', true);
  407. include template('mobile:mobile');
  408. exit;
  409. }
  410. }
  411. }
  412. class plugin_mobile extends base_plugin_mobile {}
  413. class plugin_mobile_forum extends base_plugin_mobile_forum {
  414. function post_mobile_message($param) {
  415. parent::post_mobile_message($param);
  416. list($message) = $param['param'];
  417. if(in_array($message, array('post_reply_succeed', 'post_reply_mod_succeed'))) {
  418. include_once 'source/plugin/mobile/api/4/sub_sendreply.php';
  419. }
  420. }
  421. }
  422. class plugin_mobile_misc extends base_plugin_mobile_misc {}
  423. class mobileplugin_mobile extends base_plugin_mobile {
  424. function global_header_mobile() {
  425. global $_G;
  426. if(in_array('mobileoem', $_G['setting']['plugins']['available'])) {
  427. loadcache('mobileoem_data');
  428. if($_G['cache']['mobileoem_data']['iframeUrl']) {
  429. return;
  430. }
  431. }
  432. if(IN_MOBILE === '1' || IN_MOBILE === 'yes' || IN_MOBILE === true) {
  433. return;
  434. }
  435. }
  436. }
  437. class mobileplugin_mobile_forum extends base_plugin_mobile_forum {
  438. function post_mobile_message($param) {
  439. parent::post_mobile_message($param);
  440. list($message) = $param['param'];
  441. if(in_array($message, array('post_reply_succeed', 'post_reply_mod_succeed'))) {
  442. include_once 'source/plugin/mobile/api/4/sub_sendreply.php';
  443. }
  444. }
  445. }
  446. class mobileplugin_mobile_misc extends base_plugin_mobile_misc {}
  447. class plugin_mobile_connect extends plugin_mobile {
  448. function login_mobile_message($param) {
  449. global $_G;
  450. if(substr($_GET['referer'], 0, 7) == 'Mobile_') {
  451. if($_GET['referer'] == 'Mobile_iOS' || $_GET['referer'] == 'Mobile_Android') {
  452. $_GET['mobilemessage'] = 1;
  453. }
  454. $param = array('con_auth_hash' => $_G['cookie']['con_auth_hash']);
  455. mobile_core::result(mobile_core::variable($param));
  456. }
  457. }
  458. }
  459. ?>