Jump to content

Recommended Posts

Store mode 1.1 uploaded

 

Changes Version 1.1:

- Added restore function for .htaccess file. This is needed if Header Tag Store Mode Module is uninstalled in "Offline" or "Offlinetest" mode.   Thanks to @@ecommunlimited

- Added Reminder Messages for Administrators which show permanent in Admin and in the Store for Administrators if Store Mode is not "Online".

- Added "Contact" link to maintenance.php

- Auto fill in Store Name and Store E-Mail to maintenance.php when Header Tag module is installed

Share this post


Link to post
Share on other sites

@@raiwa

 

Thnx for the update

 

Only after the update I see the output of the message in the admin on the shop side :-) instead of the define's from the language files.

Share this post


Link to post
Share on other sites

@@Fiber, in which mode?

 

In test modes you should see the standard messages like the customers see.

In other modes and if visiting with admin IP (Allowed IPs list) you should see the Reminder Message with the text like in Admin.

That's the sense, to show  for Admins the reminder message to remember you not to forget to switch back to online mode.

Share this post


Link to post
Share on other sites

@@Fiber,

 

Yes, you are right, it shouldn't show in test modes.

 

Please change in includes/modules/content/header/cm_header_store_mode.php line 111 to:

      if ( MODULE_HEADER_TAGS_STORE_MODE != 'online' && strpos(MODULE_HEADER_TAGS_STORE_MODE, '-test') == 0 && in_array(getenv('REMOTE_ADDR'), $allowed_ips_array) ) {

Please confirm and I'll upload the fix.

 

thank you

Rainer

Share this post


Link to post
Share on other sites

@@raiwa

 

Installing the content module, on URL ...admin/modules.php?set=header_tags&module=ht_store_mode
 
Notice: Use of undefined constant MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_ - assumed 'MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_' in .../includes/modules/header_tags/ht_store_mode.php on line 201
 

$KeysArray[] = MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_ . $key;

Fixed:

$KeysArray[] = 'MODULE_HEADER_TAGS_STORE_MODE_MESSAGE_' . $key;

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites
PHP Warning:  file_put_contents(../maintenance.php): failed to open stream: Forbidden access in ...includes/modules/header_tags_amantis/ht_store_mode.php on line 166

Ok, I know it's a permissions problem. But I've never known what level of permissions to grant on this situations :(

What's the minimum (most conservative and secure) chmod numbers to allow writting .htaccess from ht_store_mode.php? Can you guide me please? Thanks!

Edited by katapofatico

Share this post


Link to post
Share on other sites

@@katapofatico,

 

I use it like it is set during installation: 755. Other addons and the core admin protection also write to .htaccess and need this setting, so I think it should be ok.

 

rgds

Rainer

Edited by raiwa

Share this post


Link to post
Share on other sites

Hi Rainer and thanks again for a very useful addon.

I've got some comments.

For Php 7.x:

in includes/modules/header_tags/ht_store_mode.php

-replace
      while (list($id, $value) = each($lng->catalog_languages)) {

-with
      foreach($lng->catalog_languages as $key => $value) {


I noticed that the folder htaccess_backups is browsable.
This is what I did in includes/modules/header_tags/ht_store_mode.php.
I replaced the function htaccess_backup with this code:

  // function create htaccess backup  
  function htaccess_backup($bkup_name) {
    $separator = ((substr(DIR_FS_CATALOG, -1) != '/') ? '/' : '');
    $backupDir = DIR_FS_CATALOG . $separator . 'htaccess_backups';
    $backupDir .= '/';

    // create backup dir
    if(!is_dir($backupDir)) mkdir($backupDir, 0755);

    // create .htaccess protection containing allowed ip's
    $htaccessfile = $backupDir . '.htaccess';
    $allowed_ips_array = explode(',', MODULE_HEADER_TAGS_STORE_MODE_ALLOWED_IPS);
    $htaccess = '';
    foreach ($allowed_ips_array as $ip) {
        $htaccess .= 'Require ip ' . $ip . "\n";
    }
    file_put_contents($htaccessfile, $htaccess);

    $htaccessfileOrig = DIR_FS_CATALOG . $separator . '.htaccess';
    $htaccessfileBkup = $backupDir . $bkup_name;

    $result = copy($htaccessfileOrig, $htaccessfileBkup);
}

 

I also wanted to add a button to check the shop availability status, as follows:

In maintenance.php

- find

  define('TEXT_MAINTENANCE_CONTACT_ENGLISH', '<br><br><a href="mailto: %s ?Subject=Store Offline" target="_top">Contact</a>');

- add after

  define('TEXT_MAINTENANCE_STATUS_ENGLISH', '<br><br>To verify the site status ... Click Continue<br><br>');

- find

</style>

- add before

.button {
    background-color: #4CAF50; /* Green */
    border: none;
    color: white;
    padding: 10px 22px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    border-radius: 8px;    
}


- find

    if ( defined('TEXT_MAINTENANCE_CONTACT_ENGLISH') && TEXT_MAINTENANCE_CONTACT_ENGLISH != '' && $store_mail != '' ) {
      echo  sprintf(TEXT_MAINTENANCE_CONTACT_ENGLISH, $store_mail);
    }

- add after

    if ( defined('TEXT_MAINTENANCE_STATUS_ENGLISH') && TEXT_MAINTENANCE_STATUS_ENGLISH ) {
      echo  TEXT_MAINTENANCE_STATUS_ENGLISH;
    ?>
     <form>
        <input type="button"  class="button" value="Continue" onclick="window.location.href='<?php echo dirname($_SERVER["REQUEST_URI"])."/index.php?language=en";?>'" />
    </form>
    <?php
    }

After putting the shop online again this seems to work pretty well in Chrome and Edge, but not always in Firefox, especially with Firefox with multiple tabs/windows open. Firefox keeps cacheing pages very stubbornly.

All comments are welcome!

Edited by vmn

Share this post


Link to post
Share on other sites

Hello @vmn,

Thanks for your help and support.

You are right, this add-on has not ben updated yet for PHP 7.2 and latest Frozen.

I'll have a deeper look on all of this when I'll find some time. I'm really busy right now, please be patient.

Best regards

Rainer

Share this post


Link to post
Share on other sites

Hello again @raiwa.

I understand you are busy, but maybe you'll find some time to look at my findings.

1. I did not find any other php 7.x related issues.

2. Wouldn't it be better to use 307 instead of 302?

3. The only way I managed to prevent Firefox cacheing the redirect was to comment out the line

ExpiresDefault "access plus 2 days" in the .htaccess for the maintenance period.
Then I remove the comment when returning back to online.

I'm using the stock .htcasses:

<IfModule mod_expires.c>
...
ExpiresDefault "access plus 2 days"
</IfModule>

This is my version of the function ht_store_mode_add_to_htaccess (changes marked with //VMN):

  function ht_store_mode_add_to_htaccess($mode_text) {
    if ( isset($_GET['module']) && $_GET['module'] == 'ht_store_mode') {
      //VMN set the back_time variable in maintenance.php from url
      //VMNif ( is_file(DIR_FS_CATALOG . 'maintenance.php') ) {
      //VMN  $maintenance_file = file_get_contents(DIR_FS_CATALOG . 'maintenance.php');
      //VMN  $maintenance_file = preg_replace('%\$back_time = \'(.*)\';%', '\$back_time = \'' . MODULE_HEADER_TAGS_STORE_MODE_BACK_TIME . '\';', $maintenance_file);
      //VMN  file_put_contents(DIR_FS_CATALOG . 'maintenance.php', $maintenance_file);
      //VMN}
      // update the allowed IPs list
      $allowed_ips_array = array();
      $offline_rewrite = null;
      $allowed_ips_array = explode(',', MODULE_HEADER_TAGS_STORE_MODE_ALLOWED_IPS);          
      if (!in_array(getenv('REMOTE_ADDR'), $allowed_ips_array)) {
        $ip_list = getenv('REMOTE_ADDR') . ',' . MODULE_HEADER_TAGS_STORE_MODE_ALLOWED_IPS;
        tep_db_query("update `configuration` set `configuration_value` =  '" . $ip_list . "' where `configuration_key` = 'MODULE_HEADER_TAGS_STORE_MODE_ALLOWED_IPS'");
        $allowed_ips_array = explode(',', $ip_list);          
      }
      // define the .htaccess rewrite rules
      if (MODULE_HEADER_TAGS_STORE_MODE_BACK_TIME != '') {
        $back_time = MODULE_HEADER_TAGS_STORE_MODE_BACK_TIME;
      }
      else {
        $back_time = date('H:i', strtotime('now +2 hour'));
      }
      if ( strpos(MODULE_HEADER_TAGS_STORE_MODE, 'offline') > -1 ) {
        $offline_rewrite = '#Store Mode Begin' . "\n" .
                           '<IfModule mod_rewrite.c>' . "\n" .
                           ' RewriteEngine on'  . "\n" .
                           ' RewriteBase ' . ((getenv('HTTPS') == 'on')? DIR_WS_CATALOG : DIR_WS_HTTPS_CATALOG) . "\n" .
                           ' RewriteRule ^' . ((getenv('HTTPS') == 'on')? str_replace(DIR_WS_CATALOG, '', DIR_WS_ADMIN) : str_replace(DIR_WS_HTTPS_CATALOG, '', DIR_WS_HTTPS_ADMIN)) . ' - [L,NC]' . "\n";
        foreach ($allowed_ips_array as $ip) {
          if (MODULE_HEADER_TAGS_STORE_MODE == 'offline-test') { // define the allowed IPs redirect rules for test mode
            $i++;
            $offline_rewrite .= ' RewriteCond %{REMOTE_ADDR} ^' . str_replace('.', '\.', $ip) . '$' . ($i < sizeof($allowed_ips_array)? '  [OR]' : '') . "\n";
          } elseif (MODULE_HEADER_TAGS_STORE_MODE == 'offline') {// define the allowed IPs exclude redirect rules for normal mode
           $offline_rewrite .= ' RewriteCond %{REMOTE_ADDR} !^' . str_replace('.', '\.', $ip) . '$' . "\n";
          }
        }
        $offline_rewrite .= ' RewriteCond %{REQUEST_URI} !maintenance.php$ [NC]' . "\n" .
                            ' RewriteCond %{REQUEST_URI} !.(jpe?g?|png|gif|css|js) [NC]' . "\n" .
                            ' RewriteRule .* maintenance.php?back_time=' . $back_time. ' [R=307,L]' . "\n" . //VMN                            
                            '</IfModule>' . "\n" .
                            '#Store Mode End' . "\n\n";
        // update the .htaccess file
        $file = file_get_contents(DIR_FS_CATALOG . '.htaccess');
        if ( strpos($file, 'RewriteRule .* maintenance.php? [R=307,L]') === false ) {   //VMN
          htaccess_backup('backup_htaccess');
        } elseif ( strpos($file, 'RewriteRule .* maintenance.php? [R=307,L]') > 0 ) {  //VMN
          $file = preg_replace('@#Store Mode Begin((?:.|[\r\n])+?)#Store Mode End\n\n@', '', $file);
        }
        $file = preg_replace('@ExpiresDefault@','#ExpiresDefault',$file);   //VMN
        
        $content = $offline_rewrite . $file;
        file_put_contents(DIR_FS_CATALOG . '.htaccess', $content);
      } elseif ( (strpos(MODULE_HEADER_TAGS_STORE_MODE, 'offline') === false ) && isset($_GET['module']) && $_GET['module'] == 'ht_store_mode' ) {
        // remove rewrite rules
        $file = file_get_contents(DIR_FS_CATALOG . '.htaccess');
        $file = preg_replace('@#Store Mode Begin((?:.|[\r\n])+?)#Store Mode End\n\n@', '', $file);
        $file = preg_replace('@#ExpiresDefault@','ExpiresDefault',$file);   //VMN
        file_put_contents(DIR_FS_CATALOG . '.htaccess', $file);
      }
    }
    return nl2br(implode("\n", explode(';', $mode_text)));
  }

 
 4. The back_time is set in maintenance.php as follows:
 
 $back_time = '';
if (isset($_GET['back_time'])) {
    $back_time = $_GET['back_time'];
}
if ($back_time == '') {
    $back_time = date('H:i', strtotime('now +2 hour'));
}

Best regards,
Veli-Matti
 
 

Share this post


Link to post
Share on other sites

Hello Veli-Matti @vmn,

I finally found some time to check them:

On 11/30/2018 at 11:37 AM, vmn said:

For Php 7.x:

in includes/modules/header_tags/ht_store_mode.php

-replace
      while (list($id, $value) = each($lng->catalog_languages)) {

-with
      foreach($lng->catalog_languages as $key => $value) {

Thanks, fixed 👍

On 11/30/2018 at 11:37 AM, vmn said:

I noticed that the folder htaccess_backups is browsable.

I checked and get:

Access denied Error 403

It's the same like for the includes folder. So I do not see the need to change something there.

 

On 11/30/2018 at 11:37 AM, vmn said:

I also wanted to add a button to check the shop availability status, as follows:

Great 👍 I added the continue text and button in all languages. As we have now already a button styles, I also changed the Contact link to button.

On 12/5/2018 at 3:53 PM, vmn said:

1. I did not find any other php 7.x related issues.

I found a couple of undefined variable errors and fixed them.

On 12/5/2018 at 3:53 PM, vmn said:

2. Wouldn't it be better to use 307 instead of 302?

503 is used, not 302:

    header("$protocol 503 Service Unavailable", true, 503);
	  header('Status: 503 Service Temporarily Unavailable');
    header("Retry-After: 3600");

This is used since the old versions my add-on is based on. It seems to me correct. See W3org status definition:

503 Service Unavailable

The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response.

 

On 12/5/2018 at 3:53 PM, vmn said:

3. The only way I managed to prevent Firefox cacheing the redirect was to comment out the line

Great 👍, I implemented this.

On 12/5/2018 at 3:53 PM, vmn said:

 4. The back_time is set in maintenance.php as follows:

This brakes the actual coding to hide the backtime information if left empty. Or do I miss something ? Thanks, but I prefer to keep this as is.

 

Thanks again for all your suggestions, great job!

I attach the updated version with my changes so you can have a look and try.

Any comments welcome!

Best regards

Rainer

Store Mode Closed Maintenance BS 1.2.zip

Edited by raiwa

Share this post


Link to post
Share on other sites

Update uploaded:

Store Mode 1.2 BS

Changes Version 1.2:
- Fixed PHP 7.2 compatibility (each function, undefined variable errors). Thanks to @vmn
- fixed cache issues in .htaccess Thanks to @vmn
- added button to check status in mauntenance.php Thanks to @vmn

Share this post


Link to post
Share on other sites

Thanks @raiwa.

Please find below my answers to your comments.

On 12/15/2018 at 8:28 PM, raiwa said:

I checked and get:

Access denied Error 403

It's the same like for the includes folder. So I do not see the need to change something there.

If one knows how this addon works, it may be possible to view htaccess backups by accessing them directly.
This only applies to php files.

<Files *.php>
Order Deny,Allow
Deny from all
</Files>

So, I prefer Require ip <allowed ip's>

On 12/15/2018 at 8:28 PM, raiwa said:

503 is used, not 302:

.htaccess RewriteRule is using 302.

302 = Found
307 = Temporary Redirect

I prefer 307.

On 12/15/2018 at 8:28 PM, raiwa said:

This brakes the actual coding to hide the backtime information if left empty. Or do I miss something ? Thanks, but I prefer to keep this as is.

What's the point of hiding the backtime information, if it's empty?

Share this post


Link to post
Share on other sites
1 hour ago, vmn said:

If one knows how this addon works, it may be possible to view htaccess backups by accessing them directly.
This only applies to php files.

<Files *.php>
Order Deny,Allow
Deny from all
</Files>

So, I prefer Require ip <allowed ip's>

OK. Got it!

 

1 hour ago, vmn said:

.htaccess RewriteRule is using 302.

302 = Found
307 = Temporary Redirect

OK Got it!

1 hour ago, vmn said:

What's the point of hiding the backtime information, if it's empty?

During development of a new store  which may take still weeks or months to go online.

I think the best would be to add all 3 options:

- back in x hours specified in the module like now

- back in 2 hours dynamically shown if empty => your add

- new configuration entry to hide the back in xx h message => like now if left empty

Let me know your thoughts and I'll update it when I find some time.

 

Thanks and best regards
Rainer

Share this post


Link to post
Share on other sites

Uploaded update:

Store Mode 1.2.1 BS

Changes Version 1.2.1:

- Changed .htaccess protection for backup directory and files. Thanks to @vmn
- Changed redirect to 307 Thanks to @vmn
- Added back time setting to 2 hours if no time is entered in ht module. Thanks to @vmn
- Added show/hide back time configuration setting in ht module.
- Update header content module to auto include template file and new template file naming standard.

Share this post


Link to post
Share on other sites

Sorry for the delay.

I updated to 1.2.1.

Looks good, thanks.

Share this post


Link to post
Share on other sites

I forgot to point out, that I only plan to use and have tested the "offline" mode.
I use a local environment to develop and test my changes.

"Logoff customers
Do you want to logoff customers? Applies on all modes except online."

This does not apply to "offline" mode.

After noticing the above, I also wanted to clarify what happens, if a customer has a non-empty shopping cart, in case of maintenance.

This is my new maintenance message text:

  define('TEXT_MAINTENANCE_MESSAGE_ENGLISH', 'We are currently maintaining the Web Shop.<br><br>We apologize for any inconvenience this may cause.<br><br><strong>If your shopping cart was not empty, it will be preserved as follows</strong>:<ul style="text-align:left"><li>logged in customers:<strong> always</strong> (even if you close your browser)</li><li>others: <strong>unless</strong> you close your browser</li></ul>');

I checked the html source with W3C Markup Validation Service (https://validator.w3.org/).
Based on the results I made the following changes in maintenance.php:

-after
    header("Retry-After: 3600");
-added
    header("Cache-Control: no-cache, must-revalidate");
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
    
-replaced
  <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
-with
  <!DOCTYPE html>
 
-removed
  <meta http-equiv="Cache-Control" content="no-cache">
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<meta name="HandheldFriendly" content="true">

I tested the offline mode with my Android phone. No problems with scaling down the output.

-replaced
<style type="text/css">

-with
<style>

Buttons without a form:

-replaced
    <form>
      <input type="button"  class="button" value="Continue" onclick="window.location.href='<?php echo dirname($_SERVER["REQUEST_URI"])."/index.php?language=en";?>'" />
    </form>

-with
    <button class="button" onclick="window.location.href='<?php echo dirname($_SERVER["REQUEST_URI"])."/index.php?language=en";?>'">Continue</button>

Share this post


Link to post
Share on other sites
Posted (edited)

@vmn,

Thank you . I'll have a look on this.

Meanwhile I found that on my server "dirname($_SERVER["REQUEST_URI"])" dosensn't work. I get an empty value.

So I tried and found that the following works for me and also addresses the problem if there is a server wide redirect to SSL implemented:

  $url  = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
  $url .= $_SERVER['SERVER_NAME']. dirname($_SERVER["REQUEST_URI"]);

....

      <input type="button"  class="button" value="Continue" onclick="window.location.href='<?php echo $url."/index.php?language=en";?>'" />

Can you confirm this?

 

Edited by raiwa

Share this post


Link to post
Share on other sites
2 hours ago, raiwa said:

Can you confirm this?

Works for me, too.

Share this post


Link to post
Share on other sites

Hi,
I noticed that my fix for commenting out the ExpiresDefault line in .htaccess does not check whether the line is already commented out. This happens if I switch between offline and offline-test without switching to online in between. Also someone may have intentionally commented it out.

So, in includes/modules/header_tags/ht_store_mode.php:

find:
        $file = preg_replace('@ExpiresDefault@','#ExpiresDefault',$file);   //VMN

replace the line with:
        //Is ExpiresDefault already commented out by us?                                                                      //VMN
        if ( strpos($file, '#Store Mode comment:ExpiresDefault') === false ) {                                     //VMN
            $file = preg_replace('@ExpiresDefault@','#Store Mode comment:ExpiresDefault',$file);   //VMN
        }                                                                                                                                                             //VMN

find:
        $file = preg_replace('@#ExpiresDefault@','ExpiresDefault',$file);   //VMN

replace the line with:
        $file = preg_replace('@#Store Mode comment:ExpiresDefault@','ExpiresDefault',$file);     //VMN

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×