StandAlone SMF Api Integration

I’ve been using SMF in combination with my personal sites for years now, I like how fast it is and how easy it is to manage.
But one thing SMF lacks is a good API with most off all, documentation.

 

In this blog post I’ll show what changes(additions) need to be made so that we can create and manage topics and messages.
This post goes together with my next post that uses this API in CakePHP.

 

SMF has a small API that has the following function:

  • smf_setLoginCookie
  • smf_authenticateUser
  • smf_registerMember
  • smf_logOnline
  • smf_isOnline
  • smf_logError
  • smf_formatTime
  • smf_query
  • smf_allowedTo
  • smf_loadThemeData
  • smf_loadSession

The advantage of having these function in a separate file is that you do not need to touch the SMF core.
The file is a good start, but does not really have that much functionality.

 

What I needed was the following:

  • When someone logs on in the site, that person needs to be logged on in SMF
  • When the user logs out, log out the SMF session as well
  • When creating a post on the site’s homepage, make this a topic in the ‘News’ board on the forum.
  • When updating a post on the site, also modify it on the forum
  • On deleting a post from the site, also delete the topic from the forum
  • Show the number of comments on a topic on the site’s homepage
  • Change the password on the forum when using the ‘change password’ or ‘forgot password’ feature.
  • Register an account on SMF when the user registers on the site

 

So lets start adding the extra functionality!

 

The API version that this was done in is 1.1.6. Right now 1.1.11 is available but the steps should still be the same.

If some one can verify it works with that version please let me know so I can update this post.

 

The SMF API file can be downloaded from the simplemachines.org website.

The modified version(so my version) can be downloaded here:
http://file.crazytje.be/smf.txt

 

I made modifications to the register and logon functions(they didn’t work for me) and added these functions:

  • smf_postNewsTopic
  • smf_editNewsTopic
  • smf_getTopicMessageCount
  • smf_userExists
  • smf_changePassword
  • smf_getUserPassword

smf_postNewsTopic

What this function does is add a new topic in the board you specify.

Not much explanation needed, the queries explain themselves.

 

function smf_postNewsTopic($pSMFUserInfo, $pTopic, $pMessage, $pBoardID) {
    global $smf_user_info, $smf_settings;
 
    $smf_user_info = $pSMFUserInfo;
    $pTopic = addslashes($pTopic);
 
    $pMessage = addslashes($pMessage);
 
    smf_query("INSERT INTO $smf_settings[db_prefix]messages(ID_BOARD, ID_TOPIC, ID_MEMBER, subject, body, posterName, posterEmail, posterTime, posterIP, smileysEnabled, modifiedName, icon) VALUES ($pBoardID, '', $smf_user_info[ID_MEMBER], SUBSTRING('$pTopic', 1, 255), SUBSTRING('$pMessage', 1, 65534), SUBSTRING('$smf_user_info[memberName]', 1, 255), SUBSTRING('$smf_user_info[emailAddress]', 1, 255), " . time() . ", SUBSTRING('$_SERVER[REMOTE_ADDR]', 1, 255), " . 1 . ", '', SUBSTRING('xx', 1, 16))", __FILE__, __LINE__);
 
    $post_id = smf_insert_id();
 
    smf_query("INSERT INTO $smf_settings[db_prefix]topics (ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG) VALUES ($pBoardID, $smf_user_info[ID_MEMBER],  $smf_user_info[ID_MEMBER], $post_id, $post_id)", __FILE__, __LINE__);
 
    $topic_id = smf_insert_id();
 
    smf_query("UPDATE $smf_settings[db_prefix]messages SET ID_TOPIC = $topic_id WHERE ID_MSG = $post_id LIMIT 1", __FILE__, __LINE__);
    smf_query("UPDATE $smf_settings[db_prefix]boards SET numPosts = numPosts + 1 , numTopics = numTopics + 1 WHERE ID_BOARD = $pBoardID LIMIT 1;", __FILE__, __LINE__);
    smf_query("UPDATE $smf_settings[db_prefix]boards SET ID_LAST_MSG = $post_id, ID_MSG_UPDATED = $post_id WHERE ID_BOARD = $pBoardID LIMIT 1;", __FILE__, __LINE__);
    smf_query("UPDATE $smf_settings[db_prefix]messages SET ID_MSG_MODIFIED = $post_id WHERE ID_MSG = $post_id;", __FILE__, __LINE__);
    smf_query("UPDATE $smf_settings[db_prefix]settings SET value='$post_id' WHERE variable = 'maxMsgID' LIMIT 1;", __FILE__, __LINE__);
 
    return $topic_id;
}

