Documentation
1.4. Using phpBB3's Basic Functions
$Id: v3_api.xml 52 2007-12-09 19:45:45Z jelly_doughnut $
Copyright © 2007 phpBB Group
Abstract
This section describes the most important classes and methods in phpBB3. Database related functions are explained in the DBAL chapter.
This chapter will introduce the core functions of phpBB3. Read this carefully, as the use of these functions is an integral part of the MOD DB Requirements.
1.4.1. User input
request_var($var_name, $default, $multibyte = false, $cookie = false)
PhpBB3 introduces a new way for reading variables from the request: therequest_var function. The function ensures that the read variable is of the right type and applies the appropriate treatment to ensure a secure use. So, instead of using the old php arrays like $HTTP_POST_VARS and $HTTP_GET_VARS, the function request_var should be used. It is permissible to use -- for instance -- $_POST to check whatever or not a var was submitted by a given method, but such parameters should never be assigned directly. Every string returned is already stripslashed (if needed) and htmlspecialchars run on it.
Important
request_var is the only allowed way to read parameters with their values. Using POST/GET to check for the existence of a variable is allowed, like this: $submit = (isset($_POST['submit']) ? true : false;
So, let's have a look at it, shall we?
function request_var($var_name, $default, $multibyte = false, $cookie = false)
$var_name The name of the passed variable, as used in the corresponding HTML form.
$default The default value, should there be no such variable in the request. Also - maybe more importantly - determines the type of the returned variable.
$multibyte Optional. Set this, if the input may contain not-ASCII characters; should be used for almost all strings.
$cookie Optional. Set this, if the variable might be passed via the cookie.
The most important parameter is $default, as it determines the treatment given to the passed variable. If $default is an integer, the result will be cast to int. If it's a string, the result will be run through htmlspecialchars, and so on. Note that arrays always default to the empty array.
// Reads the variable 'int_test'. The variable will be cast to int. If there is no such variable 0 will be returned.
$int_test = request_var('int_test', 0);
// Reads the variable 'string_test'. The variable will be run through htmplspecialchars. If there is no such variable, then 'test' will be returned.
$string_test = request_var('string_test', 'test');
// Reads the variable 'int_array_test'. The entries will be cast to int. If there are no such variables, then an empty array will be returned
$int_array_test = request_var('int_array_test', array(0));
// Reads the variable 'int_string_array_test'. The keys will be cast to int, the values run through htmlspecialchars.
// If there are no such variables, then an empty array will be returned.
$int_string_array_test = request_var('int_string_array_test', array(0 => ''));
...
1.4.2. Preserving sessions
append_sid($url, $params = false, $is_amp = true, $session_id = false)
PhpBB will try to use cookies to track sessions, but as this is not always possible, there's url-rewriting as backup. To allow this system to work, there's one simple requirement: all links in forum pages need to be passed through the function append_sid.
1.4.3. Redirecting users
meta_refresh($time, $url)
To redirect other users to other pages, for instance after a performed action, use the meta_refresh function. The first parameter is the time in seconds until redirection, the second is the url to redirect to. Remember to use append_sid when redirecting to another forum page.
$meta_info = append_sid("{$phpbb_root_path}api_example.$phpEx");
meta_refresh(3, $meta_info);
1.4.4. The User Class
This class is the main toolbox to check and alter the current user's information. The user class extends the session class. The instance holding the data for the current user is named $user. The very basic use is setting up a user's session at the beginning of a page, which is done like this:
$user->session_begin(); $auth->acl($user->data); $user->setup(); ...
Let's see what kind of information can be accessed via the user Object. This has the objective of showing what's there, without explaining every last bit or any claim to completeness.
lang The array holding all defined language entries for the user. You can add more language files with the
add_langmethod or by using the lang parameter ofsetup.page Information about the current location. Always take this information with a grain of salt, as it might not be totally correct. Also, using these might pose a security risk, so be careful.
page_name The current page's name.
page_dir The path from phpbb_root_path.
query_string
script_path
root_script_path
page The current page with query string.
data The actual data and settings of the user.
user_id
user_type
group_id The user's default group.
user_ip
user_regdate
username
username_clean The all lower-case normalized version of the username for comparisons.
user_email
user_email_hash
user_birthday
user_lastvisit
user_lastmark
user_lastpost_time
user_lastpage
user_last_confirm_key security-relevant
user_last_search
user_warnings
user_last_warning
user_login_attempts
user_inactive_reason
user_inactive_time
user_posts
user_lang
user_timezone
user_dateformat
user_style
user_rank
user_colour
user_message_rules
user_full_folder
user_emailtime
user_topic_show_days, user_topic_sortby_type, user_topic_sortby_dir, user_post_show_days, user_post_sortby_type, user_post_sortby_dir Preferences for reading
user_notify
user_notify_pm
user_notify_type
user_allow_pm
user_allow_viewonline
user_allow_viewemail
user_allow_massemail
user_options
user_avatar
user_avatar_type
user_avatar_width
user_avatar_height
user_sig
user_sig_bbcode_uid and user_sig_bbcode_bitfield Needed to render the signature.
user_from
user_icq
user_aim
user_yim
user_msnm
user_jabber
user_website
user_occ
user_interests
user_actkey
user_newpasswd
is_registered
is_bot
session_admin
session_page
browser The user agent string.
host
session_id
ip
time_now
update_session_page
And now to a few selected methods
setup
function setup($lang_set = false, $style = false)The setup method is used for the initial preparation of the user object. Both its parameters are optional. lang_set can be used to add additional language files and expects either the name of a language file or an array of such names. Style can hold a style ID number.add_lang
function add_lang($lang_set)Add_lang is used to load additional language files dynamically. It expects either a filename or an array of filenames. Never use the second and the third parameter.
See the Source Code documentation for session.php to learn further details about the user class.
1.4.5. Validating input
validate_data($data, $val_ary)
functions_user offers a powerful set of functions to validate input, mostly designed for user profiles. It expects an array holding the values and another one holding the test parameters and returns an array of error messages - which will be empty if everything is fine
Here a simple example for checking the password change of an user. Note that the array keys in both arrays match and that several entries can be defined for a single key by using an array of checks. Also note that the error strings might be undefined if you use nonstandard key names.
$data = array(
'user_password' => request_var('user_password', '', true),
'password_confirm' => request_var('password_confirm', '', true),
);
$check_ary = array(
'user_password' => array(
array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
array('password')),
'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
);
$error = validate_data($data, $check_ary);
For instance, array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), means: use the check for strings, use "true" as the first parameter, $config['min_pass_chars'] for the second and $config['max_pass_chars'] as the third. validate_data knows the following input formats:
string Basic checks for strings
optional boolean. If true, empty will be accepted. Defaults to false.
max int. Minimal length.
max int. Maximal length
num Basic checks for numbers.
optional boolean. If true, empty will be accepted. Defaults to false.
max number. Minimal value. Defaults to 0.
max number. Maximal value. Defaults to 1E99
match Checks two values for equality
optional boolean. If true, empty will be accepted. Defaults to false.
match The other value
username Usernames. Uses the current ban data, settings, and taken usernames.
allowed_username One username which will be accepted regardless of the configuration. Defaults to the current user's username.
email email Addresses. Uses the current ban data, settings and used emails.
allowed_email One address which will be accepted regardless of the configuration. Defaults to the current user's email.
match Checks value against a regular expression
optional boolean. If true, empty will be accepted. Defaults to false.
match The Perl-compatible regular expression
Important
You might need to apply more than one check on a submitted value.
1.4.6. Checking authorisation
acl_get($opt, $f = 0)
To use the auth system, you will first have to set the current user's permissions. This is done with the acl method of the $auth object. $auth->acl($user->data);. This will only work after the user's session was initialised.
Permissions are grouped into different types. These are a_ for admin permissions, u_ for user permissions and f_ for forum permissions. Admin permissions and User permissions are generally global, meaning that they do apply under all circumstances. Moderator permissions can be local or global, forum permissions are always local. Local in this regard means that they do only apply for certain fora, and not the board as a whole - moderator permissions are a typical example.
To check a permission for the current user, use the acl_get method of the $auth object. It takes the name of the permission as argument, and returns either true or false. For local permissions, the forum ID has to be supplied as second argument. If you want to check more than one permission at once, use the acl_gets method.
Tip
Permissions can be negated by prefixing them with '!'.
// checking one global permissions.
if (!$auth->acl_get('a_groups'))
// checking two local permissions.
if (!$auth->acl_gets('f_list', 'f_read', $forum_id))
1.4.7. Inserting Posts and Private Messages
generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false)
submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true)
function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
Let's start with the basic feat of preparing the data to be inserted into a post or PM - for that matter any data that should be able to use BBCODES. phpBB3 offers a convenient function to prepare text for such tasks: generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false). Use this function for both the subject and the message you want to post/pm, after running them through utf8_normalize_nfc.
// note that multibyte support is enabled here
$my_text = utf8_normalize_nfc(request_var('text', '', true));
// variables to hold the parameters for submit_post
$uid = $bitfield = $options = '';
generate_text_for_storage($my_text, $uid, $bitfield, $options, true, true, true);
Tip
There is also a function generate_text_for_display, which will create HTML from prepared messages.
We'll ignore polls and attachments in this section, as those are simply beyond the scope of this text. phpBB3 offers powerful methods to insert posts and PMs, however their use is not entirely trivial. We'll limit this introduction to the very basic features.
Let's start with inserting posts. This is the signature of the submit_post function, used to add new posts: submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true). Use the value 'post' for the $mode parameter; subject and username (for guest posters) are straightforward, just insert the desired subject and username. $topic_type refers to the topic types (sticky etc., as described in constants.php). We won't cover polls; for the being just use 'false' for $poll. The interesting and important parameter is $data. $data is an array, containing the actual entries for the post . Most of these are very simple, but a few entries need to be prepared with the aforementioned generate_text_for_storage method. Use the following entries, there are more, but these will be enough to insert a message:
forum_idint. The forum ID. Can be empty for global announcements, otherwise use the forum where the post should be posted in.
icon_id The icon to display.
enable_bbcode boolean.
enable_urls boolean.
enable_sigboolean.
message The message text proper, has to be prepared with generate_text_for_storage
message_md5Use md5() after running generate_text_for_storage over the message to obtain this value
md5($my_message)bbcode_bitfield Use the bitfield supplied by generate_text_for_storage
bbcode_uid string. Use the value supplied by generate_text_for_storage
post_edit_lockedint
enable_sigboolean
topic_time_limit
post_edit_lockedint, corresponds to the ITEM_LOCKED/ITEM_UNLOCKED constants
topic_titleString
notify_setboolean
notifyboolean
post_timeint. Just use '0' for now
forum_nameString. Only used for notify mails
enable_indexingboolean.
Tip
The submit_post function will always use the current $user object as poster.
A little example to show this in action Example 1.6, “Example API submit_post()”:
Example 1.6. Example API submit_post()
// note that multibyte support is enabled here
$my_subject = utf8_normalize_nfc(request_var('my_subject', '', true));
$my_text = utf8_normalize_nfc(request_var('my_text', '', true));
// variables to hold the parameters for submit_post
$poll = $uid = $bitfield = $options = '';
generate_text_for_storage($my_subject, $uid, $bitfield, $options, false, false, false);
generate_text_for_storage($my_text, $uid, $bitfield, $options, true, true, true);
$data = array(
'forum_id' => 2,
'icon_id' => false,
'enable_bbcode' => true,
'enable_smilies' => true,
'enable_urls' => true,
'enable_sig' => true,
'message' => $my_text,
'message_md5' => md5($my_text),
'bbcode_bitfield' => $bitfield,
'bbcode_uid' => $uid,
'post_edit_locked' => 0,
'topic_title' => $my_subject,
'notify_set' => false,
'notify' => false,
'post_time' => 0,
'forum_name' => '',
'enable_indexing' => true,
);
submit_post('post', $my_subject, '', POST_NORMAL, $poll, $data);
The function for PMs behaves very much the same way. This is the signature of the submit_pm function, used to add new posts: function submit_pm($mode, $subject, &$data, $put_in_outbox = true). Use the value 'post' for the $mode parameter; subject is just that. As with posts, data is the important piece. Use the following entries:
address_listarray. This value holds the recipients. It's a nested array of the following structure
array ('u' => array(2 => 'to' 3 => ' bcc'), ('g' => array(2 => 'to' 3 => ' bcc')))Meaning, the first level array has two subarrays: 'u' for users and 'g' for groups. Each of these hold arrays mapping the recipients user_id to the type of recipient he is ('to' or 'bcc').from_user_idint. The sender's user ID
from_user_nameString. The sender's username.
icon_id The icon to use.
from_user_ip
enable_bbcode boolean.
enable_smilies boolean.
enable_urls boolean
enable_sigboolean
messageThe message text proper. Remember to run this through
bbcode_bitfieldUse message_parser to obtain this value
bbcode_uidUse message_parser to obtain this value
// note that multibyte support is enabled here
$my_subject = utf8_normalize_nfc(request_var('my_subject', '', true));
$my_text = utf8_normalize_nfc(request_var('my_text', '', true));
// variables to hold the parameters for submit_pm
$poll = $uid = $bitfield = $options = '';
generate_text_for_storage($my_subject, $uid, $bitfield, $options, false, false, false);
generate_text_for_storage($my_text, $uid, $bitfield, $options, true, true, true);
$data = array(
'address_list' => array ('u' => array(2 => 'to')),
'from_user_id' => 2,
'from_username' => 'test',
'icon_id' => 0,
'from_user_ip' => $user->data['user_ip'],
'enable_bbcode' => true,
'enable_smilies' => true,
'enable_urls' => true,
'enable_sig' => true,
'message' => $my_text,
'bbcode_bitfield' => $bitfield,
'bbcode_uid' => $uid,
);
submit_pm('post', $my_subject, $data, false);
Tip
To use submit_post you have to include functions_posting, to use submit_pm functions_privmsgs.
1.4.8. Building URLs, hidden fields and other HTML
build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false)
build_url()
phpBB3 offers a few functions to take care of the dirty deed of untemplated HTML. The important entries in the category are build_hidden_fields and build_url. Neither is doing anything unexpected, but here we go: build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false). The function will use the entries of the first parameter (array, name value) to build a string of hidden HTML input fields. That string is returned as result. If the second parameter is set to true, the function will use htmlspecialchars on the keys and the values in the first parameter; if the third is true it will use stripslashes. See Example 1.7, “Example confirm box”
build_url is even simpler: it will generate a valid url to the current page in the forum and return it as string. You can pass an array of GET parameter names which should be stripped from the url as argument.
1.4.9. Errors
Strictly speaking, this is not part of phpBB's code, but as it is a major change for coders used to the message_die function, we'll cover it anyway. The use is very simple: just supply the string you want displayed as error message. The lang system will be applied on the argument, but you should use the user object in most cases. I.e. like this: trigger_error($user->lang['SOME_LANG_KEY']);
For privilege breaches, you can add the constant "E_USER_WARNING" like (Note: that's not a valid language entry) this trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action), E_USER_WARNING);
1.4.10. Log In
login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true)
Login prompts are easily generated with the login_box function. The first parameter - $redirect - indicates the page where the user should be redirected to after a successful login; the second - $l_explain - contains the text which should be shown as explanation and the third - $l_success - should contain the text to display in the case of a successful login.
Tip
Leaving $redirect empty will cause redirection to the original page; in fact the function can be called without any parameters.
A small example to illustrate the use:
if ($user->data['user_id'] == ANONYMOUS || $user->data['is_bot'])
{
login_box('', $user->lang['SOME_LANG_KEY']);
}
1.4.11. Confirm Box
confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')
The confirm boxes are phpBB3's system to secure critical actions against CSRF attacks and unintentional triggering. The system is quite simple: the function can be called in check mode, where it will check the presence of a one-time confirmation string passed as request parameter or in display mode, where it will display the confirm box.
Let's take a quick glance at the function and its parameters. confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = ''). Generally, you will need to supply the first three parameters, while the remaining two are usually fine by default - see the code documentation for details. $check correspondends to the aforementioned mode: true will run the function in check mode, false in display. The second parameter should be a language key used to explain to the user what the confirm box is about. The third parameter, $hidden, should hold html for hidden fields containing all (user-)submitted values needed to get the current script to exactly the state where it is when calling the function. Let's see this in action Example 1.7, “Example confirm box”
Example 1.7. Example confirm box
if ($submit)
{
// check mode
if (confirm_box(true))
{
submit($my_message);
}
else
{
$s_hidden_fields = build_hidden_fields(array(
'submit' => true,
'my_mesage' => $my_message,
)
);
//display mode
confirm_box(false, 'SAMPLE_LANG_KEY', $s_hidden_fields);
}
1.4.12. Page Header and Footer
page_header()
page_footer()
make_jumpbox($action)
Page headers and footers are easily created by calling the respective functions page_footer() and page_header(). If the templates include the header/footer template files, then this will ensure the display of the forum footers and headers.
1.4.13. Bringing it all together: A Sample Page
The php file
<?php
/**
*
* @package phpBB3
* @version $Id: v3_api.xml 52 2007-12-09 19:45:45Z jelly_doughnut $
* @copyright (c) 2007 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
// The default phpBB inclusion protection - required
define('IN_PHPBB', true);
$phpbb_root_path = './';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx);
// Start session management
$user->session_begin();
$auth->acl($user->data);
// our lang file is in the mods directory
$user->setup(array('memberlist', 'mods/api_example'));
$page_title = $user->lang['SEND_PM_SELF'];
// Read user input
$my_subject = request_var('my_subject', '', true);
$my_message = request_var('my_message', '', true);
$my_subject = utf8_normalize_nfc($my_subject);
$my_message = utf8_normalize_nfc($my_message);
$submit = (isset($_POST['submit'])) ? true : false;
// check permissions
if (!$auth->acl_gets('u_sendpm', 'u_readpm'))
{
if ($user->data['is_registered'])
{
trigger_error('EXAMPLE_SEND_PM_DENIED');
}
login_box('', $user->lang['EXAMPLE_SEND_PM_LOGIN']);
}
if ($submit)
{
if (confirm_box(true))
{
// variables to hold the parameters for submit_pm
$poll = $uid = $bitfield = $options = '';
generate_text_for_storage($my_subject, $uid, $bitfield, $options, false, false, false);
generate_text_for_storage($my_text, $uid, $bitfield, $options, true, true, true);
$data = array(
'address_list' => array ('u' => array($user->data['user_id'] => 'to')),
'from_user_id' => $user->data['user_id'],
'from_username' => $user->data['username'],
'icon_id' => 0,
'from_user_ip' => $user->data['user_ip'],
'enable_bbcode' => true,
'enable_smilies' => true,
'enable_urls' => true,
'enable_sig' => true,
'message' => $my_message,
'bbcode_bitfield' => $bitfield,
'bbcode_uid' => $uid,
);
submit_pm('post', $my_subject, $data, true);
$meta_info = append_sid("{$phpbb_root_path}api_example.$phpEx");
$message = $user->lang['EXAMPLE_PM_SENT'] . '<br /><br />' . sprintf($user->lang['RETURN_SEND_PM'], '<a href="' . $meta_info . '">', '</a>');
meta_refresh(3, $meta_info);
trigger_error($message);
}
else
{
$s_hidden_fields = build_hidden_fields(array(
'submit' => true,
'my_message' => $my_message,
'my_subject' => $my_subject,
)
);
// display mode
confirm_box(false, $user->lang['EXAMPLE_API_REALLY'], $s_hidden_fields);
}
}
// Output the page
page_header($page_title);
$template->assign_vars(array(
'S_MY_MESSAGE' => $my_message,
'S_MY_SUBJECT' => $my_subject,
'S_SEND_ACTION' => build_url('confirm_key'),
)
);
$template->set_filenames(array(
'body' => 'api_example.html')
);
make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx"));
page_footer();
?>
The template
<!-- INCLUDE overall_header.html -->
<div id="pagecontent">
<form name="send" action="{S_SEND_ACTION}" method="post">
<table class="tablebg" width="100%" cellspacing="1">
<tr>
<th>{L_SEND_TITLE}</th>
</tr>
<tr>
<td class="row3" align="center"><span class="genmed">{L_SEND_EXPLAIN}</span></td>
</tr>
<tr>
<th>{L_SEND_SUBJECT}</th>
</tr>
<tr>
<td class="row1" align="center"><input name="my_subject" value="{S_MY_SUBJECT}" size="76" /></td>
</tr>
<tr>
<th>{L_SEND_MESSAGE}</th>
</tr>
<tr>
<td class="row2" align="center"><textarea name="my_message" rows="10" cols="76">{S_MY_MESSAGE}</textarea></td>
</tr>
<tr>
<td class="cat" align="center"><input class="btnmain" type="submit" name="submit" value="{L_SUBMIT}" />
<input class="btnlite" type="reset" value="{L_RESET}" /></td>
</tr>
</table>
</form>
</div>
<br clear="all" />
<!-- INCLUDE breadcrumbs.html -->
<br clear="all" />
<div align="{S_CONTENT_FLOW_END}"><!-- INCLUDE jumpbox.html --></div>
<!-- INCLUDE overall_footer.html -->
The language. Be careful to use UTF8 encoding without BOM. That format is sometimes called UTF8-cookie.
Important
If the file language/en/mods/info_{module_name}.php (for example language/en/mods/info_ucp_karma.php) exists, it will automatically be included.
<?php
/**
*
* example [English]
*
* @package language
* @version $Id: v3_api.xml 52 2007-12-09 19:45:45Z jelly_doughnut $
* @copyright (c) 2007 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* DO NOT CHANGE
*/
if (empty($lang) || !is_array($lang))
{
$lang = array();
}
// DEVELOPERS PLEASE NOTE
//
// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
//
// Placeholders can now contain order information, e.g. instead of
// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
// translators to re-order the output of data while ensuring it remains correct
//
// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
// equally where a string contains only two placeholders which are used to wrap text
// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
$lang = array_merge($lang, array(
'SEND_TITLE' => 'Send a PM to yourself',
'SEND_EXPLAIN' => 'Just a little example. You can use it to send PMs to yourself. Fun!',
'SEND_SUBJECT' => 'Subject',
'SEND_MESSAGE' => 'Message',
'EXAMPLE_API_REALLY' => 'Do you really want to send a PM to yourself?',
'EXAMPLE_PM_SENT' => 'You have sent a PM to yourself. You have no life.',
'RETURN_SEND_PM' => 'That was fun. Let\'s do it %sagain%s.',
'EXAMPLE_SEND_PM_LOGIN' => 'Login to send a PM to yourself',
'EXAMPLE_SEND_PM_LOGIN_SUCC' => 'Send a PM',
'EXAMPLE_SEND_PM_DENIED' => 'You are not allowed to send yourself PMs',
'SEND_PM_SELF' => 'Send a PM to yourself',
));
?>