assign($params['assign'], $content) : $content; return $ret; } else { $protected_msg = ( # we add ability to override protected_msg from {protect protected_msg='some message'} isset($params['protected_msg']) ? $params['protected_msg'] : cms_utils::get_app_data('_PP_Prot_Msg') ); if (isset($protected_msg)) { $ret = isset($params['assign']) ? $smarty->assign($params['assign'], $protected_msg) : $protected_msg; return $ret; } } } } } function smarty_cms_function_page_protect($params, &$template) { # initialize a few vars $smarty = $template->smarty; $gCms = cmsms(); $current_page_alias = cms_utils::get_current_alias(); $logout_alias = isset($params['logout_alias']) ? $params['logout_alias'] : $current_page_alias; $login_alias = isset($params['login_alias']) ? $params['login_alias'] : null; $assign_var = isset($params['assign']) ? $params['assign'] : 'pp_logged_in'; # some of the params have to be persistent through all the page request # so we use the same method as ModuleHint i.e. cms_utils Data Storage # flag to check if current user is authenticated $allow = cms_utils::get_app_data('_PP_Allow'); if (!isset($allow)) { $allow = false; } # timeout in minutes (cookie lifecycle). Null or 0 (zero) means off $timeout = cms_utils::get_app_data('_PP_TOut'); $use_timeout = cms_utils::get_app_data('_PP_useTOut'); if (!$timeout) { if(isset($params['timeout'])) { $interval = $params['timeout'] * 60; } $timeout = ( isset($interval) ? time() + $interval : 0 ); $use_timeout = ( $timeout > 0 ); cms_utils::set_app_data('_PP_TOut', $timeout); cms_utils::set_app_data('_PP_useTOut', $use_timeout); } $cookie_name = cms_utils::get_app_data('_PP_CookieN'); if (!isset($cookie_name)) { $cookie_name = isset($params['cookie_name']) ? $params['cookie_name'] : 'pp_auth'; cms_utils::set_app_data('_PP_CookieN', $cookie_name ); } ##### messages ##### $protected_msg = cms_utils::get_app_data('_PP_Prot_Msg'); if (!isset($protected_msg)) { $protected_msg = isset($params['protected_msg']) ? $params['$protected_msg'] : $protected_msg; cms_utils::set_app_data('_PP_Prot_Msg', $protected_msg ); } $error_msg = cms_utils::get_app_data('_PP_Error_Msg'); if (!isset($error_msg)) { $error_msg = isset($params['error_msg']) ? $params['error_msg'] : 'The password is not correct.'; cms_utils::set_app_data('_PP_Error_Msg', $error_msg ); } $welcome_msg = cms_utils::get_app_data('_PP_Welcome_Msg'); if (!isset($welcome_msg)) { $welcome_msg = isset($params['welcome_msg']) ? $params['welcome_msg'] : 'Please enter the password to access this page.'; cms_utils::set_app_data('_PP_Welcome_Msg', $welcome_msg ); } ##### messages end ##### if (!isset($params['passwords'])) { $passwords = cms_utils::get_app_data('_PP_Pass'); } else { $passwords = &$params['passwords']; } if (!is_array($passwords)) { if (strpos($passwords, ',') === false) { $passwords = array($passwords); } else { $passwords = explode(',', $passwords); } } cms_utils::set_app_data('_PP_Pass', $passwords); ##### process requests and Cookies ##### $cookie_found = false; # logout if(isset($_POST['pp_logout'])) { # clear pass from cookie and redirect setcookie($cookie_name, '', 0, '/'); $allow = false; redirect_to_alias($logout_alias); } # process pass if (isset($_POST['pp_password'])) { $pass = $_POST['pp_password']; if ( !in_array($pass, $passwords) ) { $msg = $error_msg; $allow = false; } else { if ($use_timeout) { # we set cookie here #setcookie($cookie_name, md5($username . '%pp%' . $pass), $timeout, '/'); # todo setcookie($cookie_name, md5($pass), $timeout, '/'); } $allow = true; # @since 1.1 if (!isset($login_alias)) { redirect_to_alias($login_alias); } } } else { if ($use_timeout) { # check if cookie exists and is set if (!isset($_COOKIE[$cookie_name])) { $msg = ''; $allow = false; } foreach($passwords as $one) { if (isset($_COOKIE[$cookie_name]) && $_COOKIE[$cookie_name] == md5($one)) { $cookie_found = true; $allow = true; # so we have a valid request: extend timeout setcookie($cookie_name, md5($one), $timeout, '/'); break; } } if (!$cookie_found) { $allow = false; # may very well be redundant but hey!!! we clear any pending messages anyway $msg = ''; } } } ##### end process requests and Cookies ##### cms_utils::set_app_data('_PP_Allow', $allow); ##### actions ##### # @since 1.2 $action = isset($params['action']) ? $params['action'] : 'default'; switch ($action) { case 'form': { # common to both buttons $button_id = isset($params['button_id']) ? 'id="' . $params['button_id'] . '" ' : ''; $button_class = isset($params['button_class']) ? 'class="' . $params['button_class'] . '" ' : ''; if (!$allow) { $login_btn = isset($params['login_btn']) ? $params['login_btn'] : 'Login'; $form_id = isset($params['form_id']) ? 'id="' . $params['form_id'] . '" ' : ''; $form_class = isset($params['form_class']) ? 'class="' . $params['form_class'] . '" ' : ''; $in_pass_id = isset($params['in_pass_id']) ? 'id="' . $params['in_pass_id'] . '" ' : ''; $in_pass_class = isset($params['in_pass_class']) ? 'class="' . $params['in_pass_class'] . '" ' : ''; # @since 1.2 -> avoid warnings $msg = isset($msg) ? $msg : ''; $html = ''; $html .= '
'; } else { $logout_btn = isset($params['logout_btn']) ? $params['logout_btn'] : 'Logout'; $html = ''; $html .= ''; } # @since 1.2 if (isset($params['assign_output'])) { $smarty->assign($params['assign_output'], $html); } else { $ret = $html; } } break; # default usage: has to be located on top of the template # OR preferably on the "Smarty data or logic that is specific to this page" field # otherwise you'll get smarty error: {protect} tag is unknown # also has to be the top-most tag of any sequence of calls case 'set': { # dummy action: so one can set persistent parameters without triggering other actions } break; # default actions: just register the smarty plugin case 'default': default: { # register with smarty # usage: {protect}Content you want to protect {/protect} $smarty->registerPlugin("block", "protect", "pp_protect"); } } # send a var to the calling template, either assigned name or defaults to {$pp_logged_in} $smarty->assign($assign_var, $allow); if( isset($ret) ) return $ret; # @since 1.2 -> if we come from forms action we may have $ret set } ##### Docs ##### function smarty_cms_help_function_page_protect() { $txt = <<<'EOT'This plugin allows you to protect a number pages with one or more passwords.
This plugin can be used on any number of pages, either by being set once per each page you want to protect, or by being set on a page template, allowing you to protect all pages connected to that template
As of version 1.2, this plugin can work in two different ways:
Note that these two methods are not mutually exclusive: one adds to the other.
* Note: this only works if the tag {process_pagedata} is present on the template and is called before any other content block.
As of version 1.2 the plugin has a new functionality which allows for a faster deployment of a secure page. Page Protect will assign a Smarty variable, $pp_logged_in by default, with a boolean value flagging whether the current user is logged in or not.
As an example:
{page_protect action='form' passwords='pass1'}
This is a simple way to hide the content of a page from non authorized users:
Use this on the page content!
{page_protect action='form' passwords='pass1'}
{if $pp_logged_in}
The allowed content....
{else}
Not Logged in!
{/if}
The previous snippet will show a form for non logged in users, along with the text "Not Logged in!"
For the logged in user will present a logout button, and "The allowed content....".
This is a simple way to hide the content of all pages with this template from non authorized users:
Use this on the main template!
{content assign='content'}
{page_protect action='form' passwords='pass1'}
{if $pp_logged_in}
{$content}
{else}
Not Logged in!
{/if}
The previous snippet will show a form for non logged in users, along with the text "Not Logged in!"
For the logged in user will present a logout button, and the content of the page.
Note: by using only this method, without initializing the plugin, you cannot use the {protect}{/protect} tags. To use them you need to initialize the plugin!
In previous versions, the plugin needed to be initialized to work at all. As of version 1.2 the initialization is optional. However if the plugin is not initialized it will lose versatility. That doesn't mean that the quick setup, without the initialization, is not a valid setup. It is however a setup with less functionality, thus having its drawbacks.
By initializing the plugin you will have registered with the Smarty engine a block tag, {protect}{/protect}, which allow you to protect large blocks of text easily.
The initialization can be made through one of two methods, depending on what you want to protect. The most common scenarios are the following:
In the first two cases, the initialization should be made on each page, preferably on the field Smarty data or logic that is specific to this page* found on the page options tab.
Use one of these tags:
wich are equivalent.
You can also use this tag to add a few parameters except for action='set' and action='form' (and all form exclusive parameters as they are only pertinent to the form action and not persistent). Use:
* Note: this only works if the tag {process_pagedata} is present on the template and is called before any other content block.
Put this on the field Smarty data or logic that is specific to this page found on the page options tab:
{page_protect passwords='password1,passwor2,password3,passwordn'}
Alternatively, if you are not using the {process_pagedata} on your templates, you can still initialize the plugin, for a given page, by using the initialization tag on an extra content block which should be placed at the top of the template as the very first call.
Also alternatively, if you are not using the {process_pagedata} on your templates, you can still initialize the plugin, for a given template, by using the initialization tag on the top of the template as the very first. Keep in mind that all pages using that template will recognize the {protect}{/protect} tags. Also note that this method is also used for the 3rd and 4th scenarios, as it will be explained later.
Although you can, you don't need to set the passwords, nor any other parameters on the initialization tag: as most of the parameters are persistent through the same request, there is a special action, set, that can be used specifically to set persistent parameters anywhere on a template or content block (see more on the set action help tab).
Note: you cannot use {protect}{/protect} on the same content block where you initialized the plugin. The initialization won't be in effect yet and Smarty will not recognize the new tags at that point.
Note: you can use {protect}{/protect} on the same template where you initialized the plugin. However the {protect}{/protect} tags will have to be placed inside the <BODY>...</BODY> tags or the <BODY>...</BODY> tags, while the {page_protect} needs to be outside the <HTML>...</HTML> tags, or processed through {process_pagedata}.
It is important to understand the sequence by which CMSMS parses templates:
This means that each of these template areas is considered by CMSMS as a different block, and parsed tags and variables will be carried forward to the next in that sequence. It also guarantees that the tags {protect}{/protect} will be usable inside the <BODY>...</BODY> tags and the <BODY>...</BODY> tags, if properly initialized outside the <HTML>...</HTML> tags, particularly at the top of the template.
Finally in the last two scenarios, the initialization should be made on the template, preferably on the top of the template and outside the <HTML>...</HTML> tags.
If you only need to protect a number of pages with the same set of passwords, the 3rd case, you'll need only one extra template with the initialization tag. In the 4th case, where you need to protect different groups of pages with the same set of passwords per group, but different passwords from group to group, you may still use one template and set the passwords with some Smarty logic, but if you are not experienced with Smarty, then just create a template for each set of passwords, and assign the templates to the pages accordingly.
Put this on the top of your templates:
{page_protect passwords='password1,passwor2,password3,passwordn'}
For specific help on the other actions, and the protect block tags, check the respective action help tabs.
As of version 1.2, you can set all options on the tag call with this action. If you are using the quick way, this is all you need to set a Smarty variable which you can check anywhere on the template after this call.
Other than that just place the tag where you want a login/logout form. The default form action has default values for all form parameters, so the minimal tag is {page_protect action='form'}.
use {page_protect action='form'} to display the default login/logout form.
An example with all the parameters you can use to customize the form:
{* Do you really need all this?!!! A complete form call *}
{page_protect action='form' login_btn='Let Me In!' logout_btn='Bye Bye!' form_class='css_form' form_id='css_my_form' in_pass_id='css_passwrdid' in_pass_class='css_passwrd_class' button_id='css_btn_id' button_class='css_btn_class'}
As of version 1.2 any call to {page_protect action='...'}, with any action, including the default, will set a Smarty variable, which can be customized by the assign parameter, but which will default to $pp_logged_in by omission. This will be set to boolean TRUE whenever the current visitor is logged in and FALSE otherwise.
For specific help on the The Quick Way check the respective action help tab.
You can use any of the persistent parameters with the form action if needed. However the form specific parameters are not persistent.
This is a special action with the sole purpose of allowing you to set persistent parameters on different tag calls, helping a bit with the readability of the tags: just keep in mind that if you call it using the same parameter with different values, the last value will override all previous.
{* Using the 'set' action to spread parameters through multiple calls *}
{* redirect Home *}
{page_protect action='set' logout_alias='home'}
{* set the time before a login expires *}
{page_protect action='set' timeout=10}
{* set the message to show in case the authentication fails *}
{page_protect action='set' error_msg='Oops! Wrong pass, mate! Check your notes...'}
{* setting all the above in a single tag call could lead to errors *}
These tags are block smarty tags, and can be used several times on the page in pairs, i.e: an opening tag and a closing tag. The opening tag accepts only one parameter, the protected_msg which overrides the default one if set. This is a per occurrence tag, meaning that if it is set on the default or set actions it is persistent, but if set on a {protect} tag it affects only the tag where it is used and doesn't persist to the next occurrence.
Use one of the following tags:
{protect}whatever content you want protected.{/protect}
{protect protected_msg='well, you really should be logged in if you what to see the content'}whatever content you want protected.{/protect}
Note: without initializing the plugin, you cannot use the {protect}{/protect} tags.
Note: you cannot use {protect}{/protect} on the same content block where you initialized the plugin. The initialization won't be in effect yet and Smarty will not recognize the new tags at that point.
Use this anywhere on a template or a page content block:
{* This snippet of code can be used standalone; no need for an initialization tag *}
{page_protect action='form' passwords='pass1'}
{if $pp_logged_in}
The allowed content....
{else}
Not Logged in!
{/if}
Use this anywhere on the top of a template or on a page content block, preferably on the field Smarty data or logic that is specific to this page:
{* This tag initializes the plugin so that you can use the {protect}{/protect} tags *}
{page_protect}
A more complex example. Use this anywhere on the top of a template or on a page content block, preferably on the field Smarty data or logic that is specific to this page:
{* Use smarty syntax to create an array *}
{$passwords=['pass1','pass2','pass3']}
{* Use smarty syntax to set a few messages into variables we can use to fill in the parameters *}
{$welcome_msg='Please enter your password'}
{$protected_msg='You really need to login to have access to this page.'}
{$error_msg='The password you entered is not correct. Please check carefully if the password is correct and try again.'}
{******************************************************************************
This tag initializes the plugin so that you can use the {protect}{/protect} tags.
Note the use of already set Smarty vars to pass values to some parameters.
*******************************************************************************}
{page_protect passwords=$passwords login_alias='home' logout_alias='bye-bye-page-alias' timeout=10 cookie_name='a_cookie_name' welcome_msg=$welcome_msg protected_msg=$protected_msg error_msg=$error_msg}
{* Using the 'set' action to spread parameters through multiple calls *}
{* redirect Home on logout *}
{page_protect action='set' logout_alias='home'}
{* set the time before a login expires *}
{page_protect action='set' timeout=10}
{* set the message to show in case the authentication fails *}
{page_protect action='set' error_msg='Oops! Wrong pass, mate! Check your notes...'}
{* set the name of the login the check variable *}
{page_protect action='set' assign='logged_in'}
{* setting all the above in a single tag call could lead to errors *}
{* now we can check for our own named variable *}
{if $logged_in}
The allowed content...
{else}
Not Logged in!
{/if}
An example with all the parameters you can use to customize the form:
{* Do you really need all this?!!! A complete form call which doesn't output nothing because the assign_output parameter is being used *}
{page_protect action='form' login_btn='Let Me In!' logout_btn='Bye Bye!' form_class='css_form' form_id='css_my_form' in_pass_id='css_passwrdid' in_pass_class='css_passwrd_class' button_id='css_btn_id' button_class='css_btn_class' assign_output='login_form'}
{* by using assign_output='login_form' you can use {$login_form} several times on the template *}
{$login_form}
Use one of the following tags:
{protect}whatever content you want protected.{/protect}
{protect protected_msg='well, you really should be logged in if you what to see the content'}whatever content you want protected.{/protect}
The passwords parameter can accept a range of values, from a single password, a comma separated list of passwords, or an array of values:
{page_protect passwords='pass1'}
{page_protect passwords='pass1,'pass2','pass3'}
{* Use smarty syntax to create an array *}
{$passwords=['pass1','pass2','pass3']}
{* or *}
{$passwords[]='pass1'}
{$passwords[]='pass2'}
{$passwords[]='pass3'}
{* and use it as the value for the parameter passwords *}
{page_protect passwords=$passwords}
{* or *}
{page_protect action='set' passwords=$passwords}
The order by which the tags are called is extremely important: the default action (parameter action='default' which can be omitted) , when used, cannot be set on the same content block as the {protect}{/protect} tags, and should be called on the topmost block of the template. This tag registers a smarty block plugin {protect} which won't be recognized before being parsed once (and registered) by the Smarty engine. After this first call, all other calls don't have a specific order other than, of course, the opening and closing {protect}{/protect} tags.
Some of the parameters used by this plugin are persistent for the duration of the request, that is to say, through all of the current rendered page. This means that you can set them once, knowing they will be used later on the same request on subsequent calls to the plugin. That also means that they can be changed on subsequent calls, if needed.
Note: Unless you use an array to set the passwords, avoid the use of commas (,) and of vertical slashes (|) as password symbols as these are reserved to internal use and will unavoidably lead to passwords not being recognized by the plugin.
If the timeout parameter is used, this plugin will generate a frontend cookie. By using this parameter you may be violating some countries laws of user privacy. Please make sure you provide a fair warning on the front pages if needed, or avoid using the timeout parameter, thus disabling the use of cookies. The only drawback of not using cookies is that the authentication only lasts for a single page request.
This plugin needs PHP version 5.3.
Version: 1.2
Author: Jo Morg (Fernando Morgado)
Another plugin made out of need. Enjoy!