Remove payment options for free products in WHMCS 5

Posted in WHMCS on May 18th, 2012 by Joonas – Be the first to comment

WHMCS by default requires that every order has a payment type associated with it regardless whether the order is free or not. This means that the default functionality of WHMCS is to display the payment options on the checkout form every time. This can be very confusing for a customer that expects a free product, but then is required to select a payment type.

On a current project that I am a part of, I had to remove the payment options for free checkouts. It turned out to be quite simple.

The Concept

The idea is to put a <div> around the payment options and set style=”display:none;” on the div if the order total is zero.

The Solution

In my project, I was using the Web20cart theme for the checkout pages. The concept will work for any of the cart themes that come with WHMCS and probably with any custom theme as well.

In templates/orderforms/web20cart/viewcart.tpl, find the code block that looks like this:

<h2>{$LANG.orderpaymentmethod}</h2>
  <div class="cartbox">{foreach key=num item=gateway from=$gateways}
    <label><input type="radio" name="paymentmethod" value="{$gateway.sysname}" onclick="{if $gateway.type eq "CC"}showCCForm(){else}hideCCForm(){/if}"{if $selectedgateway eq $gateway.sysname} checked{/if} /> {$gateway.name}</label>
    {/foreach}</div>

Put the codeblock inside a <div> that has a trigger for the style=”display:none;” attribute, so the payment options are hidden if the order total is zero dollars.

<div {if intval(substr($total,1,-4)) == 0}style="display:none;"{/if}>
  <h2>{$LANG.orderpaymentmethod}</h2>
  <div class="cartbox">{foreach key=num item=gateway from=$gateways}
    <label><input type="radio" name="paymentmethod" value="{$gateway.sysname}" onclick="{if $gateway.type eq "CC"}showCCForm(){else}hideCCForm(){/if}"{if $selectedgateway eq $gateway.sysname} checked{/if} /> {$gateway.name}</label>
    {/foreach}</div>
</div>

How to clear cache for Adobe Flash 11.x

Posted in Flash on May 15th, 2012 by Joonas – Be the first to comment

Clearing cache for Adobe Flash is easy. Just follow the steps below.

  1. Right click any flash application (a Youtube video for example) and click the “Global Settings” option
  2. Click the “Advanced” tab and click the “Delete All” button
  3. Choose the data that you want to delete and click the “Delete Data” button

How to fix WHMCS SEO URLs that are not working

Posted in WHMCS on May 9th, 2012 by Joonas – Be the first to comment

WHMCS offers an SEO friendly URLs option in the adminstration panel. The steps to enable them are documented in the official support center article, so check there for how to enable them.

Search Engine Friendly URLs are where a URL which once was “/knowledgebase.php?action=view&id=1″ becomes “/knowledgebase/1/How_do_I_access_my_control_panel.html”. You can enable these for the announcements, downloads and knowledgebase sections of the WHMCS client area.

I recently had to setup WHMCS 5 on a brand new cloud server running a fresh LAMP install on Debian. I had to install curl and ioncube… no problems there. I uploaded WHMCS and configured it with the official instructions and got everything working. In the admin panel, I wanted to enable SEO friendly URLs for the website, so I checked the associated box and hit save. I also renamed the htaccess.txt to .htaccess as instructed. At first everything seemed to work properly, I could navigate to the knowledge base, downloads, and announcement sections.

The Problem

The problem was that after I added some articles to the knowledgebase and tried to go view the article, the SEO URL appeared in my browser’s URL bar, but the page stayed on the main Knowledgebase index with the categories and most viewed articles.

The Solution

I was baffled for a little bit. I double checked my .htaccess file, made sure mod_rewrite was installed and working, but I couldn’t find what was wrong. After some digging around it turned out that the Apache installation that I had on my server was configured with “Options +MultiViews” as default. The solution was to add “Options -MultiViews” to the top of the WHMCS .htaccess file. Everything started working as expected.

Validate VIN checksum with PHP

Posted in Auto Industry, Business & Development, PHP on May 7th, 2012 by Joonas – Be the first to comment

While working on something very secretive for StarAuto CMS, I came across the need to validate a VIN with the checksum algorithm defined by the Vehicle Identification Number article on Wikipedia. I whipped up a simple PHP class to handle the task.

