June 28, 2017

Auto version your JavaScript or Stylesheet files using .htaccess

Usually, developers can maintain the cache they maintain themselves at the backend but cannot control the cache held by the browser as freely as they want unless there is proper version control. Here is a quick drop in solution in `.htaccess` file until you have proper versioning.

Most of the applications have one or many layers of cache for their system. The cache that application developer can maintain is at the backend (the server) level. However, you cannot control the cache held by the browser as freely as you want unless you version the files as well.

Versioning the files is definitely the best way to solve this problem because it is a very efficient solution which guarantees that browser will fetch the new resource when you want it to. But there are cases where this is not an easy step to be taken, for example, in a legacy app which resources are included in line the page.

So, is there a quick way to fix the problem until you go to proper versioning?

Yes! there is.

Using .htaccess we can auto version the files and force the browser to fetch files down to every second if we need to.

Here is how:

We can use server variables such as TIME_YEAR, TIME_MONTH to create an automatic version of your resource. These are variables that the web server provide to be used where suitable. And now, let’s see how to do this.

RewriteCond %{QUERY_STRING} !(v=(.<em>))
Rewriterule ^(js|scripts|css|styles)(.</em>)$ /$1$2?v=%{TIME_YEAR}%{TIME_MON}%{TIME_DAY}%{TIME_HOUR} [r=302,nc]`

Open your .htaccess files and paste those two lines in. What these are doing is:

  • If a request comes to the server that starts with js, scripts, css or styles then rewrite the request by appending an auto-created version at the end.
  • IF a request comes with the version already in the request then don’t do anything because we don’t want it to keep rewriting the request.

Simple as that. So for example: if the request comes to https://abc.com/js/main.js it gets served as https://abc.com/js/main.js?v=2017062811. Same goes for any request coming to other paths as well. This example ensures that browser will fetch the resource again every hour. But if you add variables like TIME_MINUTE or TIME_SECOND or TIME browser will keep fetching the content more frequently.

To see what other server variables can be used visit https://httpd.apache.org/docs/trunk/expr.html#vars

September 12, 2013

Using mod_rewrite to make Blog URLs more SEO Friendly

Three3’s Question:

I am trying to turn my blog URLs into a more SEO friendly format using mod_rewrite. All of my articles are stored in a simple MySQL database. Each blog article url looks like this:

http://www.test.com/blog?id=20&category=online%20php%20tutorials&pagename=how%20to%20customize%20functions

I have managed to to make them look like this using mod_rewrite:

http://www.test.com/blog/online-php-tutorials/how-to-customize-functions/20

Here is my code that I paced in my .htaccess file:

RewriteRule ^blog/([a-z0-9-]+)/([a-z0-9-]+)/([a-z0-9-]+)/?$ /blog?id=$3&category=$1&pagename=$2 [L]

So what happens is this: When I click on the URL http://www.test.com/blog/online-php-tutorials/how-to-customize-functions/20, all of my CSS and images are not loading because it is trying to load them from a directory that does not actually exists. How would I load the files without having to create multiple directories that contain my sites CSS files and images?

Use root identifier / in your path. This will point the DocumentRoot of your server. Let me explain How this works

For an image like this:

<img src='test.jpg' /> 

Browser/Server will find it as http://www.test.com/blog/online-php-tutorials/how-to-customize-functions/20/test.jpg' but if you use / before the path

<img src='/test.jpg' />

It will look for it in http://www.test.com/test.jpg

Another Technique

Use full path in your files like:

<img src='http://test.com/test.jpg' />
June 18, 2013

Disable direct access to files in PHP

Mr Me’s Question:

I’ve already checked the issue disable access to included files , but I am wondering if that’s the best solution.

Context: I’m building a bootstrap class for my PHP Framework, and realized that there are multiple solutions to this security issue.

After researching and reading posts like the one I mentioned at first and others related to htaccess, I think that there are basically three types of solutions:

1 – Checking a constant (like in the post I linked)

if(!defined('THIS_IS_NOT_A_DIRECT_ACCESS')) {
    header('HTTP/1.1 404 Not Found');
    include('./../error/404.php');
    die;
}

Or

require('../error/include_file.php');
//
if(!defined('THIS_IS_NOT_A_DIRECT_ACCESS'))
{
    header('HTTP/1.1 404 Not Found');
    include('404.php');  
    die; 
}

2 – Redirecting all calls to the Bootstrap and making a clever filtering.

//Something like
// if $urlRequested it's a file
    // Go to Error
// else if $urlRequested it's not a controller
    // Go to Error
// else 
    // Execute Controller Logic.

3 – Setting htaccess.

# Redirecting calls for non-directories, files or links
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.+)$ index.php?url=$1 [QSA]

# Redirecting the rest of the calls to the error page.
RewriteRule ^(.+)$ index.php?url=error/404 [QSA]

Personally I think the solution 3 is the most interesting, but I am pretty new in the Htaccess control so I wonder if this is a safe solution.

For the purists and minimalists, the Question in here would be:
Are these (the three examples) nice direct access control systems for Apache-PHP applications? Else, which would be the safest approach? And the simplest?

This is a debatable topic but .htaccess rules applies to all the document on that particular directory. While applying 1 or 2 you may have to include that portion on every file.

Apache is not executing PHP scripts

User2495173’s Question:

I changed the httpd.conf as follows:

  • Replaced

    DocumentRoot "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs"
    

    with

    DocumentRoot "C:/Temp/WebServerCore/Binaries/html"
    
  • Replaced

    <Directory "C:/Program Files (x86)/Apache Software Foundation/Apache2.2/htdocs">
    

    with

    <Directory "C:/Temp/WebServerCore/Binaries/html">
    

However Apache does not recognize the php code in my .html file. What other changes do I need to make for Apache to execute PHP?

It is by design. Apache will not parse PHP code inside a HTML file by default. You can include HTML codes in a PHP file as you would code them in a HTML document.

Renames your files and add extension .php at the end they will parsed as you want.

Or you can configure your apache configuration (httpd.conf) to parse PHP code inside HTML too.

AddHandler application/x-httpd-php5 .html .htm

Or you can match extension and set their handlers like

<FilesMatch ".(htm|html|php)$">
     SetHandler application/x-httpd-php
</FilesMatch>
June 2, 2013

apache_request_headers() versus $_SERVER

User1032531’s Question:

As far as I can tell, apache_request_headers() provides the same information as $_SERVER, but with slightly different keys. Why should someone ever use apache_request_headers() and not just get this information from $_SERVER? I am operating PHP 5.3.18 with Apache on Centos. Thank you

EDIT. identical data from $_SERVER and apache_request_headers()

Jun  2 08:50:53 localhost httpd: HTTP_HOST: www.badobe.com
Jun  2 08:50:53 localhost httpd: Host: www.badobe.com
Jun  2 08:50:53 localhost httpd: HTTP_USER_AGENT: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Jun  2 08:50:53 localhost httpd: User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Jun  2 08:50:53 localhost httpd: HTTP_ACCEPT: */*
Jun  2 08:50:53 localhost httpd: Accept: */*
Jun  2 08:50:53 localhost httpd: HTTP_ACCEPT_LANGUAGE: en-US,en;q=0.5
Jun  2 08:50:53 localhost httpd: Accept-Language: en-US,en;q=0.5
Jun  2 08:50:53 localhost httpd: HTTP_ACCEPT_ENCODING: gzip, deflate
Jun  2 08:50:53 localhost httpd: Accept-Encoding: gzip, deflate
Jun  2 08:50:53 localhost httpd: HTTP_REFERER: http://www.badobe.com/demo/administrator/index.php?cid=3
Jun  2 08:50:53 localhost httpd: Referer: http://www.badobe.com/demo/administrator/index.php?cid=3
Jun  2 08:50:53 localhost httpd: HTTP_COOKIE: PHPSESSID=feg3ecd4rsefvd03mgg6qear21
Jun  2 08:50:53 localhost httpd: Cookie: PHPSESSID=feg3ecd4rsefvd03mgg6qear21
Jun  2 08:50:53 localhost httpd: HTTP_CONNECTION: keep-alive
Jun  2 08:50:53 localhost httpd: Connection: keep-alive
Jun  2 08:50:53 localhost httpd: HTTP_IF_MODIFIED_SINCE: Sun, 02 Jun 2013 15:48:42 GMT
Jun  2 08:50:53 localhost httpd: If-Modified-Since: Sun, 02 Jun 2013 15:48:42 GMT
Jun  2 08:50:53 localhost httpd: HTTP_CACHE_CONTROL: max-age=0
Jun  2 08:50:53 localhost httpd: Cache-Control: max-age=0

Because apache_request_headers() returns an associative array of all the HTTP headers in the current request, where as $_SERVER gives more than that

  • header details
  • path details
  • script locations
March 9, 2013

Running a Zend Framework Project on a shared server

Question by Mikey

I’m trying to upload my ZF Project to shared hosting

On my XAMPP, ZF’s index page is located (and I access my page) at http://localhost/ZFprojectname/public

On the shared hosting in the root directory I have installed Joomla.

I want to access my ZF in the manner of http://mywebsite.com/booking/

so in this case, when going to http://mywebsite.com/booking/ I should be accessing ZF’s public folder (as far as I understand).

And, I’d like to put my ZFproject in public_html/somefolderName/

How would you do it?

Answer by Starx

Shared hosting do not support defining Document Root path so you can use .htaccess to forward the request to public folder instead.

Create a .htaccess file inside the booking directory with the following rule.

RewriteEngine On

RewriteRule ^.htaccess$ - [F]

RewriteCond %{REQUEST_URI} =""
RewriteRule ^.*$ /public/index.php [NC,L]

RewriteCond %{REQUEST_URI} !^/public/.*$
RewriteRule ^(.*)$ /public/$1

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [NC,L]

RewriteRule ^public/.*$ /public/index.php [NC,L]
October 9, 2012

Load php_oauth.dll into local server

Question by Nich

I’m facing problem to load the php_oauth.dll extension for my xampp. I downloaded the php_oauth.dll and added extension=php_oauth.dll in php.ini , but when i restart my apache, it cannot start the server anymore.

I’m using window 7 ,64bits.
Initially, I download the file from
http://downloads.php.net/pierre/

but i found that it was 32bits file , so I’m searching fo 64bit and found out
http://www.mediafire.com/php-win64-extensions

unfortunately,I still cannot load the oauth. Any solution to solve it? I look through many article, but it seems like dont have it, anyone can provide ,so that, others that using win 64bit can follow

Thank you!

Answer by Starx

This looks to be like a path problem. Make sure the extension is store in the correct extension directory.

The settings of this can be found inside php.ini as something like

extension_dir = C:phpextensions

By default this is ext folder inside PHP installation.

Or, follow the instruction from PHP manual while installing extensions, if you are not sure what you are doing.

September 18, 2012

How to ensure JPEG image is valid and can be handled by PHP?

Question by Nyxynyx

I have this JPEG that has been giving problems to the function imagesx($this->image) from the Resizer library that I am using. I am able to view the image using the browser, and when attempting to resize, I get the error:

imagesx() expects parameter 1 to be resource, boolean given

It is OK for me to not handle this file if it is going to throw an error. How can I use PHP to check whether this image can be handled properly by PHP’s image functions?


Code that calls the Library

// Download the photo
$img_content = file_get_contents($url);
if($img_content !== FALSE) {
    file_put_contents($img_documentroot . $img_subpath . $img_filename . '_tmp.jpg',
     $img_content);
}

echo $url . '<br>';
echo $img_documentroot . $img_subpath . $img_filename . '_tmp.jpg<br>';
ob_flush();
flush();

// Resize photo
Resizer::open( $img_documentroot . $img_subpath . $img_filename . '_tmp.jpg' )
->resize(300, 300, 'landscape' )
->save($img_documentroot . $img_subpath . $img_filename . '.jpg' , 90 );

// Thumbnail photo
Resizer::open( $img_documentroot . $img_subpath . $img_filename . '_tmp.jpg' )
->resize(100, 100, 'crop' )
->save($img_documentroot . $img_subpath . $img_filename . '.jpg' , 90 );

Output

I also echoed out the full path of the image being resized.

http://www.ApartmentsInAllstonMA.com/Images/Apts/132847_kn1.jpg
/home/photos/public_html/2012/0917/2516539_7_tmp.jpg
resource(127) of type (gd)
resource(130) of type (gd)
http://www.ApartmentsInMedford.com/Images/Apts/132847_lv2.jpg
/home/photos/public_html/2012/0917/2516539_11_tmp.jpg
resource(163) of type (gd)
resource(166) of type (gd)
http://www.AllstonApartmentX.com/images/agents/61.jpg
/home/photos/public_html/2012/0917/2516539_12_tmp.jpg
bool(false)

UPDATE

This is the code snippet that is causing the library to return a false value.

private function open_image( $file )
{

    // If $file isn't an array, we'll turn it into one
    if ( !is_array($file) ) {
        $file = array(
            'type'      => File::mime( strtolower(File::extension($file)) ),
            'tmp_name'  => $file
        );
    }

    $mime = $file['type'];
    $file_path = $file['tmp_name'];

    switch ( $mime )
    {
        case 'image/pjpeg': // IE6
        case File::mime('jpg'): $img = @imagecreatefromjpeg( $file_path );  break;
        case File::mime('gif'): $img = @imagecreatefromgif( $file_path );   break;
        case File::mime('png'): $img = @imagecreatefrompng( $file_path );   break;
        default:                $img = false;                               break;
    }

    return $img;
}

Answer by Starx

Checking for the mime type is a very good method to ensure the validity of JPEG image. Here is how you can do this.

$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type
$type = finfo_file($finfo, $filename) . "n";  
if($type == "image/jpeg") { 
     //Valid JPEG Image
}
finfo_close($finfo);

According to your errors, you are sending boolean value instead of image resource.

May 6, 2012

Changing ip address of apache server using php

Question by apurv nerlekar

I am trying to create a settings page(for the clients) where in they can view the current up address,change the ip address etc. I have a php file to view the ip address

 <?php
  $res=shell_exec("ifconfig");
  echo $res;
 ?>

This code works just fine and displays the expected result.
However the code to change the ip address of the server is not working properly.

 <?php
 shell_exec("ifconfig eth0 192.168.163.136");
 ?>

After running this code when i check the ipaddress on the terminal using ipaddr i don’t see any change in the ipaddress.
Pls point out where i am going wrong. I think its a problem of apache not being a super/root user. If that is the case i don’t know how to make apache run as a root user.

Answer by Starx

IP address are configured in Network Layer of an Network Protocol, not in application layer where PHP runs. Simply, PHP does not have access to it and cannot changed them.

Just imagine the vulnerabilities it could create if this was possible.

May 4, 2012

Zend 1.10 place websites in virtual subdirectories

Question by Julien

I have the following situation:
We have a webapp built with Zend Framework 1.10 that is available under www.domain.com/webapp

On the server filesystem, we really also have the webapp deployed in /srv/www/webapp

Now, for some reasons I can’t detail too much, the project manager has requested, now that the app is finished, that each client recieves his own url litteraly.
So we would have:
www.domain.com/webapp/client1
www.domain.com/webapp/client2

Normally, what start after the webapp/ would be the controllers, actions and so forth from zend.

Therefore the question: is there a quick way in apache to create these virtual subdirectories, as in the example, client1, client2 ?

I guess it should be possible with url rewriting ?

Thanks in advance

Answer by Starx

Rather than creating virtual directories, this can be solved by creating a specific route with Zend_Route. Assuming, controller as User and the action to pass the name would be view, then

$route = new Zend_Controller_Router_Route(
    'webapp/:username',
    array(
        'controller' => 'user',
        'action'     => 'view',
        'username'   => 'defaultuser'
    )
);
...

Please fill the form - I will response as fast as I can!