PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/mods/impersonate_user/impersonate_user.php

https://bitbucket.org/webop/webop-forum
PHP | 356 lines | 253 code | 56 blank | 47 comment | 36 complexity | 9e49f8ff902d7ae74d677bd387f53f30 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. if (!defined("PHORUM")) return;
  3. function phorum_mod_impersonate_user_generate_checksum($user_id, $salt = '')
  4. {
  5. // Find the data for the target user.
  6. $user = phorum_api_user_get($user_id);
  7. if (empty($user)) trigger_error(
  8. "impersonate_user mod: Unable to find user with user_id $user_id",
  9. E_USER_ERROR
  10. );
  11. // Check if the current user is an administrator and has a long
  12. // term session active. We use the current user's password and
  13. // sessid_lt fields as part of the checksum salt.
  14. if (empty($GLOBALS["PHORUM"]["user"]["admin"]) ||
  15. empty($GLOBALS["PHORUM"]["user"]["sessid_lt"])) trigger_error(
  16. "impersonate_user mod: The current user is not an administrator or " .
  17. "the \"sessid_lt\" user field is empty.",
  18. E_USER_ERROR
  19. );
  20. // Generate signed checksum data.
  21. $checksum = phorum_generate_data_signature(
  22. $GLOBALS["PHORUM"]["user"]["sessid_lt"] .
  23. $GLOBALS["PHORUM"]["user"]["password"] .
  24. $user['user_id'] .
  25. $user['password'] .
  26. $user['date_added'] .
  27. $salt
  28. );
  29. return $checksum;
  30. }
  31. // This addon will be called for doing the actual switching between users.
  32. function phorum_mod_impersonate_user_addon()
  33. {
  34. $PHORUM = $GLOBALS["PHORUM"];
  35. if (empty($PHORUM['args']['action'])) trigger_error(
  36. 'Illegal call to the impersonate_user mod addon handler: ' .
  37. 'missing parameter "action".',
  38. E_USER_ERROR
  39. );
  40. if ($PHORUM['args']['action'] == 'impersonate')
  41. {
  42. // Only for administrators. We also check this in the
  43. // phorum_mod_impersonate_user_generate_checksum() function, but I
  44. // am kind of paranoid about the whole user switching business.
  45. if (empty($PHORUM["user"]["admin"])) trigger_error(
  46. 'Illegal call to the impersonate_user mod addon handler: ' .
  47. 'called by a user that is not an administrator.',
  48. E_USER_ERROR
  49. );
  50. // Retrieve target parameter.
  51. if (empty($PHORUM['args']['target'])) trigger_error(
  52. 'Illegal call to the impersonate_user mod addon handler: ' .
  53. 'missing parameter "target".',
  54. E_USER_ERROR
  55. );
  56. $target_id = (int) $PHORUM['args']['target'];
  57. // Retrieve the checksum parameter.
  58. if (empty($PHORUM['args']['checksum'])) trigger_error(
  59. 'Illegal call to the impersonate_user mod addon handler: ' .
  60. 'missing parameter "checksum".',
  61. E_USER_ERROR
  62. );
  63. $checksum = $PHORUM['args']['checksum'];
  64. // Check the checksum value.
  65. $compare = phorum_mod_impersonate_user_generate_checksum($target_id);
  66. if ($compare !== $checksum) trigger_error(
  67. 'Illegal call to the impersonate_user mod addon handler: ' .
  68. 'the checksum for impersonating user id ' . $target_id .
  69. ' is invalid.',
  70. E_USER_ERROR
  71. );
  72. // Setup the data for enabling switching back to the original user.
  73. // This uses some salt to add a bit of randomness to the switchback
  74. // cookie info.
  75. $salt = md5(microtime());
  76. $admin_id = $PHORUM['user']['user_id'];
  77. $checksum = phorum_mod_impersonate_user_generate_checksum($admin_id, $salt);
  78. phorum_api_user_save_settings(array(
  79. 'mod_impersonate_user' => $target_id . ":" . $checksum
  80. ));
  81. // A cookie is used to remember the switching back info for the user.
  82. setcookie(
  83. "mod_impersonate_user",
  84. "$admin_id:$target_id:$checksum",
  85. 0, $PHORUM["session_path"], $PHORUM["session_domain"]
  86. );
  87. // Impersonate the target user.
  88. phorum_api_user_set_active_user(
  89. PHORUM_FORUM_SESSION,
  90. $target_id,
  91. PHORUM_FLAG_SESSION_ST
  92. );
  93. phorum_api_user_session_create(
  94. PHORUM_FORUM_SESSION,
  95. PHORUM_SESSID_RESET_LOGIN
  96. );
  97. }
  98. elseif ($PHORUM['args']['action'] == 'switchback')
  99. {
  100. // Check if we have a switchback cookie.
  101. if (!isset($_COOKIE['mod_impersonate_user']) ||
  102. strstr($_COOKIE['mod_impersonate_user'], ':') === FALSE) {
  103. trigger_error(
  104. 'Illegal call to the impersonate_user mod addon handler: ' .
  105. 'the mod_impersonate_user cookie containing the switchback ' .
  106. 'checksum is not available.',
  107. E_USER_ERROR
  108. );
  109. }
  110. // Retrieve the data from the cookie.
  111. list($admin_id, $c_target_id, $c_checksum) =
  112. explode(':', $_COOKIE['mod_impersonate_user']);
  113. settype($admin_id, "int");
  114. settype($c_target_id, "int");
  115. // Check if the target id in the cookie matches the active user.
  116. if ($c_target_id != $PHORUM['user']['user_id']) trigger_error(
  117. 'Illegal call to the impersonate_user mod addon handler: ' .
  118. 'the switchback cookie is not owned by the active user',
  119. E_USER_ERROR
  120. );
  121. // Retrieve switchback data that we stored in the admin user profile.
  122. $adminuser = phorum_api_user_get((int)$admin_id);
  123. if (empty($adminuser)) trigger_error(
  124. 'Illegal call to the impersonate_user mod addon handler: ' .
  125. 'no user found for switchback user_id $admin_id.',
  126. E_USER_ERROR
  127. );
  128. $p_target_id = NULL;
  129. $p_checksum = NULL;
  130. if (!empty($adminuser['settings_data']['mod_impersonate_user'])) {
  131. list($p_target_id, $p_checksum) =
  132. split(':', $adminuser['settings_data']['mod_impersonate_user']);
  133. }
  134. if ($p_target_id !== NULL) settype($p_target_id, "int");
  135. // Check if switchback user data was found in the profile.
  136. if ($p_target_id === NULL || $p_checksum === NULL) trigger_error(
  137. 'Illegal call to the impersonate_user mod addon handler: ' .
  138. 'no switchback user data found in the settings_data for ' .
  139. "admin user $admin_id.",
  140. E_USER_ERROR
  141. );
  142. // Check if the checksums and user ids match.
  143. if ($p_target_id !== $c_target_id ||
  144. $p_checksum !== $c_checksum) trigger_error(
  145. 'Illegal call to the impersonate_user mod addon handler: ' .
  146. 'cookie checksum and/or user_ids for impersonating user id ' .
  147. "$c_target_id do not match the data that was stored in the " .
  148. 'admin user profile.',
  149. E_USER_ERROR
  150. );
  151. // Clean up the switchback cookie.
  152. setcookie(
  153. "mod_impersonate_user", "",
  154. 0, $PHORUM["session_path"], $PHORUM["session_domain"]
  155. );
  156. // Switch back to the admin user.
  157. phorum_api_user_set_active_user(
  158. PHORUM_FORUM_SESSION,
  159. $admin_id,
  160. PHORUM_FLAG_SESSION_ST
  161. );
  162. phorum_api_user_session_create(
  163. PHORUM_FORUM_SESSION,
  164. PHORUM_SESSID_RESET_LOGIN
  165. );
  166. }
  167. else trigger_error(
  168. 'Illegal call to the impersonate_user mod addon handler: ' .
  169. 'the value for parameter "action" is invalid.',
  170. E_USER_ERROR
  171. );
  172. phorum_redirect_by_url(phorum_get_url(PHORUM_INDEX_URL));
  173. }
  174. // Add a impersonate user link to the user profile.
  175. function phorum_mod_impersonate_user_profile($profile)
  176. {
  177. // Only for administrators, we create the impersonate user link.
  178. if (empty($GLOBALS["PHORUM"]["user"]["admin"])) return $profile;
  179. // Add the impersonate user link to the profile data.
  180. $checksum = phorum_mod_impersonate_user_generate_checksum($profile['user_id']);
  181. $profile['URL']['IMPERSONATE_USER'] = phorum_get_url(
  182. PHORUM_ADDON_URL,
  183. "module=impersonate_user",
  184. "action=impersonate",
  185. "target=".(int)$profile['user_id'],
  186. "checksum=".urlencode($checksum)
  187. );
  188. return $profile;
  189. }
  190. // Setup data for the impersonate user notice and switch back link.
  191. function phorum_mod_impersonate_user_common()
  192. {
  193. global $PHORUM;
  194. $lang = $PHORUM['DATA']['LANG']['mod_impersonate_user'];
  195. // Check if we have a switchback cookie.
  196. if (!isset($_COOKIE['mod_impersonate_user']) ||
  197. strstr($_COOKIE['mod_impersonate_user'], ':') === FALSE) return;
  198. list($admin_id, $target_id, $checksum) =
  199. explode(':', $_COOKIE['mod_impersonate_user']);
  200. // If we are already active using the $admin_id or if the $target_id
  201. // is not the active user's user_id, then we do not have to display
  202. // the notice. This might happen if cleaning up the switchback cookie
  203. // failed for some reason or if logging out / loggin into a different
  204. // account.
  205. if ($admin_id == $PHORUM['user']['user_id'] ||
  206. $target_id != $PHORUM['user']['user_id']) {
  207. // Clean up the switchback cookie.
  208. setcookie(
  209. "mod_impersonate_user", "",
  210. 0, $PHORUM["session_path"], $PHORUM["session_domain"]
  211. );
  212. return;
  213. }
  214. // Setup template data.
  215. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['TARGET'] =
  216. phorum_api_user_get_display_name($PHORUM['user']['user_id']);
  217. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['ADMIN'] =
  218. phorum_api_user_get_display_name($admin_id);
  219. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['NOTICE'] =
  220. str_replace(
  221. '%user%',
  222. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['TARGET'],
  223. $lang['Notice']
  224. );
  225. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['SWITCHBACK'] =
  226. str_replace(
  227. '%user%',
  228. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['ADMIN'],
  229. $lang['SwitchBack']
  230. );
  231. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['URL']['SWITCHBACK'] =
  232. phorum_get_url(
  233. PHORUM_ADDON_URL,
  234. "module=impersonate_user",
  235. "action=switchback"
  236. );
  237. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['URL']['TEMPLATES'] =
  238. $PHORUM['http_path'] . '/mods/impersonate_user/templates';
  239. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['CLEAR_COOKIE'] =
  240. 'mod_impersonate_user=cleared;' .
  241. (!empty($PHORUM['session_path'])
  242. ? 'path=' . $PHORUM['session_path'] . ';'
  243. : '') .
  244. (!empty($PHORUM['session_domain'])
  245. ? 'domain=' . $PHORUM['session_domain'] . ';'
  246. : '') .
  247. 'expires=Thu, 01-Jan-1970 00:00:01 GMT';
  248. }
  249. function phorum_mod_impersonate_user_after_header()
  250. {
  251. global $PHORUM;
  252. // Display a switch back notice if data was setup in the common hook.
  253. if (empty($PHORUM['DATA']['MOD_IMPERSONATE_USER']['URL']['SWITCHBACK'])) {
  254. return;
  255. }
  256. include(phorum_get_template('impersonate_user::notice'));
  257. }
  258. // Display the impersonate user link on the profile page.
  259. function phorum_mod_impersonate_user_before_footer()
  260. {
  261. $PHORUM = $GLOBALS["PHORUM"];
  262. if (!empty($PHORUM['DATA']['PROFILE']['URL']['IMPERSONATE_USER']) &&
  263. phorum_page == 'profile') {
  264. include(phorum_get_template('impersonate_user::profile'));
  265. }
  266. }
  267. function phorum_mod_impersonate_user_cc_panel($data)
  268. {
  269. global $PHORUM;
  270. // Impersonate user is only available for admins.
  271. if (empty($PHORUM['user']['admin'])) return $data;
  272. $PHORUM['DATA']['MOD_IMPERSONATE_USER']['URL']['TEMPLATES'] =
  273. $PHORUM['http_path'] . '/mods/impersonate_user/templates';
  274. // We set {MODERATOR} here, so the cc_index.tpl will show the
  275. // moderate header. This should already be the case for administrators,
  276. // but we make it extra sure here.
  277. if (!empty($PHORUM['user']['admin'])) {
  278. $PHORUM['DATA']['MODERATOR'] = TRUE;
  279. }
  280. if ($data['panel'] == 'impersonate_user') {
  281. // Separate include file, because of its length.
  282. include('./mods/impersonate_user/cc_panel.php');
  283. $data['handled'] = TRUE;
  284. }
  285. return $data;
  286. }
  287. function phorum_mod_impersonate_user_cc_moderator_menu()
  288. {
  289. global $PHORUM;
  290. // Only for administrators, we create the impersonate user link.
  291. if (empty($PHORUM["user"]["admin"])) return $profile;
  292. // Generate the require template data for the control panel menu button.
  293. if ($PHORUM["DATA"]["PROFILE"]["PANEL"] == 'impersonate_user')
  294. $PHORUM["DATA"]["IMPERSONATE_USER_PANEL_ACTIVE"] = TRUE;
  295. $PHORUM["DATA"]["URL"]["CC_IMPERSONATE_USER"] =
  296. phorum_get_url(PHORUM_CONTROLCENTER_URL, "panel=impersonate_user");
  297. // Show the menu button.
  298. include(phorum_get_template('impersonate_user::cc_menu_item'));
  299. }
  300. ?>