class VIN
{
    public static $transliteration = array(
        'A'=>1, 'B'=>2, 'C'=>3, 'D'=>4, 'E'=>5, 'F'=>6, 'G'=>7, 'H'=>8, 
        'J'=>1, 'K'=>2, 'L'=>3, 'M'=>4, 'N'=>5, 'P'=>7, 'R'=>9,
        'S'=>2, 'T'=>3, 'U'=>4, 'V'=>5, 'W'=>6, 'X'=>7, 'Y'=>8, 'Z'=>9,
    );
 
    public static $weights = array(8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2);
 
    /***
     * The checksum method is used to validate whether or not a VIN is valid
     * It will return an array with two keys: status and message
     * The "status" will either be boolean TRUE or FALSE
     * The "message" will be a string describing the status
     */
    public static function checksum($vin)
    {
        $vin = strtoupper($vin);
        $length = strlen($vin);
        $sum = 0;
 
        if($length != 17)
        {
            return array('status'=>false, 'message'=>'VIN is not the right length');
        }
 
        for($x=0; $x<$length; $x++)
        {
            $char = substr($vin, $x, 1);
 
            if(is_numeric($char))
            {
                $sum += $char * self::$weights[$x];
            }
            else
            {
                if(!isset(self::$transliteration[$char]))
                {
                    return array('status'=>false, 'message'=>'VIN contains an invalid character.');
                }
 
                $sum += self::$transliteration[$char] * self::$weights[$x];
            }
        }
 
        $remainder = $sum % 11;
        $checkdigit = $remainder == 10 ? 'X' : $remainder;
 
        if(substr($vin, 8, 1) != $checkdigit)
        {
            return array('status'=>false, 'message'=>'The VIN is not valid.');
        }
 
        return array('status'=>true, 'message'=>'The VIN is valid.');
    }
}

The one and only function of the class is to validate the checksum of a VIN and determine if the VIN is valid or invalid. Check the code below for some test output.

$vin = '1G1YW2DW0A5108451';
$checksum = VIN::checksum($vin);
 
var_dump($vin);
var_dump($checksum);

The VIN number in the sample is valid, so the output reflects that.

string(17) "1G1YW2DW0A5108451"
array(2) {
  ["status"]=>
  bool(true)
  ["message"]=>
  string(17) "The VIN is valid."
}

Hopefully someone will find this code useful.

Converting a number to an alphabetical representation

Posted in PHP on May 3rd, 2012 by Joonas – Be the first to comment

I came across a situation where initial order numbers were being built like ORDER12345 and orders related to the initial order were coming out as ORDER12345-1, ORDER12345-2, ORDER12345-3, etc. This worked fine and the relationships were easily human readable, but some other integrated systems that these orders were being sent to were cutting off the order number because they could only accept 11 characters for an order number.

For example, the integrated shipping system 0nly accepted 11 characters, so when a 12 character order number (ORDER12345-1) was sent to the system, it was getting cut off and ended up being (ORDER12345-). This was unacceptable because anybody looking at the shipping label could not tell which related order was in question by looking at the order number.

The solution that was decided upon was to remove the dash and numbers from the related orders and replace them with an alphabetical representation. So a “ORDER12345-1″ would become “ORDER12345A”,  ”ORDER12345-2″ would become “ORDER12345B”, etc.

I ended up writing a function do convert an integer in to an alphabetical representation. If the number passed to the function is greater than the number of letters in the alphabet, the functions uses to letters to describe the number. See the PHP function below.

function number2alpha($number, $case='UPPER')
{
	$alpha = '';
	$number = intval($number);
 
	# The ASCII decimal range for lowercase letters is 97 (a) to 122 (z)
	# for uppercase letters it is 65 (A) to 90 (Z)
	# The default for this function is uppercase
	$min = 65;
	$max = 90;
 
	# If you specify LOWER as the $case, we switch to lowercase number range
	if(strtoupper($case) == 'LOWER')
	{
		$min = 97;
		$max = 122;
	}
 
	# Decrement number by one if it is greater than one
	# This allows us to always start with the letter "A" or "a" accordingly
	if($number > 0)
	{
		$number--;
	}
 
	# Determine whether to start counting from a lowercase "a" or an uppercase "A"
	# This also determines what case the rest of the letters will use
	$number = $min + $number;
 
	# If the number we are translating to letter is greater than the maximum for the range,
	# it means that we need to roll over to using two letters, ex. AA, AB, AC, etc.
	# this part uses recursion and calls this same function again for the remainder...
	if($number > $max)
	{
		$alpha .= chr($min).number2alpha($number-$max, $case);
	}
	else
	{
		# If the number falls within the range, just put in one character
		$alpha .= chr($number);
	}
 
	return $alpha;
}

