📜 ⬆️ ⬇️

PhpBB3 trap system

1. Introduction


What is it?

The trap system allows application developers and mods to set traps in phpBB code or use them in their own functions.

PhpBB functions with which you can use traps

There are 4 functions in phpBB that you can capture with your own hooks:

phpbb_user_session_handler () - called from inside user :: setup after correctly initializing the session and user objects;
append_sid ($ url, $ params = false, $ is_amp = true, $ session_id = false) - called to form links (add session identifier);
$ template-> display ($ handle, $ include_once = true) - called right before the output (not yet compiled) template;
exit_handler () - called at the very end of the phpBB3 code execution.

Please note: a trap using $ template-> display can take the third $ template argument (a link to the $ template object), which can be used instead of the global one.
')
If you integrated phpBB3 with your application, then you may want to use constants:

PHPBB_MSG_HANDLER (rewrite message handler);
PHPBB_DB_NEW_LINK (overwrite the new_link parameter for sql_connect);
PHPBB_ROOT_PATH (overwrite $ phpbb_root_path);
PHPBB_ADMIN_PATH (overwrite $ phpbb_admin_path);
PHPBB_USE_BOARD_URL_PATH (use generate_board_url () for images instead of $ phpbb_root_path).

If the PHPBB_USE_BOARD_URL_PATH constant is set to true, then phpBB uses generate_board_url () (which returns a link to the forum with the script path included) for all loaded images. This constant is in the files:

/includes/session.php - user :: img ()
/includes/functions_content.php - smiley_text ()

It will also change the paths in the template variables:
{T_THEME_PATH} - styles / xxx / theme
{T_TEMPLATE_PATH} - styles / xxx / template
{T_SUPER_TEMPLATE_PATH} - styles / xxx / template
{T_IMAGESET_PATH} - styles / xxx / imageset
{T_IMAGESET_LANG_PATH} - styles / xxx / imageset / yy
{T_IMAGES_PATH} - images /
{T_SMILIES_PATH} - $ config ['smilies_path'] /
{T_AVATAR_PATH} - $ config ['avatar_path'] /
{T_AVATAR_GALLERY_PATH} - $ config ['avatar_gallery_path'] /
{T_ICONS_PATH} - $ config ['icons_path'] /
{T_RANKS_PATH} - $ config ['ranks_path'] /
{T_UPLOAD_PATH} - $ config ['upload_path'] /
{T_STYLESHEET_LINK} - styles / xxx / theme / stylesheet.css (or a link to style.php, if css is dynamically generated)
The new template variable {BOARD_URL} consists of board url + script path.

2. We allow to use traps in functions and methods of classes.

The following examples explain how phpBB3 uses the built-in hook system. It is possible that you are more interested in registering your own traps, but the demonstration of this code will help you understand the trap system better ...

First of all, this example shows how to embed the necessary code in a function if you want to allow it to intercept traps:

  1. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  2. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  3. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  4. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  5. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  6. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  7. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  8. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  9. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  10. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  11. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }
  12. function my_own_function ( $my_first_parameter , $my_second_parameter ) { global $phpbb_hook ; if ( $phpbb_hook -> call_hook ( __FUNCTION__ , $my_first_parameter , $my_second_parameter ) ) { if ( $phpbb_hook -> hook_return ( __FUNCTION__ ) ) { return $phpbb_hook -> hook_return_result ( __FUNCTION__ ) ; } } [ ] }


Above, the call_hook function should always be called with the parameters of your function.

And this example shows how you could have a class method intercept traps ...
  1. class my_hookable_object
  2. {
  3. function hook_me ( $ my_first_parameter , $ my_second_parameter )
  4. {
  5. global $ phpbb_hook ;
  6. if ( $ phpbb_hook -> call_hook ( array ( __CLASS__ , __FUNCTION__ )) , $ my_first_parameter , $ my_second_parameter ) )
  7. {
  8. if ( $ phpbb_hook -> hook_return ( array ( __CLASS__ , __FUNCTION__ ) ) )
  9. {
  10. return $ phpbb_hook -> hook_return_result ( array ( __CLASS__ , __FUNCTION__ ) ) ;
  11. }
  12. }
  13. [ HERE YOUR CODE ]
  14. }
  15. }


