1. <?php
  2. menu_register(array(
  3. 'oauth' => array(
  4. 'callback' => 'user_oauth',
  5. 'hidden' => 'true',
  6. ),
  7. 'login' => array(
  8. 'callback' => 'user_login',
  9. 'hidden' => 'true',
  10. ),
  11. ));
  12. function user_oauth() {
  13. require_once 'OAuth.php';
  14. // Session used to keep track of secret token during authorisation step
  15. session_start();
  16. // Flag forces twitter_process() to use OAuth signing
  17. $GLOBALS['user']['type'] = 'oauth';
  18. if ($oauth_token = $_GET['oauth_token']) {
  19. // Generate ACCESS token request
  20. $params = array('oauth_verifier' => $_GET['oauth_verifier']);
  21. $response = twitter_process('https://api.twitter.com/oauth/access_token', $params);
  22. parse_str($response, $token);
  23. // Store ACCESS tokens in COOKIE
  24. $GLOBALS['user']['password'] = $token['oauth_token'] .'|'.$token['oauth_token_secret'];
  25. // Fetch the user's screen name with a quick API call
  26. unset($_SESSION['oauth_request_token_secret']);
  27. $user = twitter_process('https://api.twitter.com/1.1/account/verify_credentials.json');
  28. $GLOBALS['user']['username'] = $user->screen_name;
  29. _user_save_cookie(1);
  30. header('Location: '. BASE_URL);
  31. exit();
  32. } else {
  33. // Generate AUTH token request
  34. $params = array('oauth_callback' => BASE_URL.'oauth');
  35. $response = twitter_process('https://api.twitter.com/oauth/request_token', $params);
  36. parse_str($response, $token);
  37. // Save secret token to session to validate the result that comes back from Twitter
  38. $_SESSION['oauth_request_token_secret'] = $token['oauth_token_secret'];
  39. // redirect user to authorisation URL
  40. $authorise_url = 'https://api.twitter.com/oauth/authorize?oauth_token='.$token['oauth_token'];
  41. header("Location: $authorise_url");
  42. }
  43. }
  44. function user_oauth_sign(&$url, &$args = false) {
  45. require_once 'OAuth.php';
  46. $method = $args !== false ? 'POST' : 'GET';
  47. // Move GET parameters out of $url and into $args
  48. if (preg_match_all('#[?&]([^=]+)=([^&]+)#', $url, $matches, PREG_SET_ORDER)) {
  49. foreach ($matches as $match) {
  50. $args[$match[1]] = $match[2];
  51. }
  52. $url = substr($url, 0, strpos($url, '?'));
  53. }
  54. $sig_method = new OAuthSignatureMethod_HMAC_SHA1();
  55. $consumer = new OAuthConsumer(OAUTH_CONSUMER_KEY, OAUTH_CONSUMER_SECRET);
  56. $token = NULL;
  57. if (($oauth_token = $_GET['oauth_token']) && $_SESSION['oauth_request_token_secret']) {
  58. $oauth_token_secret = $_SESSION['oauth_request_token_secret'];
  59. } else {
  60. list($oauth_token, $oauth_token_secret) = explode('|', $GLOBALS['user']['password']);
  61. }
  62. if ($oauth_token && $oauth_token_secret) {
  63. $token = new OAuthConsumer($oauth_token, $oauth_token_secret);
  64. }
  65. $request = OAuthRequest::from_consumer_and_token($consumer, $token, $method, $url, $args);
  66. $request->sign_request($sig_method, $consumer, $token);
  67. switch ($method) {
  68. case 'GET':
  69. $url = $request->to_url();
  70. $args = false;
  71. return;
  72. case 'POST':
  73. $url = $request->get_normalized_http_url();
  74. $args = $request->to_postdata();
  75. return;
  76. }
  77. }
  78. function user_ensure_authenticated() {
  79. if (!user_is_authenticated()) {
  80. $content = theme('login');
  81. $content .= file_get_contents('about.html');
  82. theme('page', 'Login', $content);
  83. }
  84. }
  85. function user_logout() {
  86. unset($GLOBALS['user']);
  87. setcookie('USER_AUTH', '', time() - 3600, '/');
  88. }
  89. function user_is_authenticated() {
  90. if (!isset($GLOBALS['user'])) {
  91. if(array_key_exists('USER_AUTH', $_COOKIE)) {
  92. _user_decrypt_cookie($_COOKIE['USER_AUTH']);
  93. } else {
  94. $GLOBALS['user'] = array();
  95. }
  96. }
  97. // Auto-logout any users that aren't correctly using OAuth
  98. if (user_current_username() && user_type() !== 'oauth') {
  99. user_logout();
  100. twitter_refresh('logout');
  101. }
  102. if (!user_current_username()) {
  103. if ($_POST['username'] && $_POST['password']) {
  104. $GLOBALS['user']['username'] = trim($_POST['username']);
  105. $GLOBALS['user']['password'] = $_POST['password'];
  106. $GLOBALS['user']['type'] = 'oauth';
  107. $sql = sprintf("SELECT * FROM user WHERE username='%s' AND password=MD5('%s') LIMIT 1", mysql_escape_string($GLOBALS['user']['username']), mysql_escape_string($GLOBALS['user']['password']));
  108. $rs = mysql_query($sql);
  109. if ($rs && $user = mysql_fetch_object($rs)) {
  110. $GLOBALS['user']['password'] = $user->oauth_key . '|' . $user->oauth_secret;
  111. } else {
  112. theme('error', 'Invalid username or password.');
  113. }
  114. _user_save_cookie($_POST['stay-logged-in'] == 'yes');
  115. header('Location: '. BASE_URL);
  116. exit();
  117. } else {
  118. return false;
  119. }
  120. }
  121. return true;
  122. }
  123. function user_current_username() {
  124. return $GLOBALS['user']['username'];
  125. }
  126. function user_is_current_user($username) {
  127. return (strcasecmp($username, user_current_username()) == 0);
  128. }
  129. function user_type() {
  130. return $GLOBALS['user']['type'];
  131. }
  132. function _user_save_cookie($stay_logged_in = 0) {
  133. $cookie = _user_encrypt_cookie();
  134. $duration = 0;
  135. if ($stay_logged_in) {
  136. $duration = time() + (3600 * 24 * 365);
  137. }
  138. setcookie('USER_AUTH', $cookie, $duration, '/');
  139. }
  140. function _user_encryption_key() {
  141. return ENCRYPTION_KEY;
  142. }
  143. function _user_encrypt_cookie() {
  144. $plain_text = $GLOBALS['user']['username'] . ':' . $GLOBALS['user']['password'] . ':' . $GLOBALS['user']['type'];
  145. $td = mcrypt_module_open('blowfish', '', 'cfb', '');
  146. $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
  147. mcrypt_generic_init($td, _user_encryption_key(), $iv);
  148. $crypt_text = mcrypt_generic($td, $plain_text);
  149. mcrypt_generic_deinit($td);
  150. return base64_encode($iv.$crypt_text);
  151. }
  152. function _user_decrypt_cookie($crypt_text) {
  153. $crypt_text = base64_decode($crypt_text);
  154. $td = mcrypt_module_open('blowfish', '', 'cfb', '');
  155. $ivsize = mcrypt_enc_get_iv_size($td);
  156. $iv = substr($crypt_text, 0, $ivsize);
  157. $crypt_text = substr($crypt_text, $ivsize);
  158. mcrypt_generic_init($td, _user_encryption_key(), $iv);
  159. $plain_text = mdecrypt_generic($td, $crypt_text);
  160. mcrypt_generic_deinit($td);
  161. list($GLOBALS['user']['username'], $GLOBALS['user']['password'], $GLOBALS['user']['type']) = explode(':', $plain_text);
  162. }
  163. function user_login() {
  164. return theme('page', 'Login','
  165. <form method="post" action="'.$_GET['q'].'">
  166. <p>Username <input name="username" size="15" />
  167. <br />Password <input name="password" type="password" size="15" />
  168. <br /><label><input type="checkbox" checked="checked" value="yes" name="stay-logged-in" /> Stay logged in? </label>
  169. <br /><input type="submit" value="Sign In" /></p>
  170. </form>
  171. <p><b>Registration steps:</b></p>
  172. <ol>
  173. <li><a href="oauth">Sign in via Twitter.com</a> from any computer</li>
  174. <li>Visit the Dabr settings page to choose a password</li>
  175. <li>Done! You can now benefit from accessing Twitter through Dabr from anywhere (even from computers that block Twitter.com)</li>
  176. </ol>
  177. ');
  178. }
  179. function theme_login() {
  180. $content = '<div style="margin:1em; font-size: 1.2em">
  181. <p><a href="oauth"><img src="images/twitter_button_2_lo.gif" alt="Sign in with Twitter/OAuth" width="165" height="28" /></a><br /><a href="oauth">Sign in via Twitter.com</a></p>
  182. <p>Twitter no longer allow you to log in directly with a username and password so we can\'t show the standard login form. There\'s some more information on the <a href="http://blog.dabr.co.uk/">Dabr blog</a>.</p>';
  183. if (MYSQL_USERS == 'ON') $content .= '<p>No access to Twitter.com? <a href="login">Sign in with your Dabr account</a></p>';
  184. $content .= '</div>';
  185. return $content;
  186. }
  187. function theme_logged_out() {
  188. return '<p>Logged out. <a href="">Login again</a></p>';
  189. }