[Php-blog-plugin-cvs] additional_plugins/serendipity_event_guestbook ChangeLog, 1.17, 1.18 README,
A reliable, secure & extensible PHP blog | Not mainstream since 2002
Brought to you by:
garvinhicking,
jhermanns
Update of /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv20321/serendipity_event_guestbook Modified Files: ChangeLog README documentation_en.html lang_en.inc.php serendipity_event_guestbook.php Log Message: gitclone.sh autocommit Index: serendipity_event_guestbook.php =================================================================== RCS file: /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook/serendipity_event_guestbook.php,v retrieving revision 1.68 retrieving revision 1.69 diff -u -d -r1.68 -r1.69 --- serendipity_event_guestbook.php 24 Aug 2013 00:31:48 -0000 1.68 +++ serendipity_event_guestbook.php 25 Aug 2013 00:31:54 -0000 1.69 @@ -1,7 +1,7 @@ <?php # /** - * serendipity_event_guestbook.php, v.3.40 - 2013-08-21 Ian + * serendipity_event_guestbook.php, v.3.41 - 2013-08-24 Ian */ //error_reporting(E_ALL); @@ -61,7 +61,7 @@ 'dateformat' )); $propbag->add('author', 'Ian'); - $propbag->add('version', '3.40'); + $propbag->add('version', '3.41'); $propbag->add('requirements', array( 'serendipity' => '1.3', 'smarty' => '2.6.7', @@ -73,17 +73,19 @@ $this->filter_defaults = array('words' => '\[link(.*?)\];http://'); } + function example() { echo "\n<ul>\n"; echo " <li><strong>Note to v. 3.40:</strong> If have, please update copied guestbook tpl files in your template!</li>\n"; echo "</ul>\n\n"; } + function cleanup() { global $serendipity; // check possible config mismatch setting - if ( serendipity_db_bool($this->get_config('showapp')) === true && serendipity_db_bool($this->get_config('automoderate')) === true ) { + if (serendipity_db_bool($this->get_config('showapp')) === true && serendipity_db_bool($this->get_config('automoderate')) === true) { $this->set_config('automoderate', false); echo '<div class="serendipityAdminMsgError"><img class="backend_attention" src="' . $serendipity['serendipityHTTPPath'] . 'templates/default/admin/img/admin_msg_note.png" alt="" />'; echo PLUGIN_GUESTBOOK_CONFIG_ERROR . '</div>'; @@ -299,7 +301,7 @@ $propbag->add('type', 'text'); $propbag->add('rows', 2); $propbag->add('name', PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS); - $propbag->add('description', PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS_BLAHBLAH); + $propbag->add('description', PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS_BLAHBLAH . ' ' . PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS_BYPASS); $propbag->add('default', $this->filter_defaults['words']); break; @@ -366,7 +368,7 @@ /** * Check POST string if guestbooks content filter found something to strip - * Adds match to $serendipity['messagestack']['comments'] array + * Adds match to $serendipity['messagestack']['comments'] array, if not in admin group * * @param string $string mostly entry body checks * @@ -375,12 +377,10 @@ function strip_input($string) { global $serendipity; - $stripped = strip_tags($string); - // Filter Content + $stripped = strip_tags($string); $filter_bodys = explode(';', $this->get_config('entrychecks')); - // filter body checks if not admin [serendipityUserlevel] => 255 && [serendipityAuthedUser] => 1 - // @ToDo: is there a need to make this accessible to admin group? - if (is_array($filter_bodys) && (!serendipity_userLoggedIn() && !$_SESSION['serendipityAuthedUser'] === true && !$_SESSION['serendipityUserlevel'] == '255')) { + // filter string checks if not in admin group + if (is_array($filter_bodys) && $serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) { foreach($filter_bodys AS $filter_body) { $filter_body = trim($filter_body); if (empty($filter_body)) { @@ -399,6 +399,7 @@ /** * Strip and secure $serendipity['POST'] by keys and define modified array var if value has changed + * No need for trim(strip_tags()) here, while this changes length and is further on done on output separately! * * @param mixed $parr array or string depending on $single * @param array $keys array of keys only @@ -410,12 +411,12 @@ function strip_security($parr = null, $keys = null, $single = false, $compare = true) { $authenticated_user = serendipity_userLoggedIn() ? true : false; if ($single) { - return $authenticated_user ? htmlspecialchars($parr) : htmlspecialchars(trim(strip_tags($parr))); + return $authenticated_user ? htmlspecialchars($parr) : htmlspecialchars(strip_tags($parr)); } else { foreach ($parr AS $k => $v) { if (in_array($k, $keys)) { $valuelength = strlen($v); - $parrsec[$k] = $authenticated_user ? htmlspecialchars($v) : htmlspecialchars(trim(strip_tags($v))); + $parrsec[$k] = $authenticated_user ? htmlspecialchars($v) : htmlspecialchars(strip_tags($v)); if (!$authenticated_user && $compare && ($valuelength != strlen($parrsec[$k]))) { $parrsec['stripped'] = true; $parrsec['stripped-by-key'] = $k; @@ -517,6 +518,16 @@ /** + * This function is used for sidebar plugins only + * + * @param string $title is somehow important to indicate the title of a plugin in the plugin configuration manager. + */ + function generate_content(&$title) { + $title = PLUGIN_GUESTBOOK_TITLE.' (' . $this->get_config('pagetitle') . ')'; // do we need to set this to headline now? + } + + + /** * BBCode replacements * old preg_replace had issues with whitespaces * @@ -539,20 +550,11 @@ * @return string */ function bbc_reverse($text) { - $pattern = '|[[\/\!]*?[^\[\]]*?]|si'; + $pattern = '|[[\/]*?[^\[\]]*?]|si'; $replace = ''; return preg_replace($pattern, $replace, $text); } - /** - * This function is used for sidebar plugins only - * - * @param string $title is somehow important to indicate the title of a plugin in the plugin configuration manager. - */ - function generate_content(&$title) { - $title = PLUGIN_GUESTBOOK_TITLE.' (' . $this->get_config('pagetitle') . ')'; // do we need to set this to headline now? - } - /** * Cut string between two other strings @@ -746,6 +748,7 @@ $valid['message'] = FALSE; $serendipity['guestbook_message_header'] = FALSE; $authenticated_user = serendipity_userLoggedIn() ? true : false; + $gb_automoderate = serendipity_db_bool($this->get_config('automoderate')); if (empty($serendipity['POST']['guestbookform'])) { return false; @@ -766,13 +769,17 @@ } // do not allow non logged-in manual BBCode in comments - if (!$authenticated_user) $serendipity['POST']['comment'] = $this->bbc_reverse($serendipity['POST']['comment']); - - if ($hit = preg_grep("~/forcemoderation_treat~i", array_keys($serendipity))) { - $serendipity['spamblock']['forcemoderate'] = array_values($hit); + if (!$authenticated_user) { + $serendipity['POST']['comment'] = $this->bbc_reverse($serendipity['POST']['comment']); } - if (isset($serendipity[end($serendipity['spamblock']['forcemoderate'])]) == 'moderate') { + // find Spamblock global set force auto moderation + if ($hit = preg_grep("|/forcemoderation_treat|i", array_keys($serendipity))) { + $forcemoderate = array_values($hit); + } + // if force moderate is set to moderate, advice security to not support 'stripped' or 'stripped-by-key' POST mark + // this does only happen true, if not automoderate is set in both plugins and strip tags really removed some tags. + if (isset($serendipity[$forcemoderate[0]]) == 'moderate' && $gb_automoderate === true) { $serendipity['POST'] = $this->strip_security($serendipity['POST'], array('name', 'email', 'comment', 'url'), false, false); } else { $serendipity['POST'] = $this->strip_security($serendipity['POST'], array('name', 'email', 'comment', 'url')); @@ -805,7 +812,7 @@ serendipity_plugin_api::hook_event('frontend_saveComment', $ca, $commentInfo); } // End of fake call. - // listen to Spamblock Plugin and do some specific guestbook checks, if captchas and entry were alowed + // listen to Spamblock Plugin and do some specific guestbook checks, if captcha and entry were allowed if (serendipity_db_bool($ca['allow_comments']) === true) { if (trim($serendipity['POST']['name']) == '') { @@ -879,7 +886,7 @@ $valid['message'] = (count($messages) < 1) ? TRUE : FALSE; // no errors and messages - if ( $valid['message'] === true ) { + if ($valid['message'] === true) { // set var, if not set by backend form if (!is_numeric($_POST['guestbook']['approved'])) $_POST['guestbook']['approved'] = ''; if (is_numeric($_POST['guestbook']['id'])) $_POST['guestbook']['approved'] = 1; @@ -892,7 +899,7 @@ // keep this for future finetuning via SPAMBLOCK plugin if (array_key_exists('moderate_comments', $ca)) { - if (serendipity_db_bool($ca['moderate_comments']) === true && serendipity_db_bool($this->get_config('automoderate')) === true) { + if (serendipity_db_bool($ca['moderate_comments']) === true && $gb_automoderate === true) { // set entries to get approved in backend, before they can appear in frontent $_POST['guestbook']['approved'] = 0; } @@ -900,11 +907,8 @@ } // write new entry into database, if input is valid - if ( !empty($serendipity['POST']['guestbookform']) - && $valid['captcha'] === true - && $valid['data_length'] === true - && $valid['data_email'] === true - && $valid['message'] === true) { + if (!empty($serendipity['POST']['guestbookform']) && $valid['captcha'] === true && $valid['data_length'] === true + && $valid['data_email'] === true && $valid['message'] === true) { $admincomment = (!empty($serendipity['POST']['admincomment'])) ? '[ac] ' . $serendipity['POST']['admincomment'] . ' [/ac]' : ''; $acapp = ($authenticated_user && $_SESSION['serendipityAuthedUser'] === true) ? 1 : NULL; @@ -919,12 +923,20 @@ } // claim insertEntriesDB is true - $showapp = serendipity_db_bool($this->get_config('showapp')); + $showapp = serendipity_db_bool($this->get_config('showapp')); $showapptxt = ($showapp && !$authenticated_user) ? ' ' . PLUGIN_GUESTBOOK_DBDONE_APP : ''; - if (!$authenticated_user && (!$showapp && $_POST['guestbook']['approved'] == 0 || $serendipity['csuccess'] == 'moderate')) { - $showapptxt = '<br />' . $serendipity['moderate_reason'] . '<br />' . PLUGIN_GUESTBOOK_AUTOMODERATE_ERROR . PLUGIN_GUESTBOOK_DBDONE_APP; + + if (!$authenticated_user) { + // be strict here, since it could be null also + if (($showapp === false && $acapp === 0) || $serendipity['csuccess'] == 'moderate') { + if (isset($serendipity[$forcemoderate[0]]) == 'moderate') { + $showapptxt = '<br />' . $serendipity['moderate_reason'] . '<br />' . PLUGIN_GUESTBOOK_AUTOMODERATE_ERROR . PLUGIN_GUESTBOOK_DBDONE_APP; + } + } } - array_push($messages, PLUGIN_GUESTBOOK_MESSAGE . ': ' . PLUGIN_GUESTBOOK_DBDONE . $showapptxt ); + + array_push($messages, PLUGIN_GUESTBOOK_MESSAGE . ': ' . PLUGIN_GUESTBOOK_DBDONE . $showapptxt); + // flag global meassage header to have successfully checked and safed the entry $serendipity['guestbook_message_header'] = true; // reset post values @@ -1072,6 +1084,7 @@ // get the form page template file $conform = $this->parseTemplate('plugin_guestbook_form.tpl'); $serendipity['smarty']->assign('GUESTBOOK_FORM', $conform); + } // generate_FormPage() end @@ -1371,6 +1384,7 @@ $eventData .= $becss; } + /** * Main admin backend function * @@ -1571,7 +1585,8 @@ break; } echo "\n\n</div> <!-- // backend_guestbook_wrapper end -->\n\n"; - } + } // backend_guestbook_menu() end + /** * Fake call to check if database is set and ready @@ -1791,7 +1806,7 @@ } } - } + } // backend_guestbook_dbclean() end /** @@ -1811,6 +1826,7 @@ } } + /** * Create prettified questionaire buttons string * @@ -1831,6 +1847,7 @@ ' . $this->backend_guestbook_emsg(); } + /** * Set header start string * @@ -1840,6 +1857,7 @@ return $str = "<div class='serendipity_center guestbook_tpl_message'>\n <div class='guestbook_tpl_message_inner'>\n"; } + /** * Set header end string * @@ -1849,6 +1867,7 @@ return $str = " </div>\n</div>\n"; } + /** * Guestbook backup table and dir/file voodoo * @@ -2013,4 +2032,5 @@ } } + /* vim: set sts=4 ts=4 expandtab : */ Index: lang_en.inc.php =================================================================== RCS file: /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook/lang_en.inc.php,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- lang_en.inc.php 24 Aug 2013 00:31:48 -0000 1.16 +++ lang_en.inc.php 25 Aug 2013 00:31:54 -0000 1.17 @@ -1,11 +1,11 @@ <?php # /** - * @version 3.40 - * @file serendipity_event_guestbook.php, langfile(utf-8/en) v.3.40 - 2013-08-21 Ian + * @version 3.41 + * @file serendipity_event_guestbook.php, langfile(en) v.3.41 - 2013-08-24 Ian * @translated * @author Ian - * @revisionDate 2013-08-21 + * @revisionDate 2013-08-24 */ @define('PLUGIN_GUESTBOOK_HEADLINE', 'Headline'); @@ -73,9 +73,6 @@ @define('TEXT_NAME', 'Name'); @define('TEXT_HOMEPAGE', 'Homepage'); @define('TEXT_EMAILSUBJECT', 'New guestbook entry'); -@define('TEXT_EMAILMODERATE', "\n\nThis guestbook entry was set to moderate (%s)!"); -@define('TEXT_EMAILFOOTER', "\n\nSent by Serendipity Guestbook Plugin."); -@define('TEXT_EMAILTEXT', "%s just wrote to your guestbook:\n%s\n%s\n"); @define('TEXT_CONVERTBOLDUNDERLINE', 'Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.'); @define('TEXT_CONVERTSMILIES', 'Standard emoticons like :-) and ;-) are converted to images.'); @define('TEXT_IMG_DELETEENTRY', 'Delete entry'); @@ -86,8 +83,6 @@ @define('ERROR_TEXTEMPTY', 'Please insert a text.'); @define('ERROR_EMAILEMPTY', 'Please insert a valid e-mail.'); @define('ERROR_DATATOSHORT', 'Your entry should have at least 3, in the comment field at least 10 characters.'); -@define('ERROR_DATASTRIPPED', 'An active security-filter consists your entry is unvalid. Please send the already cleared entry again.'); -@define('ERROR_DATANOTAGS', 'An active plugin-wordfilter consists your entry is unvalid.'); @define('ERROR_NOVALIDEMAIL', 'Your e-mail address appears to be invalid: '); @define('ERROR_NOINPUT', 'Please enter your name, e-mail address and a comment'); @define('ERROR_ISFALSECAPTCHA', 'The CAPTCHAS of your entry did not match!'); @@ -124,6 +119,14 @@ /* config v.3.26 additions */ @define('PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS', 'Special body checks'); @define('PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS_BLAHBLAH', 'List individual guestbook entry body checks. Regular Expressions are allowed, separate strings by semicolons (;). You have to escape special chars with "\". If you leave this field empty, no special checks are done.'); +/* config v.3.40 additions */ +@define('TEXT_EMAILMODERATE', "\n\nThis guestbook entry was set to moderate (%s)!"); +@define('TEXT_EMAILFOOTER', "\n\nSent by Serendipity Guestbook Plugin."); +@define('TEXT_EMAILTEXT', "%s just wrote to your guestbook:\n%s\n%s\n"); +@define('ERROR_DATASTRIPPED', 'An active security-filter consists your entry is unvalid. Please send the already cleared entry again.'); +@define('ERROR_DATANOTAGS', 'An active plugin-wordfilter consists your entry is unvalid.'); +/* config v.3.41 additions */ +@define('PLUGIN_GUESTBOOK_FILTER_ENTRYCHECKS_BYPASS', '(Bypassed by USERLEVEL_ADMIN only!)'); /* Backend main constants */ @define('PLUGIN_GUESTBOOK_ADMIN_NAME', 'Guestbook'); Index: ChangeLog =================================================================== RCS file: /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook/ChangeLog,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- ChangeLog 24 Aug 2013 00:31:48 -0000 1.17 +++ ChangeLog 25 Aug 2013 00:31:52 -0000 1.18 @@ -1,4 +1,14 @@ -3.40: +3.41: +----- + + * Be more strict in types for automoderate messages + * Removed trim() in strip_security() + * Removed bbc_reverse() pattern \! part + * Filter guestbook comment checks, if not in admin group + * Added constant bypass guestbook comment checks + + + 3.40: ----- * Added some powered by guestbook note to email in body and headers @@ -16,6 +26,7 @@ * Bump version to propagate new .htaccess access by Spartacus + 3.31: ----- Index: documentation_en.html =================================================================== RCS file: /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook/documentation_en.html,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- documentation_en.html 15 Sep 2012 00:34:44 -0000 1.11 +++ documentation_en.html 25 Aug 2013 00:31:54 -0000 1.12 @@ -34,7 +34,7 @@ <body> <div><a name="top" id="top"></a></div> <div id="wrapper"> - <div class="doc_edited">serendipity_event_guestbook/documentation_en.html, last modified 2011-03-08</div> + <div class="doc_edited">serendipity_event_guestbook/documentation_en.html, last modified 2013-08-24</div> <div class="doc_block"><span class="white">PLEASE NOTE</span><br /> <br /> This Serendipity guestbook plugin is TEMPLATE based, configurable by its own stylesheet, has a FRONTEND and a BACKEND.<br /> @@ -61,7 +61,7 @@ <li>The <span class="eye">'Show Captchas'</span> setting defines the use of Serendipity CAPTCHAS (requires Spamblock plugin activated) to prevent comment SPAM (<em>default: yes</em>).</li> <li>The <span class="eye">'Approve entries'</span> setting defines the guestbook entries to be verified by admin generally before they show up in frontend (<em>default: false</em>).</li> <li>The <span class="eye">'Auto-moderate'</span> setting defines the same behaviour for a single entry, if the SPAMBLOCK-plugin wordfilter option is activ and set to 'moderate', caused by stopword matches (<em>default: false</em>). The guestbook content evaluation will still return captcha checking, if any spam check evaluates true. This differs from normal spamblock behaviour!</li> - <li>The <span class="eye">'Entry checks'</span> setting sets an active and individual wordfilter array (<em>default: pre-filled</em>). Regular Expressions are allowed, separate strings by semicolons (;). You have to escape special chars with "\". If you leave this field empty, no special checks are done.</li> + <li>The <span class="eye">'Entry checks'</span> setting sets an active and individual wordfilter array (<em>default: pre-filled</em>). Regular Expressions are allowed, separate strings by semicolons (;). You have to escape special chars with "\". If you leave this field empty, no special checks are done. (Bypassed by USERLEVEL_ADMIN only!)</li> <li>The <span class="eye">'Date format'</span> setting defines an individual strftime() code for the entry datetime (<em>default: %a, %d.%m.%Y %H:%M</em>).</li> </ul> <a name="admin" id="admin"></a> @@ -121,6 +121,29 @@ * please leave a message in http://www.s9y.org/forums/<br /> * have fun! Ian<br /> ****************************************************************</p> + <h2>Version 3.41 <span class="date">[ 2013-08-24 ]</span></h2> + <ul> + <li>Be more strict in types for automoderate messages</li> + <li>Removed trim() in strip_security()</li> + <li>Removed bbc_reverse() pattern \! part</li> + <li>Filter guestbook comment checks, if not in admin group</li> + <li>Added constant bypass guestbook comment checks</li> + </ul> + <h2>Version 3.40 <span class="date">[ 2013-08-23 ]</span></h2> + <ul> + <li>Added some powered by guestbook note to email in body and headers</li> + <li>Added entry set auto-moderate state into email body</li> + <li>Use nativ API parseTemplate() method, extends Serendipity >= 1.3</li> + <li>Improved security overall</li> + <li>Added bottom paginator to entry pages (both front- & backend)</li> + <li>Added new option to resize backend pagination amounts</li> + <li>Fixed multiple issues, eg entries homepage not showing up, while not inserted</li> + <li>Lang files cleanup and added some new constants</li> + </ul> + <h2>Version 3.32 <span class="date">[ 2013-05-23 ]</span></h2> + <ul> + <li>Bump version to propagate new .htaccess access by Spartacus</li> + </ul> <h2>Version 3.31 <span class="date">[ 2012-09-14 ]</span></h2> <ul> <li>The Frontend missed its stylesheets - sorry!</li> Index: README =================================================================== RCS file: /cvsroot/php-blog/additional_plugins/serendipity_event_guestbook/README,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- README 17 Sep 2012 00:33:00 -0000 1.14 +++ README 25 Aug 2013 00:31:54 -0000 1.15 @@ -1,5 +1,5 @@ /****************************************************************************** - * serendipty_event_guestbook.php, README, last modified 2012-09-14 * + * serendipty_event_guestbook.php, README, last modified 2013-08-24 * * if you have a interesting hack or want to help, * * please leave a message in http://www.s9y.org/forums/ * * have fun! Ian * @@ -28,7 +28,7 @@ * The 'Show Captchas' setting defines the use of Serendipity CAPTCHAS (requires Spamblock plugin activated) to prevent comment SPAM (default: yes). * The 'Approve entries' setting defines the guestbook entries to be verified by admin generally before they show up in frontend (default: false). * The 'Auto-moderate' setting defines the same behaviour for a single entry, if the SPAMBLOCK-plugin wordfilter option is activ and set to 'moderate', caused by stopword matches (default: false). The guestbook content evaluation will still return captcha checking, if any spam check evaluates true. This differs from normal spamblock behaviour! - * The 'Entry checks' setting sets an active and individual wordfilter array (default: pre-filled). Regular Expressions are allowed, separate strings by semicolons (;). You have to escape special chars with "\". If you leave this field empty, no special checks are done. + * The 'Entry checks' setting sets an active and individual wordfilter array (default: pre-filled). Regular Expressions are allowed, separate strings by semicolons (;). You have to escape special chars with "\". If you leave this field empty, no special checks are done. (Bypassed by USERLEVEL_ADMIN only!) * The 'Date format' setting defines an individual strftime() code for the entry datetime (default: %a, %d.%m.%Y %H:%M). S9Y :: GUESTBOOK :: ADMINISTRATION @@ -74,6 +74,38 @@ ------------------------------------- +| Version 3.41 [ 2013-08-24 ] | +------------------------------------- + + * Be more strict in types for automoderate messages + * Removed trim() in strip_security() + * Removed bbc_reverse() pattern \! part + * Filter guestbook comment checks, if not in admin group + * Added constant bypass guestbook comment checks + + +------------------------------------- +| Version 3.40 [ 2013-08-23 ] | +------------------------------------- + + * Added some powered by guestbook note to email in body and headers + * Added entry set auto-moderate state into email body + * Use nativ API parseTemplate() method, extends Serendipity >= 1.3 + * Improved security overall + * Added bottom paginator to entry pages (both front- & backend) + * Added new option to resize backend pagination amounts + * Fixed multiple issues, eg entries homepage not showing up, while not inserted + * Lang files cleanup and added some new constants + + +------------------------------------- +| Version 3.32 [ 2013-05-23 ] | +------------------------------------- + + * Bump version to propagate new .htaccess access by Spartacus + + +------------------------------------- | Version 3.31 [ 2012-09-14 ] | ------------------------------------- |