Here the only difference is in how you define the first parameter. For a function, this is only a constant __FUNCTION__, and for a method it is an array (__ CLASS__, __FUNCTION__). In PHP4, the constant __CLASS__ always returns the name of the class in lowercase.

Now, in phpBB, predefined functions have appeared that can intercept traps, but how to make them available (and therefore allow others to intercept them)? For this there is a method add_hook () :
  1. // add your own function that can
  2. // catch traps
  3. $ phpbb_hook -> add_hook ( 'my_own_function' ) ;
  4. // add your own method that can
  5. // catch traps
  6. $ phpbb_hook -> add_hook ( array ( 'my_hookable_object' , 'hook_me' ) ) ;

You can also remove the ability to hook traps by a function / method by calling $ phpbb_hook-> remove_hook () with the same parameters as add_hook (). This is useful if you want some traps not to be called.

3. Registration traps

We now turn to the definition of your functions that should be called. To do this, we take the append_sid () function as an example (this function can be used by default hooks) and create two classes and a function:
  1. class my_append_sid_class {
  2. // our functions
  3. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false ) {
  4. // get the possible results of the previous trap
  5. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  6. return $ result [ 'result' ] . "<br /> I was the second." ;
  7. }
  8. }
  9. // one more class
  10. class my_second_append_sid_class {
  11. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false ) {
  12. // get the possible results of the previous trap
  13. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  14. echo $ result [ 'result' ] . "<br /> I am the third." ;
  15. }
  16. }
  17. // normal function
  18. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false ) {
  19. // get the possible results of the previous trap
  20. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  21. return "I was called first" ;
  22. }
  23. // initialize second class
  24. $ my_second_append_sid_class = new my_second_append_sid_class ( ) ;


Make sure that you add the same parameters to your function as defined for the function that hooks traps with one exception: the first parameter is always & $ hook, a link to the hook object that you can work with.

Now we register the traps one by one using the $ phpbb_hook-> register () method:
  1. // Now we will register our “substitutes” for the append_sid function in order ...
  2. // Register the function (called first)
  3. $ phpbb_hook -> register ( 'append_sid' , 'my_append_sid' ) ;
  4. // Register first class
  5. $ phpbb_hook -> register ( 'append_sid' , array ( 'my_append_sid_class' , 'my_append_sid' ) ) ;
  6. // .. and second class
  7. $ phpbb_hook -> register ( 'append_sid' , array ( & $ my_second_append_sid_class , 'my_append_sid' ) ) ;


With this example, you can even force your own functions to intercept themselves:

  1. // Register the trap that phpbb will intercept
  2. $ phpbb_hook -> register ( 'append_sid' , 'my_own_append_sid' ) ;
  3. // Add a function that will intercept traps
  4. $ phpbb_hook -> add_hook ( 'my_own_append_sid' ) ;
  5. // Register the trap that will be intercepted by our function
  6. $ phpbb_hook -> register ( 'my_own_append_sid' , 'also_my_own_append_sid' ) ;


Special processing / chains

The hooks registration method is able to accept the third argument for defining a special “chain” mode. It can take the values: first , last and standalone .

$ phpbb_hook-> register ('append_sid', 'my_own_append_sid', 'first') guarantees a function call at the beginning of the chain. It is possible to call more than one function within the first block - the FIFO principle is used here;
$ phpbb_hook-> register ('append_sid', 'my_own_append_sid', 'last') guarantees a function call at the very end of the chain. It is possible to call more than one function within the latter - the FIFO principle is used here;
$ phpbb_hook-> register ('append_sid', 'my_own_append_sid', 'standalone') ensures that only a specific function is called. All other functions are removed from the chain and other functions are not added to it after. If two applications attempt to switch the standalone mode, then a PHP notification will be displayed and the second function will be ignored.
Object Trap Resolution