The comments in the above code explain the different parts of the logic, so I won’t write about it again. Instead, I will provide an usage sample and the output.

$results = array(
	'uppercase_test_1'   => number2alpha(1),
	'uppercase_test_15'  => number2alpha(15),
	'uppercase_test_26'  => number2alpha(26),
	'uppercase_test_40'  => number2alpha(40),
	'uppercase_test_104' => number2alpha(104),
	'lowercase_test_1'   => number2alpha(1, 'LOWER'),
	'lowercase_test_15'  => number2alpha(15, 'LOWER'),
	'lowercase_test_26'  => number2alpha(26, 'LOWER'),
	'lowercase_test_40'  => number2alpha(40, 'LOWER'),
	'lowercase_test_104' => number2alpha(104, 'LOWER'),
);
 
print_r($results);

The output of the above test is the following:

Array
(
    [uppercase_test_1] => A
    [uppercase_test_15] => O
    [uppercase_test_26] => Z
    [uppercase_test_40] => AN
    [uppercase_test_104] => AAAZ
    [lowercase_test_1] => a
    [lowercase_test_15] => o
    [lowercase_test_26] => z
    [lowercase_test_40] => an
    [lowercase_test_104] => aaaz
)

Completely automated, hosted website solution for car dealerships

Posted in Business & Development, Case Studies on May 2nd, 2012 by Joonas – Be the first to comment

Most car dealerships are not big brand name dealerships and they do not have entire internet departments dedicated to maximizing their profit potential by leveraging social media, search engine optimization, and a rockstar website. I identified this problem in the industry back in 2007 when I was shopping for a used car in Tucson (Arizona) and found it difficult to research my options online. There were tons of car dealers in Tucson. I knew this because I drove by tons of them on my way to work and back. I drafted some plans with a good friend of mine on how to solve the problem for the smaller car dealerships and car lots. In 2011, we finally launched StarAuto CMS, which is a complete website solution for small to medium sized car dealers.

Why do small car dealers not have websites?

The reason most of the smaller car dealers do not have websites is because they do not (or think they don’t) have the necessary technical skills to build/maintain a website. Others shy away from getting a website due to startup costs and ridiculous monthly upkeep fees. We built StarAuto CMS to address all of these problems and concerns.

Lack of technical skills is not a valid reason anymore!

In order to address the tech skills concern, we made StarAuto CMS in to a hosted service. This means that we host the website on our server and manage the hardware and software. We keep the server and website up to date with latest updates and security patches. The car dealer does not have to be tech savvy to run and maintain a StarAuto CMS powered website. The solution comes with an easy to use online control panel that the car dealer can use to easily manage every page of their website, configuration options, and the inventory and associated pictures. The car dealer is in complete control of their website.

A website should not be a bank breaker.

We solved the startup cost and upkeep fee problem by making StarAuto CMS a standardized solution with complete automation. Other car dealer website providers build custom websites for each dealership. This means that the other providers have to have staff members actively building, deploying, and maintaining websites for their customers. We do not have to do that, which allows us to minimize the cost to StarAuto CMS customers. When a new customer signs up for a StarAuto CMS, their website is setup immediately. Most small to medium sized car dealers need similar websites, so we built StarAuto CMS with a standard feature set that satisfies most of the small to medium sized car dealers. The customers that need further enhancements, can then get in touch with us an commission custom work for additional components to StarAuto CMS that are specific to their business model.

Every business needs a website.

Internet is a very important sales tool in today’s world and there is no reason that every business is not using it to maximize their marketing reach and profits.

“A record 67.5 percent of new vehicle buyers in the U.S. researched their purchase online while shopping for a vehicle last year.” - J.D. Powers and Associates

We believe that every car dealership needs a website; therefore, we made StarAuto CMS the most affordable car dealer website solution. In fact, any car dealer is able to sign up for a completely FREE version of StarAuto CMS. The free version is not a trial, it does not lack features, and it does not expire. It is a fast an easy way for car dealers to test StarAuto CMS for real and determine if it fits their business model. If it does, they can upgrade their service to a paid version starting at $15 per month. At the time of writing, StarAuto CMS is the most affordable and fastest way for a car dealership to launch a web presence.

The technology behind StarAuto CMS (for the techies).

