PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/rock.php

http://github.com/iwind/rockmongo
PHP | 733 lines | 457 code | 56 blank | 220 comment | 94 complexity | 832858fb193439159a667341359d9299 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. define("DS", DIRECTORY_SEPARATOR);
  3. define("__ROOT__", dirname(__FILE__) . DS . "app");
  4. define("__VERSION__", "0.0.1");
  5. define("nil", "nil_" . uniqid(microtime(true)));
  6. if (!defined("__ENV__")) {
  7. define("__ENV__", "dev");
  8. }
  9. if (!defined("__PLATFORM__")) {
  10. define("__PLATFORM__", "def");
  11. }
  12. if (!isset($_SERVER["PHP_SELF"]) && isset($_SERVER["SCRIPT_NAME"])) {
  13. $_SERVER["PHP_SELF"] = $_SERVER["SCRIPT_NAME"];
  14. }
  15. //merge $_POST and $_GET
  16. $GLOBALS["ROCK_USER_VARS"] = array();
  17. $GLOBALS["ROCK_HTTP_VARS"] = array_merge($_GET, $_POST);
  18. /**
  19. * Application class
  20. *
  21. */
  22. class Rock {
  23. private static $_controller;
  24. /**
  25. * Start application
  26. *
  27. */
  28. public static function start() {
  29. $path = x("action");
  30. if (!$path) {
  31. $path = "index.index";
  32. }
  33. if (!strstr($path, ".")) {
  34. $path .= ".index";
  35. }
  36. if (!preg_match("/(^.*(?:^|\\.))(\\w+)\\.(\\w+)$/", $path, $match)) {
  37. trigger_error("you called an invalid action");
  38. }
  39. $name = $match[1] . $match[2];
  40. define("__CONTROLLER__", $name);
  41. $controller = $match[2];
  42. $action = $match[3];
  43. $mainRoot = null;
  44. $isInPlugin = false;
  45. if (substr($name, 0, 1) == "@") {
  46. $isInPlugin = true;
  47. $mainRoot = __ROOT__ . DS . "plugins" . DS . substr($name, 1, strpos($name, ".") - 1);
  48. if (!is_dir($mainRoot)) {
  49. $mainRoot = dirname(dirname(__ROOT__)) . DS . "plugins" . DS . substr($name, 1, strpos($name, ".") - 1);
  50. }
  51. $name = substr($name, strpos($name, ".") + 1);
  52. }
  53. else {
  54. $isInPlugin = false;
  55. $mainRoot = __ROOT__;
  56. }
  57. $dir = str_replace(".", DS, $name);
  58. $file = $mainRoot . DS . "controllers" . DS . $dir . ".php";
  59. if (!is_file($file)) {
  60. trigger_error("file '{$file}' of controller '{$controller}' is not found", E_USER_ERROR);
  61. }
  62. require($file);
  63. $class = ucfirst(rock_name_to_java($controller)) . "Controller";
  64. if (!class_exists($class, false)) {
  65. $file = realpath($file);
  66. trigger_error("class '{$class}' is not found in controller file '{$file}'", E_USER_ERROR);
  67. }
  68. $obj = new $class;
  69. if (!($obj instanceof RController)) {
  70. trigger_error("controller class '{$class}' must be a subclass of RController", E_USER_ERROR);
  71. }
  72. define("__ACTION__", $action);
  73. $obj->setRoot($mainRoot);
  74. $obj->setAction($action);
  75. $obj->setPath($file);
  76. $obj->setName($name);
  77. $obj->setInPlugin($isInPlugin);
  78. $obj->exec();
  79. }
  80. public static function setController($controller) {
  81. self::$_controller = $controller;
  82. }
  83. /**
  84. * get current running controller object
  85. *
  86. * @return RController
  87. */
  88. public static function controller() {
  89. return self::$_controller;
  90. }
  91. }
  92. /**
  93. * Controller parent class
  94. *
  95. */
  96. class RController {
  97. private $_action;
  98. private $_path;
  99. private $_name;
  100. private $_inPlugin = false;
  101. /**
  102. * set current action name
  103. *
  104. * @param string $action action name
  105. */
  106. public function setAction($action) {
  107. $this->_action = $action;
  108. }
  109. /**
  110. * Get action name
  111. *
  112. * @return string
  113. */
  114. public function action() {
  115. return $this->_action;
  116. }
  117. public function setRoot($root) {
  118. $this->_root = $root;
  119. }
  120. public function root() {
  121. return $this->_root;
  122. }
  123. /**
  124. * Set controller file path
  125. *
  126. * @param string $path file path
  127. */
  128. public function setPath($path) {
  129. $this->_path = $path;
  130. }
  131. /**
  132. * Set controller name
  133. *
  134. * @param string $name controller name
  135. */
  136. public function setName($name) {
  137. $this->_name = $name;
  138. }
  139. /**
  140. * Get controller name
  141. *
  142. * @return string
  143. */
  144. public function name() {
  145. return $this->_name;
  146. }
  147. /**
  148. * Set if the controller is in a plugin
  149. *
  150. * @param boolean $isInPlugin true or false
  151. */
  152. public function setInPlugin($isInPlugin) {
  153. $this->_inPlugin = $isInPlugin;
  154. }
  155. /**
  156. * Call before actions
  157. *
  158. */
  159. public function onBefore() {
  160. }
  161. /**
  162. * Call after actions
  163. *
  164. */
  165. public function onAfter() {
  166. }
  167. /**
  168. * Execute action
  169. *
  170. */
  171. public function exec() {
  172. Rock::setController($this);
  173. if (class_exists("RPlugin")) {
  174. RPlugin::callBefore();
  175. }
  176. $this->onBefore();
  177. $method = "do" . $this->_action;
  178. if (!method_exists($this, $method)) {
  179. trigger_error("can not find action '{$this->_action}' in class '" . get_class($this) . "'", E_USER_ERROR);
  180. }
  181. $ret = $this->$method();
  182. if (is_object($ret) && ($ret instanceof RView)) {
  183. $ret->display();
  184. }
  185. $this->onAfter();
  186. if (class_exists("RPlugin")) {
  187. RPlugin::callAfter();
  188. }
  189. }
  190. /**
  191. * Display View
  192. *
  193. * @param string $action action name, if not NULL, find view with this name
  194. */
  195. public function display($action = null) {
  196. if (is_null($action)) {
  197. $action = $this->_action;
  198. }
  199. $view = null;
  200. if ($this->_inPlugin) {
  201. $view = dirname(dirname($this->_path)) . "/views/" . str_replace(".", "/", $this->_name) . "/{$action}.php";
  202. }
  203. else {
  204. $view = dirname(__ROOT__) . DS . rock_theme_path() . "/views/" . str_replace(".", "/", $this->_name) . "/{$action}.php";
  205. }
  206. if (is_file($view)) {
  207. extract(get_object_vars($this), EXTR_OVERWRITE);
  208. require($view);
  209. }
  210. }
  211. }
  212. /**
  213. * Model class
  214. *
  215. */
  216. class RModel {
  217. }
  218. /**
  219. * View class
  220. *
  221. */
  222. class RView {
  223. /**
  224. * Display view
  225. *
  226. */
  227. public function display() {
  228. }
  229. }
  230. /**
  231. * print data to screen
  232. *
  233. * @param mixed $data1 data to be printed
  234. */
  235. function p($data1 = null) {
  236. $args = func_get_args();
  237. foreach ($args as $arg) {
  238. if (is_null($arg)) {
  239. $arg = "NULL";
  240. }
  241. else if (is_bool($arg)) {
  242. $arg = $arg ? "TRUE" : "FALSE";
  243. }
  244. echo "<xmp>\n" . print_r($arg, true) . "\n</xmp>\n";
  245. }
  246. }
  247. /**
  248. * get or set parameter value
  249. *
  250. * @param string|array $name a name or an array of values
  251. * @param mixed $value value to be set
  252. * @return mixed
  253. */
  254. function x($name, $value = nil) {
  255. if ($value != nil) {
  256. $GLOBALS["ROCK_USER_VARS"][$name] = $value;
  257. return $value;
  258. }
  259. if (array_key_exists($name, $GLOBALS["ROCK_USER_VARS"])) {
  260. return $GLOBALS["ROCK_USER_VARS"][$name];
  261. }
  262. if (array_key_exists($name, $GLOBALS["ROCK_HTTP_VARS"])) {
  263. return rock_filter_param($GLOBALS["ROCK_HTTP_VARS"][$name]);
  264. }
  265. return null;
  266. }
  267. /**
  268. * filter parameters
  269. *
  270. * @param string $param parameters to be filtered
  271. * @param boolean $filter will filter?
  272. * @return mixed
  273. */
  274. function rock_filter_param($param, $filter = true) {
  275. if (!is_array($param) && !is_object($param)) {
  276. if (ini_get("magic_quotes_gpc")) {
  277. $param = stripslashes($param);
  278. }
  279. return $filter ? htmlspecialchars(trim($param)) : $param;
  280. }
  281. foreach ($param as $key => $value) {
  282. $param[$key] = rock_filter_param($value, $filter);
  283. }
  284. return $param;
  285. }
  286. /**
  287. * get parameter value
  288. *
  289. * different from x($name), the value will not be filtered (trim or htmlspecialchars)
  290. *
  291. * @param string $name parameter name
  292. * @return mixed
  293. * @see x
  294. */
  295. function xn($name = nil) {
  296. if ($name == nil) {
  297. return array_merge(rock_filter_param($GLOBALS["ROCK_HTTP_VARS"], false), $GLOBALS["ROCK_USER_VARS"]);
  298. }
  299. if (array_key_exists($name, $GLOBALS["ROCK_USER_VARS"])) {
  300. return $GLOBALS["ROCK_USER_VARS"][$name];
  301. }
  302. if (array_key_exists($name, $GLOBALS["ROCK_HTTP_VARS"])) {
  303. return rock_filter_param($GLOBALS["ROCK_HTTP_VARS"][$name], false);
  304. }
  305. return null;
  306. }
  307. /**
  308. * get parameter value and convert it to integer value
  309. *
  310. * @param string $name parameter name
  311. * @return integer
  312. * @see x
  313. */
  314. function xi($name) {
  315. return intval(x($name));
  316. }
  317. /**
  318. * import a class file
  319. *
  320. * @param string $class full class name
  321. * @param boolean $isClass if file is class
  322. */
  323. function import($class, $isClass = true) {
  324. $className = substr($class, strrpos($class, ".") + 1);
  325. if ($isClass && class_exists($className, false)) {
  326. return $className;
  327. }
  328. $file = null;
  329. if (strstr($class, "@")) {
  330. $trace = debug_backtrace();
  331. $calledFile = $trace[0]["file"];
  332. $count = substr_count($class, "@");
  333. $dir = $calledFile;
  334. for ($i = 0; $i < $count; $i ++) {
  335. $dir = dirname($dir);
  336. }
  337. $file = $dir . "/" . str_replace(".", "/", str_replace("@.", "", $class)) . ".php";
  338. }
  339. else {
  340. $file = __ROOT__ . "/" . str_replace(".", "/", $class) . ".php";
  341. }
  342. if (empty($GLOBALS["ROCK_LOADED"]) || !in_array($file, $GLOBALS["ROCK_LOADED"])) {
  343. require($file);
  344. $GLOBALS["ROCK_LOADED"][] = $file;
  345. }
  346. return $className;
  347. }
  348. /**
  349. * get configuration value
  350. *
  351. * support __PLATFORM__
  352. *
  353. * o("config.name") - find in app/configs/config.php directory
  354. * o("@.config") - find config.php in current directory
  355. * o("@.config.servers") - find config.php in current directory
  356. *
  357. * @param string $config configuration key
  358. * @return mixed
  359. */
  360. function o($config) {
  361. if (isset($GLOBALS["ROCK_CONFIGS"][$config])) {
  362. return $GLOBALS["ROCK_CONFIGS"][$config];
  363. }
  364. $file = null;
  365. $option = null;
  366. $pieces = explode(".", $config);
  367. if (strstr($config, "@")) {
  368. $trace = debug_backtrace();
  369. $calledFile = $trace[0]["file"];
  370. $count = substr_count($config, "@");
  371. $dir = $calledFile;
  372. for ($i = 0; $i < $count; $i ++) {
  373. unset($pieces[$i]);
  374. $dir = dirname($dir);
  375. }
  376. $filename = array_shift($pieces);
  377. $file = $dir . "/" . $filename . "@" . __PLATFORM__ . ".php";
  378. }
  379. else {
  380. $filename = array_shift($pieces);
  381. $file = __ROOT__ . "/configs/" . $filename . "@" . __PLATFORM__ . ".php";
  382. }
  383. $options = $pieces;
  384. $ret = require($file);
  385. //有没有子选项
  386. if (empty($options)) {
  387. $GLOBALS["ROCK_CONFIGS"][$config] = $ret;
  388. return $ret;
  389. }
  390. if (!is_array($ret)) {
  391. $GLOBALS["ROCK_CONFIGS"][$config] = $ret;
  392. return null;
  393. }
  394. $ret = rock_array_get($ret, $options);
  395. $GLOBALS["ROCK_CONFIGS"][$config] = $ret;
  396. return $ret;
  397. }
  398. /**
  399. * convert name to java style
  400. *
  401. * Example:<br/>
  402. * load_xml_config --> loadXmlConfig
  403. *
  404. * @param string $name name to be converted
  405. * @return string
  406. */
  407. function rock_name_to_java($name) {
  408. $name = preg_replace_callback("/_([a-zA-Z])/", create_function('$match', 'return strtoupper($match[1]);'), $name);
  409. return $name;
  410. }
  411. /**
  412. * get value from array for one key
  413. *
  414. * @param array $array the array
  415. * @param array|string $keys key or keys, can be a.b.c
  416. * @return mixed
  417. * @see rock_array_set
  418. */
  419. function rock_array_get(array $array, $keys) {
  420. if (is_array($keys) && empty($keys)) {
  421. return $array;
  422. }
  423. if (!is_array($keys)) {
  424. if (strstr($keys, "`")) {
  425. $keys = preg_replace_callback("/`(.+)`/U", create_function ('$match', 'return str_replace(".", "\.", $match[1]);'), $keys);
  426. }
  427. $keys = preg_split("/(?<!\\\\)\\./", $keys);
  428. }
  429. if (count($keys) == 1) {
  430. $firstKey = array_pop($keys);
  431. $firstKey = str_replace("\\.", ".", $firstKey);
  432. return array_key_exists($firstKey, $array)?$array[$firstKey]:null;
  433. }
  434. $lastKey = array_pop($keys);
  435. $lastKey = str_replace("\\.", ".", $lastKey);
  436. $lastArray = $array;
  437. foreach ($keys as $key) {
  438. $key = str_replace("\\.", ".", $key);
  439. if (is_array($lastArray) && array_key_exists($key, $lastArray)) {
  440. $lastArray = $lastArray[$key];
  441. }
  442. else {
  443. return null;
  444. }
  445. }
  446. return (is_array($lastArray) && array_key_exists($lastKey, $lastArray))? $lastArray[$lastKey] : null;
  447. }
  448. /**
  449. * set an element's value in the array, and return a new array
  450. *
  451. * @param array $array array
  452. * @param array|string $keys key of the element, support dot operator (.), for example: a.b.c
  453. * @param mixed $value new value
  454. * @return array
  455. * @see rock_array_get
  456. */
  457. function rock_array_set(array $array, $keys, $value) {
  458. if (is_array($keys) && empty($keys)) {
  459. return $array;
  460. }
  461. if (!is_array($keys)) {
  462. if (strstr($keys, "`")) {
  463. $keys = preg_replace_callback("/`(.+)`/U", create_function ('$match', 'return str_replace(".", "\.", $match[1]);'), $keys);
  464. }
  465. $keys = preg_split("/(?<!\\\\)\\./", $keys);
  466. }
  467. if (count($keys) == 1) {
  468. $firstKey = array_pop($keys);
  469. $firstKey = str_replace("\\.", ".", $firstKey);
  470. $array[$firstKey] = $value;
  471. return $array;
  472. }
  473. $lastKey = array_pop($keys);
  474. $lastKey = str_replace("\\.", ".", $lastKey);
  475. $lastConfig = &$array;
  476. foreach ($keys as $key) {
  477. $key = str_replace("\\.", ".", $key);
  478. if (!isset($lastConfig[$key]) || !is_array($lastConfig[$key])) {
  479. $lastConfig[$key] = array();
  480. }
  481. $lastConfig = &$lastConfig[$key];
  482. }
  483. $lastConfig[$lastKey] = $value;
  484. return $array;
  485. }
  486. /**
  487. * pick values from an array, the make it as keys
  488. *
  489. * <code>
  490. * $array = array(
  491. * array("a" => 11, "b" => 12),
  492. * array("a" => 21, "b" => 22)
  493. * //...
  494. * );
  495. *
  496. * $array2 = rock_array_combine($array, "a", "b");
  497. * </code>
  498. *
  499. * then $array2 will be:
  500. * <code>
  501. * array(
  502. * 11 => 12,
  503. * 21 => 22
  504. * );
  505. * </code>
  506. *
  507. * if $valueName not be set, the element value be "value":
  508. *
  509. * <code>
  510. * $array2 = rock_array_combine($array, "a");
  511. *
  512. * array(
  513. * 11 => array("a" => 11, "b" => 12),
  514. * 21 => array("a" => 21, "b" => 22)
  515. * );
  516. * </code>
  517. *
  518. * support dot (.) operator in keyName and valueName:
  519. * - rock_array_combine($array, "a.b", "a.c");
  520. * $array[n][a][b] will be "key",$array[n][a][c] value be"value", here, n is index
  521. *
  522. * @param array $array array values to combine from
  523. * @param integer|string $keyName key name
  524. * @param integer|string $valueName value name
  525. * @return array
  526. * @since 1.0
  527. */
  528. function rock_array_combine($array, $keyName, $valueName = null) {
  529. $ret = array();
  530. foreach ($array as $row) {
  531. if (is_array($row)) {
  532. $keyValue = rock_array_get($row, $keyName);
  533. $value = is_null($valueName) ? $row : rock_array_get($row, $valueName);
  534. if ($keyValue) {
  535. $ret[$keyValue] = $value;
  536. }
  537. else {
  538. $ret[] = $value;
  539. }
  540. }
  541. }
  542. return $ret;
  543. }
  544. /**
  545. * Retrieve message from language file
  546. *
  547. * @param string $code message code
  548. * @return mixed
  549. */
  550. function rock_lang($code) {
  551. if (!isset($GLOBALS["ROCK_LANGS"])) {
  552. $file = __ROOT__ . "/langs/" . __LANG__ . "/message.php";
  553. $message = array();
  554. require($file);
  555. if (isset($message) && is_array($message)) {
  556. $GLOBALS["ROCK_LANGS"] = $message;
  557. }
  558. else {
  559. $GLOBALS["ROCK_LANGS"] = array();
  560. }
  561. }
  562. $ret = isset($GLOBALS["ROCK_LANGS"][$code]) ? $GLOBALS["ROCK_LANGS"][$code] : null;
  563. if (is_null($ret)) {
  564. require __ROOT__ . "/langs/en_us/message.php";
  565. if (isset($message[$code])) {
  566. $ret = $message[$code];
  567. }
  568. $GLOBALS["ROCK_LANGS"] = array_merge($message, $GLOBALS["ROCK_LANGS"]);
  569. }
  570. if (is_null($ret)) {
  571. $ret = $code;
  572. }
  573. $args = func_get_args();
  574. unset($args[0]);
  575. if (empty($args)) {
  576. return $ret;
  577. }
  578. return vsprintf($ret, $args);
  579. }
  580. /**
  581. * Check RockMongo version
  582. *
  583. */
  584. function rock_check_version() {
  585. global $MONGO;
  586. if (!isset($MONGO["servers"][0]["host"])) {
  587. return;
  588. }
  589. //version 1.0.x
  590. foreach ($MONGO["servers"] as $index => $server) {
  591. foreach($server as $param => $value) {
  592. switch ($param) {
  593. case "host":
  594. $server["mongo_host"] = $value;
  595. break;
  596. case "sock":
  597. $server["mongo_sock"] = $value;
  598. break;
  599. case "port":
  600. $server["mongo_port"] = $value;
  601. $server["mongo_name"] = $server["mongo_host"] . ":" . $server["mongo_port"];
  602. break;
  603. case "username":
  604. $server["mongo_user"] = $value;
  605. break;
  606. case "password":
  607. $server["mongo_pass"] = $value;
  608. break;
  609. case "auth_enabled":
  610. if (!$value) {
  611. $server["mongo_auth"] = false;
  612. $server["control_auth"] = false;
  613. }
  614. break;
  615. case "admins":
  616. foreach ($value as $name => $pass) {
  617. $server["control_users"][$name] = $pass;
  618. }
  619. break;
  620. case "show_dbs":
  621. $server["ui_only_dbs"] = $value;
  622. break;
  623. }
  624. }
  625. $MONGO["servers"][$index] = $server;
  626. }
  627. }
  628. /**
  629. * initialize language
  630. *
  631. */
  632. function rock_init_lang() {
  633. if (isset($_COOKIE["ROCK_LANG"])) {
  634. // Patched by synthomat
  635. // as reported in CVE-2013-5107
  636. if (preg_match("/^[a-z]{2}_[a-z]{2}$/", $_COOKIE["ROCK_LANG"])) {
  637. define("__LANG__", $_COOKIE["ROCK_LANG"]);
  638. } else {
  639. define("__LANG__", "en_us");
  640. }
  641. return;
  642. }
  643. if (isset($_SERVER["HTTP_ACCEPT_LANGUAGE"])) {
  644. $firstLang = "";
  645. if (strstr($_SERVER["HTTP_ACCEPT_LANGUAGE"], ",")) {
  646. list($firstLang) = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
  647. }
  648. else {
  649. $firstLang = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
  650. }
  651. if ($firstLang) {
  652. $firstLang = strtolower(str_replace("-", "_", $firstLang));
  653. if (is_dir(__ROOT__ . DS . "langs" . DS . $firstLang)) {
  654. define("__LANG__", $firstLang);
  655. return;
  656. }
  657. }
  658. }
  659. if (!defined("__LANG__")) {
  660. define("__LANG__", "en_us");
  661. }
  662. }
  663. /**
  664. * initialize plugins
  665. *
  666. */
  667. function rock_init_plugins() {
  668. global $MONGO;
  669. if (empty($MONGO["features"]["plugins"]) || strtolower($MONGO["features"]["plugins"]) != "on") {
  670. return;
  671. }
  672. import("lib.core.RPlugin");
  673. import("lib.core.REvent");
  674. import("lib.core.RFilter");
  675. RPlugin::load();
  676. }
  677. ?>