Because the trap system cannot distinguish between initialized objects, and only operates on the classes themselves, you need to solve this at the code level.

One possible way is to use the property:
  1. class my_hookable_object {
  2. function blabla ( )
  3. {
  4. }
  5. }
  6. class my_hookable_object2 extends my_hookable_object
  7. {
  8. var $ call_hook = true ;
  9. function hook_me ( $ my_first_parameter , $ my_second_parameter )
  10. {
  11. if ( $ this -> call_hook )
  12. {
  13. global $ phpbb_hook ;
  14. if ( $ phpbb_hook -> call_hook ( array ( __CLASS__ , __FUNCTION__ )) , $ my_first_parameter , $ my_second_parameter ) )
  15. {
  16. if ( $ phpbb_hook -> hook_return ( array ( __CLASS__ , __FUNCTION__ ) ) )
  17. {
  18. return $ phpbb_hook -> hook_return_result ( array ( __CLASS__ , __FUNCTION__ ) ) ;
  19. }
  20. }
  21. }
  22. return 'not hooked' ;
  23. }
  24. }
  25. function hooking ( & $ hook , $ first , $ second )
  26. {
  27. return 'hooked' ;
  28. }
  29. $ first_object = new my_hookable_object2 ( ) ;
  30. $ second_object = new my_hookable_object2 ( ) ;
  31. $ phpbb_hook -> add_hook ( array ( 'my_hookable_object2' , 'hook_me' ) ) ;
  32. $ phpbb_hook -> register ( array ( 'my_hookable_object2' , 'hook_me' ) , 'hooking' ) ;
  33. // Do not call a trap for $ first_object
  34. $ first_object -> call_hook = false ;
  35. echo $ first_object -> hook_me ( 'first' , 'second' ) . '<br />' ;
  36. echo $ second_object -> hook_me ( 'first' , 'second' ) . '<br />' ;
  37. //Conclusion:
  38. not hooked
  39. hooked


Another possibility is to use a variable function (which can be omitted when passing variables to the trap):
  1. class my_hookable_object {
  2. function blabla ( )
  3. {
  4. }
  5. }
  6. class my_hookable_object2 extends my_hookable_object
  7. {
  8. function hook_me ( $ my_first_parameter , $ my_second_parameter , $ hook_me = true )
  9. {
  10. if ( $ hook_me )
  11. {
  12. global $ phpbb_hook ;
  13. if ( $ phpbb_hook -> call_hook ( array ( __CLASS__ , __FUNCTION__ )) , $ my_first_parameter , $ my_second_parameter ) )
  14. {
  15. if ( $ phpbb_hook -> hook_return ( array ( __CLASS__ , __FUNCTION__ ) ) )
  16. {
  17. return $ phpbb_hook -> hook_return_result ( array ( __CLASS__ , __FUNCTION__ ) ) ;
  18. }
  19. }
  20. }
  21. return 'not hooked' ;
  22. }
  23. }
  24. function hooking ( & $ hook , $ first , $ second )
  25. {
  26. return 'hooked' ;
  27. }
  28. $ first_object = new my_hookable_object2 ( ) ;
  29. $ second_object = new my_hookable_object2 ( ) ;
  30. $ phpbb_hook -> add_hook ( array ( 'my_hookable_object2' , 'hook_me' ) ) ;
  31. $ phpbb_hook -> register ( array ( 'my_hookable_object2' , 'hook_me' ) , 'hooking' ) ;
  32. echo $ first_object -> hook_me ( 'first' , 'second' , false ) . '<br />' ;
  33. echo $ second_object -> hook_me ( 'first' , 'second' ) . '<br />' ;
  34. // Conclusion:
  35. not hooked
  36. hooked


4. Return of the result

It is necessary to clearly define, either the function returns the result obtained by the intercepted function, or continues its execution. This may be due to the need of the application and, consequently, the function returns the result only if the function intercepted by the trap returns a result.