We wanted StarAuto CMS to be flexible, light weight, and powerful; so we decided to use PHP5 and the Kohana Framework 3.2 to build the software. The package is split in to three different pieces. The first piece is the Kohana 3.2 core. The other two pieces are the control panel and the frontend layer. Both the control panel and the frontend share the Kohana core files, so when framework upgrades are necessary, upgrades will only have to happen in one location.

Naturally we cannot host all clients on the same server, so we built the project in such a way that the code base can be deployed on multiple servers that operate independently. This allowed us to easily leverage WHMCS 5 for server allocation. When a new customer signs up, WHMCS determines which server has the least amount of customers hosted on it and deploys the new website there, effectively balancing the load on our servers.

When we were configuring WHMCS for our purposes, there were some incompatibility issues between the latest PLESK10 and WHMCS5, so we had to solve some problems. I wrote posts about those solutions in the past. You can find those posts in the PLESK category on this blog.

The Square Coloring Game

Posted in Javascript, XHTML on April 25th, 2012 by Joonas – Be the first to comment

The Square Coloring Game

I found myself with some “free time” on my hands on April 19 and decided to fiddle with some javascript to pass the time. I ended up writing a simple coloring game. You get to choose the size for your squares in pixels and then the game generates a blank page for you that you have to color by hovering your mouse over the squares. The game tracks how many squares are on your screen and how many you have colored. Once you have colored all your games, you get a message saying how many microseconds it took you to color all the squares.

You can play the game at the following link:
http://dev.strategystar.net/examples/the-square-coloring-game/

The game is really simple and doesn’t use any third party javascript libraries. You can view the game code at the following link:
http://dev.strategystar.net/examples/the-square-coloring-game/game.js

Execute SCP with PHP and capture the output

Posted in PHP on March 14th, 2012 by Joonas – 1 Comment

Most people attempt to capture the progress bar output from SCP when they run the command via PHP’s exec or shell_exec functions, so that they can determine which files SCP moved, usually by parsing the output with preg_match. First of all, SCP only sends the progress bar output if the command is run from an interactive shell like your putty or terminal, but when PHP executes the command without an interactive shell, SCP just doesn’t send the output at all, so capturing the progress bar output is VERY difficult and not worth it, considering the other option.

The other option (solution) is to use the verbose flag on SCP and redirect STDERR to STDOUT. This allows PHP to capture detailed output including any errors that come up.

Your PHP code should look something like…

<?php
 
$source = 'serverA:/tmp/source/*';
$destination = 'serverB:/tmp/destination/*';
 
# 2>&1 redirects STDERR output to STDOUT and -v enables verbose output
$cmd = sprintf("scp -q -v %s %s 2>&1", $source, $destination);
$out = shell_exec($cmd);
 
var_dump($out);
 
?>

If you run the above script, with your configuration of course, and var_dump the output, you should see a lot of junk related to authentication, but in the midst of the madness, you should see the messages that indicate what files were uploaded or downloaded. You can use a regular expression on that output to capture the files that were moved by SCP.

The SCP output should have lines like this that indicate which files were moved:

Sending file modes: C0644 212531 myfile-03132012.csv
Sink: C0644 212531 myfile-03132012.csv

Enjoy. Leave comments if you have questions or suggestions.

Update to using WHMCS 5 with Plesk 10.4 and enabling graceful Apache restarts

Posted in MySQL, PLESK, WHMCS on March 1st, 2012 by Joonas – Be the first to comment

We just upgraded our server software for our StarAuto CMS product and we came across a new Apache restart issue with Plesk 10.4 after a new account is created. Our WHMCS installation was also upgraded to 5. By default, Plesk 10.4 does a hard restart after any account creation or modification action, but we can’t have the service be interrupted abruptly for a few moments when ever a new client website is setup, so we had to browse around and figure out a solution.

The solution is to add a record to the Plesk (psa) database on the server where Plesk is installed. First, log in to MySQL as root (admin) and switch to the psa database. Then run the following insert to enable graceful Apache restarts.

INSERT INTO misc VALUES ('restart_apache_gracefully', 'true');

By using this method, which is actually outlined in the Parallels knowledgebase, you no longer have to use the nasty work around that we used and explained in our previous post, “Integrating WHMCS 4.x with PLESK 10“, about getting around the hard Apache resets.

Our service runs on a DV server from MediaTemple and we change our admin account password frequently for security reasons, but the root password for MySQL doesn’t change automatically, so we had forgotten our root MySQL password (silly), so we retrieved it by following the instructions from Plesk.

