smf.plugin.php

Go to the documentation of this file.
00001 <?php
00002 
00016 include_once("embient.plugin.php");
00017 
00024 function embient_create_smf_plugin()
00025 {
00026   return new EmbientSMF();
00027 }
00028 
00040 function embient_smf_encrypt($username, $password)
00041 {
00042   return sha1(strtolower($username) . $password);
00043 }
00044 
00051 function embient_smf_salt()
00052 {
00053   return substr(md5(rand()), 0, 4);
00054 }
00055 
00067 function embient_smf_parse_url($local = false, $global = false)
00068 {
00069   // Parse the URL with PHP to make life easier.
00070   $parsed_url = parse_url($this->conf['boardurl']);
00071 
00072   // Is local cookies off?
00073   if (empty($parsed_url['path']) || !$local)
00074   {
00075     $parsed_url['path'] = '';
00076   }
00077 
00078   // Globalize cookies across domains (filter out IP-addresses)?
00079   if ($global && preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0)
00080   {
00081     // If we can't figure it out, just skip it.
00082     if (preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1)
00083     {
00084       $parsed_url['host'] = '.' . $parts[1];
00085     }
00086   }
00087   else if (!$local) // We shouldn't use a host at all if both options are off.
00088   {
00089     $parsed_url['host'] = '';
00090   }
00091 
00092   return array($parsed_url['host'], $parsed_url['path'] . '/');
00093 }
00094 
00095 
00099 class EmbientSMF extends EmbientPlugin
00100 {
00102   var $conf;
00103 
00105   var $settings;
00106 
00107   // -------------------------
00108 
00112   function EmbientSMF()
00113   {
00114     $this->EmbientPlugin('smf');
00115 
00116     // user field mapping for SMF
00117     $this->_mapping = array
00118     (
00119       'name'      => 'memberName',
00120       'passwd'    => 'passwd',
00121       'mail'      => 'emailAddress',
00122       'signature' => 'signature',
00123       'timezone'  => 'timeOffset',
00124     );
00125   }
00126 
00130   function Init($cfg)
00131   {
00132     @set_magic_quotes_runtime(0);
00133     require_once($cfg['root']['value'] ."/Settings.php");
00134 
00135     // load settings to class's properties
00136     $this->conf['maintenance'] = $maintenance;
00137     $this->conf['mtitle']      = $mtitle;
00138     $this->conf['mmessage']    = $mmessage;
00139 
00140     $this->conf['mbname']          = $mbname;
00141     $this->conf['language']        = $language;
00142     $this->conf['boardurl']        = $boardurl;
00143     $this->conf['webmaster_email'] = $webmaster_email;
00144     $this->conf['cookiename']      = $cookiename;
00145 
00146     $this->conf['db_server']     = $db_server;
00147     $this->conf['db_name']       = $db_name;
00148     $this->conf['db_user']       = $db_user;
00149     $this->conf['db_passwd']     = $db_passwd;
00150     $this->conf['db_prefix']     = $db_prefix;
00151     $this->conf['db_persist']    = $db_persist;
00152     $this->conf['db_error_send'] = $db_error_send;
00153 
00154     $this->conf['boarddir']  = $boarddir;
00155     $this->conf['sourcedir'] = $sourcedir;
00156 
00157     $this->conf['db_last_error'] = $db_last_error;
00158 
00159     // If $maintenance is set to 2, don't connect to the database at all.
00160     if ($this->conf['maintenance'] == 2)
00161     {
00162       embient_error('SMF system is under maintenance, cannot connect to its database', __FILE__, __LINE__);
00163       return false;
00164     }
00165 
00166     // load database params
00167     $db_params = array(
00168                   'db_host'   => $this->conf['db_server'],
00169                   'db_user'   => $this->conf['db_user'],
00170                   'db_passwd' => $this->conf['db_passwd'],
00171                   'db_name'   => $this->conf['db_name'],
00172                   'prefix'    => $this->conf['db_prefix'],
00173                  );
00174 
00175     // connect to database
00176     if ( ! parent::Init($db_params) )
00177     {
00178       return false;
00179     }
00180 
00181     // load settings from database
00182     $query = "SELECT variable, value FROM {settings}";
00183 
00184     if ( ! $this->_db->Query($query, __FILE__, __LINE__) )
00185     {
00186       return false;
00187     }
00188 
00189     $this->settings = array();
00190 
00191     $rows = $this->_db->GetRowsCount();
00192 
00193     for ( $i = 0; $i < $rows; $i++ )
00194     {
00195       $setting = $this->_db->FetchArray();
00196       $this->settings[$setting['variable']] = $setting['value'];
00197     }
00198 
00199     return ! empty($this->settings);
00200   }
00201   
00205   function Login($username)
00206   {
00207     if ( ! $this->_Load($username) )
00208     {
00209       embient_error("User ". $username ." cannot be loaded", __FILE__, __LINE__);
00210     }
00211 
00212     // they've got no salt; fix it!
00213     if ( $this->user['passwordSalt'] == '' )
00214     {
00215       $this->user['passwordSalt'] = embient_smf_salt();
00216       $this->Update($username, $this->user);
00217     }
00218 
00219     // load user groups information
00220         if ( empty($this->user['additionalGroups']) )
00221     {
00222             $this->user['groups'] = array($this->user['ID_GROUP'], $this->user['ID_POST_GROUP']);
00223     }
00224         else
00225     {
00226             $this->user['groups'] = array_merge(
00227                 array($this->user['ID_GROUP'], $this->user['ID_POST_GROUP']),
00228                 explode(',', $this->user['additionalGroups'])
00229             );
00230     }
00231 
00232     // This might be set to "forum default"...
00233     if (empty($this->user['timeFormat']))
00234     {
00235       $this->user['timeFormat'] = $this->settings['time_format'];
00236     }
00237 
00238     // delete previous one
00239     if (isset($_COOKIE[$this->conf['cookiename']]))
00240     {
00241       $array = @unserialize($_COOKIE[$this->conf['cookiename']]);
00242 
00243       // Out with the old, in with the new!
00244       if (isset($array[3]) && $array[3] != $cookie_state)
00245       {
00246         $cookie_url = embient_smf_parse_url($array[3] & 1 > 0, $array[3] & 2 > 0);
00247         setcookie($this->conf['cookiename'], serialize(array(0, '', 0)), time() - 3600, $cookie_url[1], $cookie_url[0], 0);
00248       }
00249     }
00250 
00251     // set new one
00252     $cookie_state  = (empty($this->settings['localCookies']) ? 0 : 1) | (empty($this->settings['globalCookies']) ? 0 : 2);
00253     $cookie_url    = embient_smf_parse_url(!empty($this->settings['localCookies']), !empty($this->settings['globalCookies']));
00254     $cookie_time   = time() + ($this->settings['cookieTime'] * 60);
00255     $cookie_passwd = sha1($this->user['passwd'] . $this->user['passwordSalt']); // encrypt the cookie
00256 
00257     $cookie_data   = serialize(array($this->user['ID_MEMBER'], $cookie_passwd, $cookie_time, $cookie_state));
00258 
00259     setcookie($this->conf['cookiename'], $cookie_data, $cookie_time, $cookie_url[1], $cookie_url[0], 0);
00260     $_COOKIE[$this->conf['cookiename']] = $cookie_data;
00261 
00262     $this->_LogAction("Browsing main site");
00263 
00264     $query = "UPDATE {members} "
00265            .   "SET "
00266            .     "lastLogin = '". time() ."', "
00267            .     "memberIP = IFNULL('". $_SERVER[REMOTE_ADDR] ."', '') "
00268            .   "WHERE ID_MEMBER = '". $this->user['ID_MEMBER'] ."'";
00269 
00270     $this->_db->Query($query, __FILE__, __LINE__);
00271   }
00272 
00276   function Logout($username)
00277   {
00278     // remove cookie
00279     $cookie_data = serialize(array(0, '', 0));
00280     $cookie_url  = embient_smf_parse_url($this->settings['localCookies'], $this->settings['globalCookies']);
00281 
00282     setcookie($this->conf['cookiename'], $cookie_data, time() - 3600, $cookie_url[1], $cookie_url[0], 0);
00283     $_COOKIE[$this->conf['cookiename']] = $cookie_data;
00284 
00285     // delete session info in database
00286     $query = "DELETE FROM {sessions} "
00287            . "WHERE session_id = '". $_COOKIE[ini_get('session.name')] ."';";
00288 
00289     $this->_db->Query($query, __FILE__, __LINE__);
00290 
00291     // clear action
00292     $this->_LogAction();
00293 
00294     // clear user info
00295     $this->user = array();
00296   }
00297 
00301   function Add($user)
00302   {
00303     // initialise the user info
00304     $this->user = Array();
00305     $this->_ConvertUserInfo($user);
00306 
00307     // encrypt password
00308     $this->user['passwd'] = embient_smf_encrypt($this->user['memberName'], $this->user['passwd']);
00309 
00310     // format query
00311     $val = '';
00312     foreach( $this->user as $v)
00313     {
00314       $val = $val.($val != '' ? ', ' : '')."'$v'";
00315     }    
00316 
00317     $query = "INSERT INTO {members} "
00318                  . "(" . implode(', ', array_keys($this->user)) . ") "
00319            . "VALUES (". $val .')';
00320 
00321     $this->_db->Query($query, __FILE__, __LINE__);
00322   }
00323 
00327   function Update($username, $user)
00328   {
00329     // get database key for this user
00330     if ( ! $this->_Load($username) )
00331     {
00332       return;
00333     }
00334 
00335     $uid = $this->user['ID_MEMBER'];
00336 
00337     // if new user name or password is supplied, re-encrypt the password
00338     $newpass = '';
00339     if ( $user['name'] != $username || ! empty($user['passwd']) )
00340     {
00341       $newpass = embient_smf_encrypt($user['name'], $user['passwd']);
00342     }
00343 
00344     // load value
00345     $this->user = Array();                 // clear buffer
00346     $this->_ConvertUserInfo($user, false); // not load default
00347 
00348     // load new encrpyted password, if available
00349     if ( ! empty($newpass) )
00350     {
00351       $this->user['passwd'] = $newpass;
00352     }
00353 
00354     // create query
00355     $fields = array();
00356 
00357     foreach ($this->user as $key => $val)
00358     {
00359       array_push($fields, "$key = '$val'");
00360     }
00361 
00362     $query = "UPDATE {members} "
00363            . "SET "
00364            . implode(', ', $fields) ." "
00365            . "WHERE ID_MEMBER = '". $uid ."'";
00366 
00367     $this->_db->Query($query, __FILE__, __LINE__);
00368   }
00369 
00373   function Delete($username)
00374   {
00375     // get database key for this user
00376     if ( ! $this->_Load($username) )
00377     {
00378       return;
00379     }
00380 
00381     $uid = $this->user['ID_MEMBER'];
00382 
00383     // ---------------------------------------------------
00384     // following codes are converted from Subs-Members.php
00385 
00386     // Make these peoples' posts guest posts.
00387     $query =  "UPDATE {messages} "
00388            .  "SET ID_MEMBER = 0, posterEmail = '' "
00389            .    "WHERE ID_MEMBER = '$uid'";
00390 
00391     $this->_db->Query($query, __FILE__, __LINE__);
00392 
00393     $query = "UPDATE {polls} "
00394            . "SET ID_MEMBER = 0 "
00395            . "WHERE ID_MEMBER = '$uid'";
00396 
00397     $this->_db->Query($query, __FILE__, __LINE__);
00398 
00399     // Make these peoples' posts guest first posts and last posts.
00400     $query = "UPDATE {topics} "
00401            . "SET ID_MEMBER_STARTED = 0 "
00402            . "WHERE ID_MEMBER_STARTED = '$uid'";
00403 
00404     $this->_db->Query($query, __FILE__, __LINE__);
00405 
00406     $query = "UPDATE {topics} "
00407                . "SET ID_MEMBER_UPDATED = 0 "
00408                . "WHERE ID_MEMBER_UPDATED = '$uid'";
00409 
00410     $this->_db->Query($query, __FILE__, __LINE__);
00411 
00412     $query = "UPDATE {log_actions} "
00413            . "SET ID_MEMBER = 0 "
00414            . "WHERE ID_MEMBER = '$uid'";
00415 
00416     $this->_db->Query($query, __FILE__, __LINE__);
00417 
00418     $query = "UPDATE {log_banned} "
00419            . "SET ID_MEMBER = 0 "
00420            . "WHERE ID_MEMBER = '$uid'";
00421 
00422     $this->_db->Query($query, __FILE__, __LINE__);
00423 
00424     $query = "UPDATE {log_errors} "
00425            . "SET ID_MEMBER = 0 "
00426            . "WHERE ID_MEMBER = '$uid'";
00427 
00428     // Delete the logs...
00429     $query = "DELETE FROM {log_boards} "
00430            . "WHERE ID_MEMBER = '$uid'";
00431 
00432     $this->_db->Query($query, __FILE__, __LINE__);
00433 
00434     $query = "DELETE FROM {log_karma} "
00435            . "WHERE ID_TARGET = '$uid' OR ID_EXECUTOR = '$uid'";
00436 
00437     $this->_db->Query($query, __FILE__, __LINE__);
00438 
00439     $query = "DELETE FROM {log_mark_read} "
00440            . "WHERE ID_MEMBER = '$uid'";
00441 
00442     $this->_db->Query($query, __FILE__, __LINE__);
00443 
00444     $query = "DELETE FROM {log_notify} "
00445            . "WHERE ID_MEMBER = '$uid'";
00446 
00447     $this->_db->Query($query, __FILE__, __LINE__);
00448 
00449     $query = "DELETE FROM {log_online} "
00450            . "WHERE ID_MEMBER = '$uid'";
00451 
00452     $this->_db->Query($query, __FILE__, __LINE__);
00453 
00454     $query = "DELETE FROM {log_polls} "
00455            . "WHERE ID_MEMBER = '$uid'";
00456 
00457     $this->_db->Query($query, __FILE__, __LINE__);
00458 
00459     $query = "DELETE FROM {log_topics} "
00460            . "WHERE ID_MEMBER = '$uid'";
00461 
00462     $this->_db->Query($query, __FILE__, __LINE__);
00463 
00464     $query = "DELETE FROM {collapsed_categories} "
00465            . "WHERE ID_MEMBER = '$uid'";
00466 
00467     // It's over, no more moderation for you.
00468     $query = "DELETE FROM {moderators} "
00469            . "WHERE ID_MEMBER = '$uid'";
00470 
00471     $this->_db->Query($query, __FILE__, __LINE__);
00472 
00473     // If you don't exist we can't ban you.
00474     $query = "DELETE FROM {ban_items} "
00475            . "WHERE ID_MEMBER = '$uid'";
00476 
00477     $this->_db->Query($query, __FILE__, __LINE__);
00478 
00479     // Remove individual theme settings.
00480     $query = "DELETE FROM {themes} "
00481            . "WHERE ID_MEMBER = '$uid'";
00482 
00483     $this->_db->Query($query, __FILE__, __LINE__);
00484 
00485     // These users are nobody's buddy nomore.
00486     $query = "SELECT ID_MEMBER, pm_ignore_list, buddy_list "
00487            . "FROM {members} "
00488            . "WHERE FIND_IN_SET('$uid', pm_ignore_list) OR FIND_IN_SET('$uid', buddy_list)";
00489 
00490     $this->_db->Query($query, __FILE__, __LINE__);
00491 
00492     while ( $row = $this->_db->FetchRow() )
00493     {
00494       $query = "UPDATE {members} "
00495              . "SET "
00496              . " pm_ignore_list = '". implode(',', array_diff(explode(',', $row[1]), array($uid))) ."', "
00497              . " buddy_list = '". implode(',', array_diff(explode(',', $row[0]), array($uid))) ."' "
00498              . "WHERE ID_MEMBER = $row[0] LIMIT 1";
00499 
00500       $this->_db->Query($query, __FILE__, __LINE__);
00501     }
00502 
00503     // end of codes, converted from Subs-Members.php
00504     // ---------------------------------------------------
00505 
00506     // update the personal message stuff
00507 
00508     // Calculate the number of messages to be deducted from 
00509     // the field "instanceMessages" of existing users
00510     $query = "SELECT t2.ID_MEMBER, COUNT(t2.ID_MEMBER) AS delcount "
00511            . "FROM smf_personal_messages AS t1, smf_pm_recipients AS t2 "
00512            . "WHERE t1.ID_MEMBER_FROM = '$uid' "
00513            . "   AND t2.ID_PM = t1.ID_PM "
00514            . "   AND t2.deleted = 0 "
00515            . "GROUP BY t2.ID_MEMBER";
00516     
00517     $this->_db->Query($query, __FILE__, __LINE__);
00518 
00519     while ( $row = $this->_db->FetchArray() )
00520     {
00521       $query = "UPDATE {members} "
00522              . "SET instantMessages = instanceMessages - ". $row['delcount'] ." "
00523              . "WHERE instanceMessages > 0 AND "
00524              . "  ID_MEMBER = ". $row['ID_MEMBER'];
00525 
00526       $this->_db_Query($query, __FILE__, __LINE__);
00527     }
00528 
00529     $query = "SELECT t2.ID_MEMBER, COUNT(t2.ID_MEMBER) AS readcount "
00530            . "FROM smf_personal_messages AS t1, smf_pm_recipients AS t2 "
00531            . "WHERE t1.ID_MEMBER_FROM = '$uid' "
00532            . "     AND t2.ID_PM = t1.ID_PM "
00533            . "     AND t2.deleted = 0 "
00534            . "     AND t2.is_read = 0 "
00535            . "GROUP BY t2.ID_MEMBER";
00536 
00537     $this->_db->Query($query, __FILE__, __LINE__);
00538 
00539     while ( $row = $this->_db->FetchArray() )
00540     {
00541       $query = "UPDATE {members} "
00542              . "SET instantMessages = unreadMessages - ". $row['readcount'] ." "
00543              . "WHERE unreadMessages > 0 AND "
00544              . "  ID_MEMBER = ". $row['ID_MEMBER'];
00545 
00546       $this->_db_Query($query, __FILE__, __LINE__);
00547     }
00548 
00549         // Do the actual deletion.
00550     $query = "DELETE FROM {pm_recipients} "
00551            . "WHERE ID_PM IN (SELECT ID_PM "
00552            . "                      FROM smf_personal_messages "
00553            . "                      WHERE ID_MEMBER_FROM = '$uid')";
00554 
00555     $this->_db->Query($query, __FILE__, __LINE__);
00556 
00557     $query = "DELETE FROM {personal_messages} "
00558            . "WHERE ID_MEMBER_FROM = '$uid'";
00559 
00560     $this->_db->Query($query, __FILE__, __LINE__);
00561 
00562     // Finally, delete member itself
00563     $query = "DELETE FROM {members} "
00564            . "WHERE ID_MEMBER = '$uid' "
00565            . "LIMIT 1";
00566 
00567     $this->_db->Query($query, __FILE__, __LINE__);
00568   }
00569 
00570   // -------------------------
00571 
00579   function _LogAction($action = NULL)
00580   {
00581     if ( $this->_db->connection == false || ! $this->user )
00582     {
00583       return false;
00584     }
00585 
00586     $query = "DELETE FROM {log_online} "
00587            . "WHERE "
00588            .   "logTime < NOW() - INTERVAL ". $this->settings['lastActive'] ." SECOND "
00589            .   "OR ID_MEMBER = '". $this->user['ID_MEMBER'] ."' "
00590            .   "OR session = '" . @session_id() . "'";
00591 
00592     $this->_db->Query($query, __FILE__, __LINE__);
00593 
00594     if ($action == NULL)
00595     {
00596       return;
00597     }
00598 
00599     $serialized = $_GET;
00600     $serialized['action']     = $action;
00601     $serialized['USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
00602 
00603     unset($serialized['sesc']);
00604 
00605     $serialized = addslashes(serialize($serialized));
00606 
00607     $query = "INSERT IGNORE INTO {log_online} (session, ID_MEMBER, ip, url) "
00608            . "VALUES ("
00609            .   "'". @session_id() . "', "
00610            .   "'". $this->user['ID_MEMBER'] ."', "
00611            .   "IFNULL(INET_ATON('". $_SERVER[REMOTE_ADDR] ."'), 0), "
00612            .   "'$serialized'"
00613            . ")";
00614 
00615     $this->_db->Query($query, __FILE__, __LINE__);
00616   }
00617 
00618   // -------------------------
00619 
00624   function _Load($username)
00625   {
00626     if ( $this->_db->connection == false )
00627     {
00628       embient_error("SMF Database is not connected", __FILE__, __LINE__);
00629       return false;
00630     }
00631 
00632     // clear current information
00633     $this->user = array();
00634 
00635     $query ="SELECT * FROM {members} WHERE memberName = '$username' LIMIT 1";
00636 
00637     if ( ! $this->_db->Query($query, __FILE__, __LINE__) )
00638     {
00639       return false;
00640     }
00641 
00642     if ( $this->_db->GetRowsCount() <= 0 )
00643     {
00644       embient_error("User [$username] could not be found in SMF database.", __FILE__, __LINE__);
00645       return false;
00646     }
00647 
00648     // fetch info
00649     $this->user = $this->_db->FetchArray();
00650 
00651     // make it SQL-safe
00652     foreach ($this->user as $key => $val)
00653     {
00654       $this->user[$key] = $val;
00655     }
00656 
00657     return true;
00658   }
00659 
00664   function _ConvertUserInfo($user, $default = true)
00665   {
00666 
00667     // -----------------------
00668     // convert Embient info to SMF info
00669     parent::_ConvertUserInfo($user, $default);
00670 
00671     // -----------------------
00672     // Postprocessing
00673 
00674     // convert Embient time zone to SMF timezone
00675     if ( ! empty($this->user['timeOffset']) )
00676     {
00677       $this->user['timeOffset'] = $this->user['timeOffset'] / 3600;
00678     }
00679 
00680     // loading real name with first and last name first
00681     if ( ! empty($user['firstname']) || ! empty($user['firstname']) )
00682     {
00683       $this->user['realName'] = trim($user['firstname'] .' '. $user['lastname']);
00684     }
00685 
00686     // -----------------------
00687     // load default value
00688     if ( $default )
00689     {
00690       // This might be set to "forum default"...
00691       if (empty($this->user['timeFormat']))
00692       {
00693         $this->user['timeFormat'] = $this->settings['time_format'];
00694       }
00695 
00696       $this->user['realName']        = embient_load_with_default( trim($this->user['realName']), $this->user['memberName'] );
00697       $this->user['memberIP']        = $_SERVER[REMOTE_ADDR];
00698       $this->user['hideEmail']       = embient_load_with_default( $this->user['guest_hideContacts'], $this->settings['guest_hideContacts'] );
00699       $this->user['passwordSalt']    = embient_load_with_default( $this->user['passwordSalt']   , embient_smf_salt() );
00700       $this->user['posts']           = embient_load_with_default( $this->user['posts']          , "0"                );
00701       $this->user['dateRegistered']  = embient_load_with_default( $this->user['dateRegistered'] , time()             );
00702       $this->user['validation_code'] = embient_load_with_default( $this->user['validation_code'], ''                 );
00703       $this->user['personalText']    = embient_load_with_default( $this->user['personalText']   , ''                 );
00704       $this->user['pm_email_notify'] = embient_load_with_default( $this->user['pm_email_notify'], 1                  );
00705       $this->user['ID_THEME']        = embient_load_with_default( $this->user['ID_THEME']       , 0                  );
00706       $this->user['ID_POST_GROUP']   = embient_load_with_default( $this->user['ID_POST_GROUP']  , 4                  );
00707     }
00708   }
00709 }

Generated on Fri Feb 10 15:05:54 2006 for Embient by  doxygen 1.4.6-NO