input.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <?php
  2. /**
  3. * Parameter input functions.
  4. * This file contains functions for getting input from get/post variables.
  5. *
  6. * @package Elgg.Core
  7. * @subpackage Input
  8. */
  9. /**
  10. * Get some input from variables passed submitted through GET or POST.
  11. *
  12. * If using any data obtained from get_input() in a web page, please be aware that
  13. * it is a possible vector for a reflected XSS attack. If you are expecting an
  14. * integer, cast it to an int. If it is a string, escape quotes.
  15. *
  16. * Note: this function does not handle nested arrays (ex: form input of param[m][n])
  17. * because of the filtering done in htmlawed from the filter_tags call.
  18. * @todo Is this ^ still true?
  19. *
  20. * @param string $variable The variable name we want.
  21. * @param mixed $default A default value for the variable if it is not found.
  22. * @param bool $filter_result If true, then the result is filtered for bad tags.
  23. *
  24. * @return mixed
  25. */
  26. function get_input($variable, $default = null, $filter_result = true) {
  27. return _elgg_services()->input->get($variable, $default, $filter_result);
  28. }
  29. /**
  30. * Sets an input value that may later be retrieved by get_input
  31. *
  32. * Note: this function does not handle nested arrays (ex: form input of param[m][n])
  33. *
  34. * @param string $variable The name of the variable
  35. * @param string|string[] $value The value of the variable
  36. *
  37. * @return void
  38. */
  39. function set_input($variable, $value) {
  40. _elgg_services()->input->set($variable, $value);
  41. }
  42. /**
  43. * Filter tags from a given string based on registered hooks.
  44. *
  45. * @param mixed $var Anything that does not include an object (strings, ints, arrays)
  46. * This includes multi-dimensional arrays.
  47. *
  48. * @return mixed The filtered result - everything will be strings
  49. */
  50. function filter_tags($var) {
  51. return elgg_trigger_plugin_hook('validate', 'input', null, $var);
  52. }
  53. /**
  54. * Returns the current page's complete URL.
  55. *
  56. * It uses the configured site URL for the hostname rather than depending on
  57. * what the server uses to populate $_SERVER.
  58. *
  59. * @return string The current page URL.
  60. */
  61. function current_page_url() {
  62. $url = parse_url(elgg_get_site_url());
  63. $page = $url['scheme'] . "://" . $url['host'];
  64. if (isset($url['port']) && $url['port']) {
  65. $page .= ":" . $url['port'];
  66. }
  67. $page = trim($page, "/");
  68. $page .= _elgg_services()->request->getRequestUri();
  69. return $page;
  70. }
  71. /**
  72. * Validates an email address.
  73. *
  74. * @param string $address Email address.
  75. *
  76. * @return bool
  77. */
  78. function is_email_address($address) {
  79. return filter_var($address, FILTER_VALIDATE_EMAIL) === $address;
  80. }
  81. /**
  82. * Load all the GET and POST variables into the sticky form cache
  83. *
  84. * Call this from an action when you want all your submitted variables
  85. * available if the submission fails validation and is sent back to the form
  86. *
  87. * @param string $form_name Name of the sticky form
  88. *
  89. * @return void
  90. * @since 1.8.0
  91. */
  92. function elgg_make_sticky_form($form_name) {
  93. _elgg_services()->stickyForms->makeStickyForm($form_name);
  94. }
  95. /**
  96. * Clear the sticky form cache
  97. *
  98. * Call this if validation is successful in the action handler or
  99. * when they sticky values have been used to repopulate the form
  100. * after a validation error.
  101. *
  102. * @param string $form_name Form namespace
  103. *
  104. * @return void
  105. * @since 1.8.0
  106. */
  107. function elgg_clear_sticky_form($form_name) {
  108. _elgg_services()->stickyForms->clearStickyForm($form_name);
  109. }
  110. /**
  111. * Has this form been made sticky?
  112. *
  113. * @param string $form_name Form namespace
  114. *
  115. * @return boolean
  116. * @since 1.8.0
  117. */
  118. function elgg_is_sticky_form($form_name) {
  119. return _elgg_services()->stickyForms->isStickyForm($form_name);
  120. }
  121. /**
  122. * Get a specific sticky variable
  123. *
  124. * @param string $form_name The name of the form
  125. * @param string $variable The name of the variable
  126. * @param mixed $default Default value if the variable does not exist in sticky cache
  127. * @param boolean $filter_result Filter for bad input if true
  128. *
  129. * @return mixed
  130. *
  131. * @todo should this filter the default value?
  132. * @since 1.8.0
  133. */
  134. function elgg_get_sticky_value($form_name, $variable = '', $default = null, $filter_result = true) {
  135. return _elgg_services()->stickyForms->getStickyValue($form_name, $variable, $default, $filter_result);
  136. }
  137. /**
  138. * Get all the values in a sticky form in an array
  139. *
  140. * @param string $form_name The name of the form
  141. * @param bool $filter_result Filter for bad input if true
  142. *
  143. * @return array
  144. * @since 1.8.0
  145. */
  146. function elgg_get_sticky_values($form_name, $filter_result = true) {
  147. return _elgg_services()->stickyForms->getStickyValues($form_name, $filter_result);
  148. }
  149. /**
  150. * Clear a specific sticky variable
  151. *
  152. * @param string $form_name The name of the form
  153. * @param string $variable The name of the variable to clear
  154. *
  155. * @return void
  156. * @since 1.8.0
  157. */
  158. function elgg_clear_sticky_value($form_name, $variable) {
  159. _elgg_services()->stickyForms->clearStickyValue($form_name, $variable);
  160. }
  161. /**
  162. * Page handler for autocomplete endpoint.
  163. *
  164. * @todo split this into functions/objects, this is way too big
  165. *
  166. * /livesearch?q=<query>
  167. *
  168. * Other options include:
  169. * match_on string all or array(groups|users|friends)
  170. * match_owner int 0/1
  171. * limit int default is 10
  172. * name string default "members"
  173. *
  174. * @param array $page
  175. * @return string JSON string is returned and then exit
  176. * @access private
  177. */
  178. function input_livesearch_page_handler($page) {
  179. $dbprefix = elgg_get_config('dbprefix');
  180. // only return results to logged in users.
  181. if (!$user = elgg_get_logged_in_user_entity()) {
  182. exit;
  183. }
  184. if (!$q = get_input('term', get_input('q'))) {
  185. exit;
  186. }
  187. $input_name = get_input('name', 'members');
  188. $q = sanitise_string($q);
  189. // replace mysql vars with escaped strings
  190. $q = str_replace(array('_', '%'), array('\_', '\%'), $q);
  191. $match_on = get_input('match_on', 'all');
  192. if (!is_array($match_on)) {
  193. $match_on = array($match_on);
  194. }
  195. // all = users and groups
  196. if (in_array('all', $match_on)) {
  197. $match_on = array('users', 'groups');
  198. }
  199. $owner_guid = ELGG_ENTITIES_ANY_VALUE;
  200. if (get_input('match_owner', false)) {
  201. $owner_guid = $user->getGUID();
  202. }
  203. $limit = sanitise_int(get_input('limit', elgg_get_config('default_limit')));
  204. // grab a list of entities and send them in json.
  205. $results = array();
  206. foreach ($match_on as $match_type) {
  207. switch ($match_type) {
  208. case 'users':
  209. $options = array(
  210. 'type' => 'user',
  211. 'limit' => $limit,
  212. 'joins' => array("JOIN {$dbprefix}users_entity ue ON e.guid = ue.guid"),
  213. 'wheres' => array(
  214. "ue.banned = 'no'",
  215. "(ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%')"
  216. )
  217. );
  218. $entities = elgg_get_entities($options);
  219. if (!empty($entities)) {
  220. foreach ($entities as $entity) {
  221. if (in_array('groups', $match_on)) {
  222. $value = $entity->guid;
  223. } else {
  224. $value = $entity->username;
  225. }
  226. $output = elgg_view_list_item($entity, array(
  227. 'use_hover' => false,
  228. 'use_link' => false,
  229. 'class' => 'elgg-autocomplete-item',
  230. 'title' => $entity->name, // Default title would be a link
  231. ));
  232. $icon = elgg_view_entity_icon($entity, 'tiny', array(
  233. 'use_hover' => false,
  234. ));
  235. $result = array(
  236. 'type' => 'user',
  237. 'name' => $entity->name,
  238. 'desc' => $entity->username,
  239. 'guid' => $entity->guid,
  240. 'label' => $output,
  241. 'value' => $value,
  242. 'icon' => $icon,
  243. 'url' => $entity->getURL(),
  244. 'html' => elgg_view('input/userpicker/item', array(
  245. 'entity' => $entity,
  246. 'input_name' => $input_name,
  247. )),
  248. );
  249. $results[$entity->name . rand(1, 100)] = $result;
  250. }
  251. }
  252. break;
  253. case 'groups':
  254. // don't return results if groups aren't enabled.
  255. if (!elgg_is_active_plugin('groups')) {
  256. continue;
  257. }
  258. $options = array(
  259. 'type' => 'group',
  260. 'limit' => $limit,
  261. 'owner_guid' => $owner_guid,
  262. 'joins' => array("JOIN {$dbprefix}groups_entity ge ON e.guid = ge.guid"),
  263. 'wheres' => array(
  264. "(ge.name LIKE '$q%' OR ge.name LIKE '% $q%' OR ge.description LIKE '% $q%')"
  265. )
  266. );
  267. $entities = elgg_get_entities($options);
  268. if (!empty($entities)) {
  269. foreach ($entities as $entity) {
  270. $output = elgg_view_list_item($entity, array(
  271. 'use_hover' => false,
  272. 'class' => 'elgg-autocomplete-item',
  273. 'full_view' => false,
  274. 'href' => false,
  275. 'title' => $entity->name, // Default title would be a link
  276. ));
  277. $icon = elgg_view_entity_icon($entity, 'tiny', array(
  278. 'use_hover' => false,
  279. ));
  280. $result = array(
  281. 'type' => 'group',
  282. 'name' => $entity->name,
  283. 'desc' => strip_tags($entity->description),
  284. 'guid' => $entity->guid,
  285. 'label' => $output,
  286. 'value' => $entity->guid,
  287. 'icon' => $icon,
  288. 'url' => $entity->getURL(),
  289. );
  290. $results[$entity->name . rand(1, 100)] = $result;
  291. }
  292. }
  293. break;
  294. case 'friends':
  295. $options = array(
  296. 'type' => 'user',
  297. 'limit' => $limit,
  298. 'relationship' => 'friend',
  299. 'relationship_guid' => $user->getGUID(),
  300. 'joins' => array("JOIN {$dbprefix}users_entity ue ON e.guid = ue.guid"),
  301. 'wheres' => array(
  302. "ue.banned = 'no'",
  303. "(ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%')"
  304. )
  305. );
  306. $entities = elgg_get_entities_from_relationship($options);
  307. if (!empty($entities)) {
  308. foreach ($entities as $entity) {
  309. $output = elgg_view_list_item($entity, array(
  310. 'use_hover' => false,
  311. 'use_link' => false,
  312. 'class' => 'elgg-autocomplete-item',
  313. 'title' => $entity->name, // Default title would be a link
  314. ));
  315. $icon = elgg_view_entity_icon($entity, 'tiny', array(
  316. 'use_hover' => false,
  317. ));
  318. $result = array(
  319. 'type' => 'user',
  320. 'name' => $entity->name,
  321. 'desc' => $entity->username,
  322. 'guid' => $entity->guid,
  323. 'label' => $output,
  324. 'value' => $entity->username,
  325. 'icon' => $icon,
  326. 'url' => $entity->getURL(),
  327. 'html' => elgg_view('input/userpicker/item', array(
  328. 'entity' => $entity,
  329. 'input_name' => $input_name,
  330. )),
  331. );
  332. $results[$entity->name . rand(1, 100)] = $result;
  333. }
  334. }
  335. break;
  336. default:
  337. header("HTTP/1.0 400 Bad Request", true);
  338. echo "livesearch: unknown match_on of $match_type";
  339. exit;
  340. break;
  341. }
  342. }
  343. ksort($results);
  344. header("Content-Type: application/json;charset=utf-8");
  345. echo json_encode(array_values($results));
  346. exit;
  347. }
  348. /**
  349. * Strip slashes from array keys
  350. *
  351. * @param array $array Array of values
  352. *
  353. * @return array Sanitized array
  354. * @access private
  355. */
  356. function _elgg_stripslashes_arraykeys($array) {
  357. if (is_array($array)) {
  358. $array2 = array();
  359. foreach ($array as $key => $data) {
  360. if ($key != stripslashes($key)) {
  361. $array2[stripslashes($key)] = $data;
  362. } else {
  363. $array2[$key] = $data;
  364. }
  365. }
  366. return $array2;
  367. } else {
  368. return $array;
  369. }
  370. }
  371. /**
  372. * Strip slashes
  373. *
  374. * @param mixed $value The value to remove slashes from
  375. *
  376. * @return mixed
  377. * @access private
  378. */
  379. function _elgg_stripslashes_deep($value) {
  380. if (is_array($value)) {
  381. $value = _elgg_stripslashes_arraykeys($value);
  382. $value = array_map('_elgg_stripslashes_deep', $value);
  383. } else {
  384. $value = stripslashes($value);
  385. }
  386. return $value;
  387. }
  388. /**
  389. * Initialize the input library
  390. *
  391. * @return void
  392. * @access private
  393. */
  394. function _elgg_input_init() {
  395. // register an endpoint for live search / autocomplete.
  396. elgg_register_page_handler('livesearch', 'input_livesearch_page_handler');
  397. // backward compatible for plugins directly accessing globals
  398. if (get_magic_quotes_gpc()) {
  399. $_POST = array_map('_elgg_stripslashes_deep', $_POST);
  400. $_GET = array_map('_elgg_stripslashes_deep', $_GET);
  401. $_COOKIE = array_map('_elgg_stripslashes_deep', $_COOKIE);
  402. $_REQUEST = array_map('_elgg_stripslashes_deep', $_REQUEST);
  403. if (!empty($_SERVER['REQUEST_URI'])) {
  404. $_SERVER['REQUEST_URI'] = stripslashes($_SERVER['REQUEST_URI']);
  405. }
  406. if (!empty($_SERVER['QUERY_STRING'])) {
  407. $_SERVER['QUERY_STRING'] = stripslashes($_SERVER['QUERY_STRING']);
  408. }
  409. if (!empty($_SERVER['HTTP_REFERER'])) {
  410. $_SERVER['HTTP_REFERER'] = stripslashes($_SERVER['HTTP_REFERER']);
  411. }
  412. if (!empty($_SERVER['PATH_INFO'])) {
  413. $_SERVER['PATH_INFO'] = stripslashes($_SERVER['PATH_INFO']);
  414. }
  415. if (!empty($_SERVER['PHP_SELF'])) {
  416. $_SERVER['PHP_SELF'] = stripslashes($_SERVER['PHP_SELF']);
  417. }
  418. if (!empty($_SERVER['PATH_TRANSLATED'])) {
  419. $_SERVER['PATH_TRANSLATED'] = stripslashes($_SERVER['PATH_TRANSLATED']);
  420. }
  421. }
  422. }
  423. return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
  424. $events->registerHandler('init', 'system', '_elgg_input_init');
  425. };