On server with Parallels Plesk Panel versions 8.x, 9.x and above admin password is stored in file /etc/psa/.psa.shadow. Use the following command to get the password:

~# cat /etc/psa/.psa.shadow

Since version 10 admin password stored in file /etc/psa/.psa.shadow is encrypted. Use the following command to get admin password in plain text:

~# /usr/local/psa/bin/admin –show-password

Despite version of Parallels Plesk Panel you may use the following command to login to mysql with root privileges:

~# mysql -uadmin -p`cat /etc/psa/.psa.shadow`

How to change the root password in Linux

Posted in Linux on February 12th, 2012 by Joonas – Be the first to comment

Changing the root password in Linux is super easy.

  1. Simply login to your server as root via SSH
  2. Type “passwd” in the command prompt.

The “passwd” program will prompt you for your current password and then the new password that you want to set.

This command works on all the modern Linux distributions. If you need help using the command, type “man passwd” in your command prompt.

Get more elaborate XML validation errors with PHP

Posted in PHP, XML on January 23rd, 2012 by Joonas – 1 Comment

In a previous post, “Validate XML file against an XSD schema“, I showed how you validate an XML document against a corresponding XSD document. By default, the DOMDocument class does not spit out very elaborate debug messages when a file fails validation.

You can use PHP’s libxml functions to enable advanced errors that will tell you exactly what the problem is and what line it is on, etc. Check out the code below for a simple use example.

# Enable advanced libxml errors
libxml_use_internal_errors(true);
 
$filename = 'your-input-file.xml';
$xsd_document = 'your-schema-document.xsd';
$dom = new DomDocument();
 
if (!$dom->load($filename)) die('Could not load XML file: '.$filename);
if (!$dom->schemaValidate($xsd_document))
{
    print_r(libxml_get_errors());
    die('XML file did not validate against schema: '.$xsd_document);
}

The advanced errors will help you spot errors in XML faster and be able to provide better reporting on what is going on with the failures of what ever your implementation may be.

There are some other cool things that you can do with the libxml functions as well.

Convert bad characters to UTF-8 in an XML file with PHP

Posted in PHP, XML on January 12th, 2012 by Joonas – Be the first to comment

I ran in to a situation where a vendor was sending an XML file to my system and I needed to parse it and do a bunch of stuff with the data. Well, I wanted to load the file with PHP DOMDocument, but as soon as I did, the following error started to cause grief.

Warning: DOMDocument::load(): Input is not proper UTF-8, indicate encoding !

The error happens because there are non-UTF-8 characters in the XML file. The vendor was writing a bad characters to the file. In an ideal world, the problem should have been fixed upstream by the vendor, but that was out of the question. I came up with the following solution.

The solution is to search the file for non-UTF-8 characters and convert them to UTF-8 with PHP’s utf8_encode function. See the sample code below.

<?php
 
# The XML file with bad characters
$filename = "sample_xml_file.xml";
 
# Read file contents to a variable
$contents = file_get_contents($filename);
 
# Find the bad characters
preg_match_all('/[^(\x20-\x7F)]*/', $contents, $badchars);
 
# Process bad characters if some were found
if(isset($badchars[0]))
{
        # Narrow down the results to uniques only
        $badchars[0] = array_unique($badchars[0]);
 
        # Replace the bad characters with their UTF8 equivalents
        foreach($badchars[0] as $badchar)
        {
                $contents = preg_replace("/".$badchar."/", utf8_encode($badchar), $contents);
        }
}
 
# Write the fixed contents back to the file
file_put_contents($filename, $contents);
 
# Cleanup
unset($contents);
 
# Now the bad characters have been encoded to UTF8
# It will now load file with DOMDocument
$dom = new DOMDocument();
$dom->load($filename);
 
?>

This solution worked for all the bad iso-8859-1 characters that I have run in to, which were mostly control characters, but if it doesn’t work for you and/or you have a different approach, please leave a comment!

Export data from a database to CSV / Excel with PHP

Posted in PHP on January 9th, 2012 by Joonas – 2 Comments

Let’s assume that you already have a database setup with a table called “users” and you want to export users and their email addresses to a CSV file. PHP has built in functions to deal with CSV files.

“CSV is a simple file format that is widely supported by consumer, business, and scientific applications. Among its most common uses is to move tabular data between programs that naturally operate on a more efficient or complete proprietary format. For example: a CSV file might be used to transfer information from a database program to a spreadsheet.” – Wikipedia