Case number 1 - Returning the result of the function

Imagine that the following function supports traps:
  1. function append_sid ( $ url , $ params = false , $ is_amp = true , $ session_id = false ) {
  2. global $ _SID , $ _EXTRA_URL , $ phpbb_hook ;
  3. // Developers using traps need to do
  4. // global $ _SID and $ _EXTRA_URL in their own
  5. // functions and skillfully manage them.
  6. // Most of the code can be simply copied from here.
  7. if ( $ phpbb_hook -> call_hook ( __FUNCTION__ , $ url , $ params , $ is_amp , $ session_id ) ) {
  8. if ( $ phpbb_hook -> hook_return ( __FUNCTION__ ) )
  9. {
  10. return $ phpbb_hook -> hook_return_result ( __FUNCTION__ ) ;
  11. }
  12. }
  13. [ ... ]
  14. }


Now your function. Immediately after you return the result, the append_sid () function will return your result:
  1. // Intercepted function
  2. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false )
  3. {
  4. // Get possible results
  5. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  6. return 'After I return something, the append_sid () function will return my result' ;
  7. }


You should always use the opportunity to get the results of executing the function above, in the method previous_hook_result () , which returns an array of the form array ('result' => [your result]).

Case number 2 - We do not return anything at all

Sometimes applications do not need to return something and therefore the following functions will continue to run:
  1. function append_sid ( $ url , $ params = false , $ is_amp = true , $ session_id = false )
  2. {
  3. global $ _SID , $ _EXTRA_URL , $ phpbb_hook ;
  4. if ( $ phpbb_hook -> call_hook ( __FUNCTION__ , $ url , $ params , $ is_amp , $ session_id ) )
  5. {
  6. if ( $ phpbb_hook -> hook_return ( __FUNCTION__ ) )
  7. {
  8. return $ phpbb_hook -> hook_return_result ( __FUNCTION__ ) ;
  9. }
  10. }
  11. [ ... ]
  12. }
  13. // Intercepted function
  14. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false )
  15. {
  16. // Get possible results
  17. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  18. [ ... ]
  19. // I only overwrite some variables and do not return anything, so the append_sid () function will not return anything.
  20. }


Note: The decision to return or not to return is made exclusively at the very end of the call to the chain of traps. For example:
  1. // Intercepted function
  2. function my_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false )
  3. {
  4. // Get possible results
  5. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  6. // $ result variable does not contain value
  7. return 'FILLED' ;
  8. }
  9. // This function is also registered and executed after my_append_sid ()
  10. function my_own_append_sid ( & $ hook , $ url , $ params = false , $ is_amp = true , $ session_id = false )
  11. {
  12. $ result = $ hook -> previous_hook_result ( 'append_sid' ) ;
  13. // $ result variable is filled with 'FILLED'
  14. // But, since I do not return anything, the append_sid () function will continue its execution
  15. }
  16. // The way to register both functions
  17. $ phpbb_hook -> register ( 'append_sid' , 'my_append_sid' ) ;
  18. $ phpbb_hook -> register ( 'append_sid' , 'my_own_append_sid' ) ;


6. Embedding your files / classes / methods

In general, there are two ways between which you can choose:

1) Add the file to the folder includes / hooks / . The file must have hook_ prefix. This file will connect inside common.php, you can register your traps, connect other files or functions, etc. It is recommended to connect other files only if necessary (for example, inside a function call).

Keep in mind that you need to clear the cache so that your newly moved files are accessible by phpBB3.

2) The second method is intended for those who want to wrap the code phpBB3, instead of placing a special file in the folder for traps. This is usually done by connecting phpBB files within an application file. In order to register your trap you need to create a function in the application:
  1. // My function, which is executed inside the constructor
  2. function phpbb_hook_register ( & $ hook )
  3. {
  4. $ hook -> register ( 'append_sid' , 'my_append_sid' ) ;
  5. }
  6. [ ... ]


Original text .

Source: https://habr.com/ru/post/131074/


All Articles