| 1 |
<?php
|
| 2 |
// $Id: drupalvb.inc.php,v 1.33 2009/02/01 02:00:25 sun Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Drupal vB CRUD functions.
|
| 7 |
*/
|
| 8 |
|
| 9 |
/**
|
| 10 |
* Set the necessary cookies for the user to be logged into the forum.
|
| 11 |
*
|
| 12 |
* Frontend cookie names:
|
| 13 |
* - lastvisit, lastactivity, sessionhash
|
| 14 |
* Backend cookie names:
|
| 15 |
* - cpsession, userid, password
|
| 16 |
*
|
| 17 |
* However, in all cases the cookiedomain is NOT prefixed with a dot unless
|
| 18 |
* cookie domain has not been manually altered to either a suggested value or
|
| 19 |
* custom value in vB's settings.
|
| 20 |
*/
|
| 21 |
function drupalvb_set_login_cookies($userid) {
|
| 22 |
// Load required vB user data.
|
| 23 |
$vbuser = db_fetch_array(drupalvb_db_query("SELECT userid, password, salt FROM {user} WHERE userid = %d", $userid));
|
| 24 |
if (!$vbuser) {
|
| 25 |
return FALSE;
|
| 26 |
}
|
| 27 |
|
| 28 |
$vb_config = drupalvb_get('config');
|
| 29 |
$vb_options = drupalvb_get('options');
|
| 30 |
|
| 31 |
$cookie_prefix = (isset($vb_config['Misc']['cookieprefix']) ? $vb_config['Misc']['cookieprefix'] : 'bb');
|
| 32 |
$cookie_path = $vb_options['cookiepath'];
|
| 33 |
$now = time();
|
| 34 |
$expire = $now + (@ini_get('session.cookie_lifetime') ? ini_get('session.cookie_lifetime') : 60 * 60 * 24 * 365);
|
| 35 |
|
| 36 |
$vb_cookie_domain = (!empty($vb_options['cookiedomain']) ? $vb_options['cookiedomain'] : $GLOBALS['cookie_domain']);
|
| 37 |
// Per RFC 2109, cookie domains must contain at least one dot other than the
|
| 38 |
// first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
|
| 39 |
// @see conf_init()
|
| 40 |
if (!(count(explode('.', $vb_cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $vb_cookie_domain)))) {
|
| 41 |
$vb_cookie_domain = '';
|
| 42 |
}
|
| 43 |
|
| 44 |
// Clear out old session (if available).
|
| 45 |
if (!empty($_COOKIE[$cookie_prefix .'sessionhash'])) {
|
| 46 |
drupalvb_db_query("DELETE FROM {session} WHERE sessionhash = '%s'", $_COOKIE[$cookie_prefix .'sessionhash']);
|
| 47 |
}
|
| 48 |
|
| 49 |
// Setup user session.
|
| 50 |
$ip = implode('.', array_slice(explode('.', drupalvb_get_ip()), 0, 4 - $vb_options['ipcheck']));
|
| 51 |
$idhash = md5($_SERVER['HTTP_USER_AGENT'] . $ip);
|
| 52 |
$sessionhash = md5($now . request_uri() . $idhash . $_SERVER['REMOTE_ADDR'] . user_password(6));
|
| 53 |
|
| 54 |
drupalvb_db_query("REPLACE INTO {session} (sessionhash, userid, host, idhash, lastactivity, location, useragent, loggedin) VALUES ('%s', %d, '%s', '%s', %d, '%s', '%s', %d)", $sessionhash, $vbuser['userid'], substr($_SERVER['REMOTE_ADDR'], 0, 15), $idhash, $now, '/forum/', $_SERVER['HTTP_USER_AGENT'], 2);
|
| 55 |
|
| 56 |
// Setup cookies.
|
| 57 |
setcookie($cookie_prefix .'sessionhash', $sessionhash, $expire, $cookie_path, $vb_cookie_domain);
|
| 58 |
setcookie($cookie_prefix .'lastvisit', $now, $expire, $cookie_path, $vb_cookie_domain);
|
| 59 |
setcookie($cookie_prefix .'lastactivity', $now, $expire, $cookie_path, $vb_cookie_domain);
|
| 60 |
setcookie($cookie_prefix .'userid', $vbuser['userid'], $expire, $cookie_path, $vb_cookie_domain);
|
| 61 |
setcookie($cookie_prefix .'password', md5($vbuser['password'] . variable_get('drupalvb_license', '')), $expire, $cookie_path, $vb_cookie_domain);
|
| 62 |
return TRUE;
|
| 63 |
}
|
| 64 |
|
| 65 |
/**
|
| 66 |
* Clear all vB cookies for the current user.
|
| 67 |
*
|
| 68 |
* @see drupalvb_logout(), drupalvb_user_logout()
|
| 69 |
*/
|
| 70 |
function drupalvb_clear_cookies($userid = NULL) {
|
| 71 |
$vb_config = drupalvb_get('config');
|
| 72 |
$vb_options = drupalvb_get('options');
|
| 73 |
|
| 74 |
$cookie_prefix = (isset($vb_config['Misc']['cookieprefix']) ? $vb_config['Misc']['cookieprefix'] : 'bb');
|
| 75 |
$cookie_path = $vb_options['cookiepath'];
|
| 76 |
$expire = time() - 86400;
|
| 77 |
|
| 78 |
$vb_cookie_domain = (!empty($vb_options['cookiedomain']) ? $vb_options['cookiedomain'] : $GLOBALS['cookie_domain']);
|
| 79 |
// Per RFC 2109, cookie domains must contain at least one dot other than the
|
| 80 |
// first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
|
| 81 |
// @see conf_init()
|
| 82 |
if (!(count(explode('.', $vb_cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $vb_cookie_domain)))) {
|
| 83 |
$vb_cookie_domain = '';
|
| 84 |
}
|
| 85 |
|
| 86 |
if (!empty($userid)) {
|
| 87 |
drupalvb_db_query("DELETE FROM {session} WHERE userid = %d", $userid);
|
| 88 |
drupalvb_db_query("UPDATE {user} SET lastvisit = %d WHERE userid = %d", time(), $userid);
|
| 89 |
}
|
| 90 |
|
| 91 |
setcookie($cookie_prefix .'sessionhash', '', $expire, $cookie_path, $vb_cookie_domain);
|
| 92 |
setcookie($cookie_prefix .'lastvisit', '', $expire, $cookie_path, $vb_cookie_domain);
|
| 93 |
setcookie($cookie_prefix .'lastactivity', '', $expire, $cookie_path, $vb_cookie_domain);
|
| 94 |
setcookie($cookie_prefix .'userid', '', $expire, $cookie_path, $vb_cookie_domain);
|
| 95 |
setcookie($cookie_prefix .'password', '', $expire, $cookie_path, $vb_cookie_domain);
|
| 96 |
}
|
| 97 |
|
| 98 |
/**
|
| 99 |
* Determines the IP address of current user.
|
| 100 |
*/
|
| 101 |
function drupalvb_get_ip() {
|
| 102 |
$ip = $_SERVER['REMOTE_ADDR'];
|
| 103 |
|
| 104 |
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
|
| 105 |
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
| 106 |
}
|
| 107 |
else if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
|
| 108 |
// Make sure we don't pick up an internal IP defined by RFC1918.
|
| 109 |
foreach ($matches[0] as $match) {
|
| 110 |
if (!preg_match("#^(10|172\.16|192\.168)\.#", $match)) {
|
| 111 |
$ip = $match;
|
| 112 |
break;
|
| 113 |
}
|
| 114 |
}
|
| 115 |
}
|
| 116 |
else if (isset($_SERVER['HTTP_FROM'])) {
|
| 117 |
$ip = $_SERVER['HTTP_FROM'];
|
| 118 |
}
|
| 119 |
return $ip;
|
| 120 |
}
|
| 121 |
|
| 122 |
/**
|
| 123 |
* Create a user in vBulletin.
|
| 124 |
*
|
| 125 |
* @param object $account
|
| 126 |
* A Drupal user account.
|
| 127 |
* @param array $edit
|
| 128 |
* Form values provided by hook_user().
|
| 129 |
*/
|
| 130 |
function drupalvb_create_user($account, $edit) {
|
| 131 |
// Ensure we are not duplicating a user.
|
| 132 |
if (db_result(drupalvb_db_query("SELECT COUNT(userid) FROM {user} WHERE LOWER(username) = LOWER('%s')", drupalvb_htmlspecialchars($edit['name']))) > 0) {
|
| 133 |
return FALSE;
|
| 134 |
}
|
| 135 |
|
| 136 |
$salt = '';
|
| 137 |
for ($i = 0; $i < 3; $i++) {
|
| 138 |
$salt .= chr(rand(32, 126));
|
| 139 |
}
|
| 140 |
// Note: Password is already hashed during user export.
|
| 141 |
if (isset($edit['md5pass'])) {
|
| 142 |
$passhash = md5($edit['md5pass'] . $salt);
|
| 143 |
}
|
| 144 |
else {
|
| 145 |
$passhash = md5(md5($edit['pass']) . $salt);
|
| 146 |
}
|
| 147 |
|
| 148 |
$passdate = date('Y-m-d', $account->created);
|
| 149 |
$joindate = $account->created;
|
| 150 |
|
| 151 |
// Attempt to grab the user title from the database.
|
| 152 |
$result = drupalvb_db_query("SELECT title FROM {usertitle} WHERE minposts = 0");
|
| 153 |
if ($resarray = db_fetch_array($result)) {
|
| 154 |
$usertitle = $resarray['title'];
|
| 155 |
}
|
| 156 |
else {
|
| 157 |
$usertitle = 'Junior Member';
|
| 158 |
}
|
| 159 |
|
| 160 |
// Divide timezone by 3600, since vBulletin stores hours.
|
| 161 |
$timezone = variable_get('date_default_timezone', 0);
|
| 162 |
$timezone = ($timezone != 0 ? $timezone / 3600 : 0);
|
| 163 |
|
| 164 |
// Default new user options: I got these by setting up a new user how I
|
| 165 |
// wanted and looking in the database to see what options were set for him.
|
| 166 |
$options = variable_get('drupalvb_default_options', '3415');
|
| 167 |
|
| 168 |
// Default usergroup id.
|
| 169 |
$usergroupid = variable_get('drupalvb_default_usergroup', '2');
|
| 170 |
|
| 171 |
// Set up the insertion query.
|
| 172 |
$result = drupalvb_db_query("INSERT INTO {user} (username, usergroupid, password, passworddate, usertitle, email, salt, showvbcode, languageid, timezoneoffset, posts, joindate, lastvisit, lastactivity, options) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', 1, %d, '%s', 0, '%s', '%s', '%s', '%s')", drupalvb_htmlspecialchars($edit['name']), $usergroupid, $passhash, $passdate, $usertitle, $edit['mail'], $salt, drupalvb_get('languageid'), $timezone, $joindate, time(), time(), $options);
|
| 173 |
|
| 174 |
$userid = drupalvb_db_last_insert_id('user', 'userid');
|
| 175 |
|
| 176 |
drupalvb_db_query("INSERT INTO {userfield} (userid) VALUES (%d)", $userid);
|
| 177 |
drupalvb_db_query("INSERT INTO {usertextfield} (userid) VALUES (%d)", $userid);
|
| 178 |
|
| 179 |
// Insert new user into mapping table.
|
| 180 |
drupalvb_set_mapping($account->uid, $userid);
|
| 181 |
|
| 182 |
// Return userid of newly created account.
|
| 183 |
return $userid;
|
| 184 |
}
|
| 185 |
|
| 186 |
/**
|
| 187 |
* Update a user in vBulletin.
|
| 188 |
*/
|
| 189 |
function drupalvb_update_user($account, $edit) {
|
| 190 |
$fields = $values = array();
|
| 191 |
|
| 192 |
foreach ($edit as $field => $value) {
|
| 193 |
if (empty($value)) {
|
| 194 |
continue;
|
| 195 |
}
|
| 196 |
switch ($field) {
|
| 197 |
case 'name':
|
| 198 |
$fields[] = "username = '%s'";
|
| 199 |
$values[] = drupalvb_htmlspecialchars($value);
|
| 200 |
break;
|
| 201 |
|
| 202 |
case 'pass':
|
| 203 |
$fields[] = "password = '%s'";
|
| 204 |
// Note: Password is already hashed during user export.
|
| 205 |
if (isset($edit['md5pass'])) {
|
| 206 |
$values[] = md5($edit['md5pass'] . $edit['salt']);
|
| 207 |
}
|
| 208 |
else {
|
| 209 |
$values[] = md5(md5($value) . $edit['salt']);
|
| 210 |
}
|
| 211 |
$fields[] = "salt = '%s'";
|
| 212 |
$values[] = $edit['salt'];
|
| 213 |
$fields[] = "passworddate = '%s'";
|
| 214 |
$values[] = date('Y-m-d', time());
|
| 215 |
break;
|
| 216 |
|
| 217 |
case 'mail':
|
| 218 |
$fields[] = "email = '%s'";
|
| 219 |
$values[] = $value;
|
| 220 |
break;
|
| 221 |
|
| 222 |
case 'language':
|
| 223 |
$fields[] = "languageid = %d";
|
| 224 |
$values[] = drupalvb_get('languageid', $value);
|
| 225 |
break;
|
| 226 |
}
|
| 227 |
}
|
| 228 |
$fields[] = 'lastactivity = %d';
|
| 229 |
$values[] = time();
|
| 230 |
|
| 231 |
// Use previous case insensitive username to update conflicting names.
|
| 232 |
$values[] = drupalvb_htmlspecialchars($account->name);
|
| 233 |
drupalvb_db_query("UPDATE {user} SET ". implode(', ', $fields) ." WHERE LOWER(username) = LOWER('%s')", $values);
|
| 234 |
|
| 235 |
// Ensure this user exists in the mapping table.
|
| 236 |
// When integrating an existing installation, the mapping may not yet exist.
|
| 237 |
$userid = db_result(drupalvb_db_query("SELECT userid FROM {user} WHERE username = '%s'", drupalvb_htmlspecialchars($account->name)));
|
| 238 |
drupalvb_set_mapping($account->uid, $userid);
|
| 239 |
}
|
| 240 |
|
| 241 |
/**
|
| 242 |
* Ensure that a mapping between two existing user accounts exists.
|
| 243 |
*
|
| 244 |
* @param $uid
|
| 245 |
* A Drupal user id.
|
| 246 |
* @param $userid
|
| 247 |
* A vBulletin user id.
|
| 248 |
*/
|
| 249 |
function drupalvb_set_mapping($uid, $userid) {
|
| 250 |
db_query("INSERT IGNORE INTO {drupalvb_users} (uid, userid) VALUES (%d, %d)", $uid, $userid);
|
| 251 |
}
|
| 252 |
|
| 253 |
/**
|
| 254 |
* Export all drupal users to vBulletin.
|
| 255 |
*/
|
| 256 |
function drupalvb_export_drupal_users() {
|
| 257 |
module_load_include('inc', 'drupalvb');
|
| 258 |
|
| 259 |
$result = db_query("SELECT * FROM {users} ORDER BY uid");
|
| 260 |
while ($user = db_fetch_object($result)) {
|
| 261 |
if ($user->uid == 0) {
|
| 262 |
continue;
|
| 263 |
}
|
| 264 |
// Let create/update functions know that passwords are hashed already.
|
| 265 |
$user->md5pass = $user->pass;
|
| 266 |
if (!drupalvb_create_user($user, (array)$user)) {
|
| 267 |
// Username already exists, update email and password only.
|
| 268 |
// Case insensitive username is required to detect collisions.
|
| 269 |
$vbuser = db_fetch_array(drupalvb_db_query("SELECT salt FROM {user} WHERE LOWER(username) = LOWER('%s')", drupalvb_htmlspecialchars($user->name)));
|
| 270 |
drupalvb_update_user($user, array_merge((array)$user, $vbuser));
|
| 271 |
}
|
| 272 |
}
|
| 273 |
}
|
| 274 |
|
| 275 |
/**
|
| 276 |
* Get vBulletin configuration options.
|
| 277 |
*/
|
| 278 |
function drupalvb_get_options() {
|
| 279 |
static $options = array();
|
| 280 |
|
| 281 |
if (empty($options)) {
|
| 282 |
$result = db_query("SELECT varname, value FROM {setting}");
|
| 283 |
while ($var = db_fetch_array($result)) {
|
| 284 |
$options[$var['varname']] = $var['value'];
|
| 285 |
}
|
| 286 |
}
|
| 287 |
return $options;
|
| 288 |
}
|
| 289 |
|
| 290 |
/**
|
| 291 |
* Get vBulletin configuration.
|
| 292 |
*/
|
| 293 |
function drupalvb_get_config() {
|
| 294 |
static $config = array();
|
| 295 |
|
| 296 |
// @todo Find & include vB's config automatically?
|
| 297 |
// $files = file_scan_directory('.', '^config.php$', $nomask = array('.', '..', 'CVS', '.svn'));
|
| 298 |
$config_file = drupal_get_path('module', 'drupalvb') .'/config.php';
|
| 299 |
if (empty($config) && file_exists($config_file)) {
|
| 300 |
require_once $config_file;
|
| 301 |
}
|
| 302 |
return $config;
|
| 303 |
}
|
| 304 |
|
| 305 |
/**
|
| 306 |
* Get vB user roles.
|
| 307 |
*/
|
| 308 |
function drupalvb_get_roles() {
|
| 309 |
$result = drupalvb_db_query("SELECT usergroupid, title FROM {usergroup}");
|
| 310 |
|
| 311 |
$roles = array();
|
| 312 |
while ($data = db_fetch_object($result)) {
|
| 313 |
$roles[$data->usergroupid] = $data->title;
|
| 314 |
}
|
| 315 |
if (!$roles) {
|
| 316 |
$roles[] = t('No user roles could be found.');
|
| 317 |
}
|
| 318 |
return $roles;
|
| 319 |
}
|
| 320 |
|
| 321 |
/**
|
| 322 |
* Get vB language id by given ISO language code.
|
| 323 |
*/
|
| 324 |
function drupalvb_get_languageid($language = NULL) {
|
| 325 |
static $vblanguages;
|
| 326 |
|
| 327 |
if (!isset($vblanguages)) {
|
| 328 |
$vblanguages = array();
|
| 329 |
$result = drupalvb_db_query("SELECT languageid, title, languagecode FROM {language}");
|
| 330 |
while ($lang = db_fetch_array($result)) {
|
| 331 |
$vblanguages[$lang['languagecode']] = $lang['languageid'];
|
| 332 |
}
|
| 333 |
}
|
| 334 |
$options = drupalvb_get('options');
|
| 335 |
return (!empty($language) && isset($vblanguages[$language]) ? $vblanguages[$language] : $vblanguages[$options['languageid']]);
|
| 336 |
}
|
| 337 |
|
| 338 |
/**
|
| 339 |
* Get counts of guests and members currently online.
|
| 340 |
*/
|
| 341 |
function drupalvb_get_users_online() {
|
| 342 |
$vb_options = drupalvb_get('options');
|
| 343 |
|
| 344 |
$datecut = time() - $vb_options['cookietimeout'];
|
| 345 |
$numbervisible = 0;
|
| 346 |
$numberregistered = 0;
|
| 347 |
$numberguest = 0;
|
| 348 |
|
| 349 |
$result = drupalvb_db_query("SELECT user.username, user.usergroupid, session.userid, session.lastactivity FROM {session} AS session LEFT JOIN {user} AS user ON (user.userid = session.userid) WHERE session.lastactivity > %d", $datecut);
|
| 350 |
|
| 351 |
$userinfos = array();
|
| 352 |
|
| 353 |
while ($loggedin = db_fetch_array($result)) {
|
| 354 |
$userid = $loggedin['userid'];
|
| 355 |
if (!$userid) {
|
| 356 |
$numberguest++;
|
| 357 |
}
|
| 358 |
else if (empty($userinfos[$userid]) || ($userinfos[$userid]['lastactivity'] < $loggedin['lastactivity'])) {
|
| 359 |
$userinfos[$userid] = $loggedin;
|
| 360 |
}
|
| 361 |
}
|
| 362 |
foreach ($userinfos as $userid => $loggedin) {
|
| 363 |
$numberregistered++;
|
| 364 |
}
|
| 365 |
return array('guests' => $numberguest, 'members' => $numberregistered);
|
| 366 |
}
|
| 367 |
|
| 368 |
/**
|
| 369 |
* Get counts of new or recent posts for the current user.
|
| 370 |
*/
|
| 371 |
function drupalvb_get_recent_posts($scope = 'last') {
|
| 372 |
global $user;
|
| 373 |
|
| 374 |
// Queries the vB user database to find a matching set of user data.
|
| 375 |
$result = drupalvb_db_query("SELECT userid, username, lastvisit FROM {user} WHERE username = '%s'", drupalvb_htmlspecialchars($user->name));
|
| 376 |
|
| 377 |
// Make sure a user is logged in to get their last visit and appropriate post
|
| 378 |
// count.
|
| 379 |
if ($vb_user = db_fetch_array($result)) {
|
| 380 |
if ($scope == 'last') {
|
| 381 |
$datecut = $vb_user['lastvisit'];
|
| 382 |
}
|
| 383 |
else if ($scope == 'daily') {
|
| 384 |
$datecut = time() - 86400;
|
| 385 |
}
|
| 386 |
$posts = db_result(drupalvb_db_query("SELECT COUNT(postid) FROM {post} WHERE dateline > %d", $datecut));
|
| 387 |
}
|
| 388 |
else {
|
| 389 |
$posts = 0;
|
| 390 |
}
|
| 391 |
return $posts;
|
| 392 |
}
|
| 393 |
|
| 394 |
function drupalvb_htmlspecialchars($text) {
|
| 395 |
$text = preg_replace('/&(?!#[0-9]+|shy;)/si', '&', $text);
|
| 396 |
return str_replace(array('<', '>', '"'), array('<', '>', '"'), $text);
|
| 397 |
}
|
| 398 |
|