The code to connect to a MySQL database, query for users, create a file, and write CSV data to the file is provided below.

<?php
 
// Connect and query the database for the users
$conn = new PDO("mysql:host=localhost;dbname=mydatabase", 'myuser', 'mypassword');
$sql = "SELECT username, email FROM users ORDER BY username";
$results = $conn->query($sql);
 
// Pick a filename and destination directory for the file
// Remember that the folder where you want to write the file has to be writable
$filename = "/tmp/db_user_export_".time().".csv";
 
// Actually create the file
// The w+ parameter will wipe out and overwrite any existing file with the same name
$handle = fopen($filename, 'w+');
 
// Write the spreadsheet column titles / labels
fputcsv($handle, array('Username','Email'));
 
// Write all the user records to the spreadsheet
foreach($results as $row)
{
    fputcsv($handle, array($row['username'], $row['email']));
}
 
// Finish writing the file
fclose($handle);
 
?>

The purpose of this post is not to demonstrate how to connect to a database and/or query it for contents, nor how to loop through query results, so I will not explain how PHP’s PDO database abstraction class works. The above code demonstrates how you create a file and write CSV data to it, so let’s walk through the above code.

First, the script connects to a MySQL database using PHP’s PDO class and queries the users table for all the users sorted by username. It then generates a filename with the current UNIX timestamp appended at the end. In this example, the file will be written to the server’s /tmp/ directory. You can change the path to what ever directory you want as long as you have write access to it.

The code then opens the file connection, which creates the file and overwrites any existing file. Once the file is created, the column labels are written to the file. In this example, we are only writing two columns, a Username and an Email column. Next comes the main loop that iterates through all the users that our SQL query got from the database. The loop writes the username and the email of each user record. Finally, we close the file.

What you do with the CSV file beyond this point is up to you and your requirements.

I will write another post later on how to create an actual Excel file with an XLS/XLSX extension.

How to disable PHP open_basedir in PLESK 10

Posted in PHP, PLESK on January 5th, 2012 by Joonas – 2 Comments

PLESK 10 comes with open_basedir enabled by default. I ran in to an instance where I was dynamically creating new vhosts from time to time and could not be bothered to disable open_basedir on a case by case basis by creating a custom vhost.conf for every domain that I created. I needed open_basedir to be turned off server wide by default. The solution was to create a new config file that apache includes by default.

I did this on MediaTemple hosting using CentOS 5 and PLESK 10, but the solution should be the same or very similar on other setups as well.

First, login to your server as root and run the following command.

vim /etc/httpd/conf.d/remove_open_basedir.conf

Second, paste the following code in to the new file.

<DirectoryMatch /var/www/vhosts/(.*)/httpdocs/>
    php_admin_value open_basedir none
</DirectoryMatch>

Third, reconfigure all domains and restart apache.

/usr/local/psa/admin/sbin/httpdmng --reconfigure-all
/etc/init.d/httpd restart

Done! Now you should notice that open_basedir is disabled for all domains.

Please leave comments if this does not work for you or if the implementation on another version of Linux is different.

Do you want to disable open_basedir only for specific vhosts / domains?

Disabling open_basedir or setting it to something specific can be done painlessly on a per domain basis in PLESK. See the steps below.

First, create (or edit as necessary) a vhost specific config file.

vim /var/www/vhosts/example.com/conf/vhost.conf

Second, disable open_basedir by pasting in the code below.

<directory /var/www/vhosts/example.com/httpdocs>
php_admin_value open_basedir none
</directory>

Third, reconfigure your vhost files and restart apache.

/usr/local/psa/admin/sbin/httpdmng --reconfigure-all
/etc/init.d/httpd restart

Enjoy.

How to replace a string in a large file

Posted in Linux, PHP on December 28th, 2011 by Joonas – Be the first to comment

I run in to this quite often where I have a situation where I need to replace some characters or strings within a large file. Assume that the file is too large to read in to memory and do the replacement within PHP. The solution is to use Linux’s sed command.

sed -i -e 's/search/replace/g' myFile.txt

Calling sed in a PHP script, this might look something like:

<?php
 
$filename = "myFile.txt";
 
$output = passthru(sprintf("sed -i -e 's/%s/%s/g' %s",
    escapeshellarg("this is some text i don't want"),
    escapeshellarg("we want this instead"),
    escapeshellarg($filename)
));
 
?>