smf_editNewsTopic

We have a topic that we want to modify the first post from. This is a one line query.

    function smf_editNewsTopic($pSMFUserInfo, $pTopicID, $pNewSubject, $pNewMessage) {
        global $smf_settings;
 
        $pNewSubject = addslashes($pNewSubject);
        $pNewMessage = addslashes($pNewMessage);
 
        smf_query("UPDATE $smf_settings[db_prefix]messages SET subject='$pNewSubject', body='$pNewMessage' WHERE ID_MSG = (SELECT ID_FIRST_MSG FROM $smf_settings[db_prefix]topics WHERE ID_TOPIC = $pTopicID);", __FILE__, __LINE__);
 
        return true;
    }

smf_getTopicMessageCount

 

function smf_getTopicMessageCount($pTopicID) {
    global $smf_settings;
    $query = "SELECT ID_MSG FROM $smf_settings[db_prefix]messages WHERE ID_TOPIC='$pTopicID';";
    $res = smf_query($query, __FILE__, __LINE__);
    return mysql_num_rows($res);
}

smf_userExists

This simply checks if a user exists:

function smf_userExists($pUserName) {
    $pUserName = addslashes($pUserName);
 
    // This should come from Settings.php, hopefully.
    global $smf_connection, $smf_settings;
 
    $result = smf_query("SELECT ID_MEMBER FROM $smf_settings[db_prefix]members WHERE memberName = $pUserName' LIMIT 1", _FILE__, __LINE__);
    $count = mysql_num_rows($result);
 
    if($count > 0) { return true; }
    return false;
}

smf_changePassword

On changing the password on the site, also change it in SMF, also a 1 line query.

function smf_changePassword($pUserName, $pNewPassword) {
    $pUserName = addslashes($pUserName);
    $hash = sha1(strtolower($pUserName) . $pNewPassword);
 
    global $smf_connection, $smf_settings;
    smf_query("UPDATE $smf_settings[db_prefix]members SET passwd = '$hash' WHERE memberName = '$pUserName'", __FILE__, __LINE__);
}

smf_getUserPassword

Because I do not keep passwords in the database on my site, I want to be able to log-in the users without passing the SMF password.
This gets the(hashed) ‘passwd’ field, to get the real password you’ll still have to do “sha1($passwd.$salt);”.

function smf_getUserPassword($pUserName) {
    // This should come from Settings.php, hopefully.
    global $smf_connection, $smf_settings;
 
    if (!$smf_connection) { return false; }
    if (is_integer($pUserName)) {
        $result = smf_query("SELECT memberName FROM $smf_settings[db_prefix]members WHERE ID_MEMBER='$pUserName' LIMIT 1", __FILE__, __LINE__);
        list ($username) = mysql_fetch_row($result);
        mysql_free_result($result);
        $pUserName = $username;
    }
 
    // Save for later use.
    $result = smf_query("SELECT passwd, passwordSalt FROM $smf_settings[db_prefix]members WHERE memberName = '$pUserName' LIMIT 1", __FILE__, __LINE__);
    list ($password, $salt) = mysql_fetch_row($result);
 
    mysql_free_result($result);
 
    $data = array();
    $data['passwd'] = $password;
    $data['salt'] = $salt;
    return $data;
}

These functions all belong in smf_api.php.
To easily use integrate this in your own site, add the following to your code before calling the smf functions:

define('SMFSettingsPath', 'path/to/smf/Settings/dir');
if (!defined('SMFSettingsPath')) {
    // Hopefully the forum is in the same place as this script.
    require_once(dirname(__FILE__) . '/Settings.php');
} else {
    //Define this in your own script!, makes it easier to manage
    require_once(SMFSettingsPath);
}

Before you include the script, define the ‘SMFSettingsPath’, this is the path to your Settings.php file.
By doing this, you are not obligated to put this file in your forum, it can be kept with the site where you’ll actually use the functionality.

Click here for part 2: “Integrating SMF with CakePHP”

Leave a Reply