tag:blogger.com,1999:blog-28383373516021444052024-02-02T11:57:08.118-05:00Return to QualityUnknownnoreply@blogger.comBlogger35125tag:blogger.com,1999:blog-2838337351602144405.post-13891836948563904482012-03-06T09:49:00.000-05:002012-03-06T09:49:35.100-05:00Efficient file storage for user uploaded filesWhile disk space is cheap, dealing with large numbers of files can be tedious, and in some cases unnecessary. Before considering file naming conventions, consider the uniqueness of your files. At work, we allow our customers to upload logos. It's possible for multiple customers to upload the same logo. The last thing we wanted was to maintain multiple copies of the same logo on the server.<br />
<br />
<div>
We decided our best approach would be to name the files based on the contents of the file. If the contents changed, so did the filename.<br />
<br /></div>
<pre class="prettyprint">$filename = md5(file_get_contents($pathToFile));
</pre>
<div>
<br />
The MD5 hashed filename is what was linked to the user logos. This turned out to be a fantastic solution for our needs.<br />
<br />
What naming conventions do you use for user uploaded files? This method seems like it would work well for any uploaded files because nothing would ever be the same. Do you agree or disagree? Why?</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-51269289214414573552012-03-04T10:02:00.001-05:002012-03-04T17:21:42.458-05:00Smart MySQL BackupA lot of web sites are hosted on shared servers via web hosting services like <a href="http://secure.hostgator.com/~affiliat/cgi-bin/affiliates/clickthru.cgi?id=spire07">Hostgator</a> where a single web server may have a hundred or more customer accounts hosted on it. While services like this do backup your files and databases they do not guarantee them. This means if something goes wrong and their backups couldn't be restored for any reason, you'd simply lose your data and they wouldn't be at fault. For this reason, I do not use cPanel backups on my shared hosting account.<br />
<br />
I personally use and recommend <a href="https://github.com/bkuhl/Smart-MySQL-Backup">Smart MySQL Backup</a> to create backup databases. There are a lot of great features...<br />
<ul style="background-color: white; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #333333; font: inherit; line-height: 22px; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 30px; padding-right: 0px; padding-top: 0px;">
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">Backup individual or all databases in a separate file for each database</span></li>
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">UTF-8 support</span></li>
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">Daily, weekly and monthly backup rotation</span></li>
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">Send backups to email</span></li>
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">Upload backups to FTP</span></li>
<li style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font: inherit; margin-bottom: 15px; margin-left: 0px; margin-right: 0px; margin-top: 15px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;"><span style="font-family: inherit;">Handles foreign keys and stored procedures</span></li>
</ul>
<div>
<span style="color: #333333;"><span style="line-height: 22px;">Once I have that setup and running, I have a simple PHP script to upload the backups to Amazon S3. These backups can be restored through cPanel/PHPMyAdmin, or via command line. </span></span></div>
<br />
<pre class="prettyprint">// Take db backups and copy them to s3
// https://github.com/tpyo/amazon-s3-php-class
require_once 's3.php';
$bucket = 'my-bucket-name';
$backupPath = '/path/to/backups/archive/daily';
$s3 = new S3("[awsAccessKey]", "[awsSecretKey]");
$today = date('Y-m-d');
$expired = date('Y-m-d', strtotime('-5 days'));
foreach(glob($backupPath.'/'.$today.'/*.bz2') as $file) {
$fileInfo = pathinfo($file);
//move backup file to s3
$s3->putObject(S3::inputFile($file), $bucket, $fileInfo['basename'], S3::ACL_PRIVATE);
//remove expired files
$s3->deleteObject($bucket, str_replace($today, $expired, $fileInfo['basename']));
}</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-75961149183716910172012-03-04T09:37:00.000-05:002012-03-04T17:21:01.839-05:00PHP file upload MIME type is unreliableI ran into an odd issue this week where a PDF being uploaded by a user through the latest Firefox wasn't properly detected as a PDF. The "type" showed a value of "application/x-word-xxx" instead of "application/pdf". On my own computer, Firefox and Chrome worked fine as expected.<br />
<br />
The file type header is defined by the browser handling the uploading. The fix for this appears to be to use <a href="http://www.php.net/mime_content_type">mime_content_type</a> on the file after it's been uploaded instead of relying on $_FILES.<br />
<br />
<pre class="prettyprint">echo mime_content_type('php.gif') . "\n"; //image/gif
echo mime_content_type('test.php'); //text/plain
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-87975388261672637962011-08-03T10:59:00.008-04:002011-08-03T11:08:17.050-04:00PrintNet/GMC: Critical error: Unmatched options (810 or 811)<span style="font-family: Calibri, sans-serif; font-size: 11pt;">I ran into this issue when working with GMC... it took me forever to figure out what was up with it. To keep a long story short, turns out it was the `enableerrorconsole` flag... my initial command read </span><br />
<pre class="prettyprint">/usr/local/PNetT/PNetTCNetClient
-o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd
-e PDF
-f "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO_temp.pdf" -useincluded "*"
-difDataInput1 "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO.txt"
-difDataInput2 "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO-table.txt"
-enableerrorconsole true</pre><span style="font-family: Calibri, sans-serif; font-size: 11pt;">If you do this, you'll see one of the following errors:</span><br />
<pre class="prettyprint">Critical error 0810: Unmatched options
Critical error 0811: Unmatched options
</pre><span style="font-family: Calibri, sans-serif; font-size: 11pt;">The issue is that the `enableerrorconsole` flag does not need a true parameter, it needs options for the log files to split up. This option isn't something that is enabled/disabled by it's parameters, it's parameters specify the log files that the error console requires. According to the user manual it splits up the error for the command so that the log data goes one places, and the error is recorded somewhere else. I fixed this error by changing my command by specifying the log files as seen below:</span><br />
<pre class="prettyprint">/usr/local/PNetT/PNetTCNetClient
-o /usr/local/PNetT/tmpData/SOB/workflows/master_ppo_sob_3col.wfd
-e PDF
-f "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO_temp.pdf"
-useincluded "*"
-difDataInput1 "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO.txt"
-difDataInput2 "/usr/local/PNetT/tmpData/SOB/Master PPO-Gem Mortgage BC Classic PPO-table.txt"
-enableerrorconsole >sob.log 2>gmc-error.log</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-11996522371148684972011-08-03T09:05:00.002-04:002011-08-03T09:05:43.137-04:00PrintNetT & GMC Support, Forums & DocumentationIf you've ever used PrintNetT or GMC and tried to look something up on Google you'll notice that you can basically find nothing. I began working with these products while at a printing company and quickly realized that with my lack of training with the server client I was going to run into many problems. After some time of trying to look through the manual to get my answers I finally reached out to price options for training that I could present to my bosses to resolve all of our issues. I was referred to their <a href="http://community.gmc.net/web/gmc.net/discussions">community forums</a> and <a href="http://community.gmc.net/web/gmc.net/support">online documentation</a>. I was dumbfounded that this information was so easily accessible on their web site - but why was it so hard to find?<br />
<br />
The truth is that GMC doesn't want you to find it. Their goal is for you to pay thousands of dollars for support and training. They've blocked search engines from indexing their message boards. So the only content you're going to find is that which is not posted on their web site. I'm not trying to sell them as an evil corporation, it makes perfect sense for them to try to make more money, my only gripe is that it hurts the customer in this specific case.<br />
<br />
Be aware of these resources, they can be very helpful.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-76787302811467682092011-01-03T10:54:00.000-05:002011-01-03T10:54:54.033-05:00What to do if your server gets hacked...<span class="Apple-style-span" style="border-collapse: collapse; font-family: Arial, 'Liberation Sans', 'DejaVu Sans', sans-serif; font-size: 14px; line-height: 18px;"></span><br />
<div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><i>I read this elsewhere and thought it was just so good I had to post it. I'm not able to determine the exact source or I would provide a link to it.</i></div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><span style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">First things first, there are no "quick fixes" other than restoring your system from a backup taken prior to the intrusion, and this has at least two problems.</span></div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">It's difficult to pinpoint when the intrusion happened.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">It doesn't help you close the "hole" that allowed them to break in last time, nor deal with the consequences of any "data theft" that may also have taken place.</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">This question keeps being asked repeatedly by the victims of hackers breaking into their web server. The answers very rarely change, but people keep asking the question. I'm not sure why. Perhaps people just don't like the answers they've seen when searching for help, or they can't find someone they trust to give them advice. Or perhaps people read an answer to this question and focus too much on the 5% of why their case is special and different from the answers they can find online and miss the 95% of the question and answer where their case is near enough the same as the one they read online.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">That brings me to the first important nugget of information. I really do appreciate that you are a special unique snowflake. I appreciate that your website is too, as it's a reflection of you and your business or at the very least, your hard work on behalf of an employer. But to someone on the outside looking in, whether a computer security person looking at the problem to try and help you or even the attacker himself, it is very likely that your problem will be at least 95% identical to every other case they've ever looked at.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Don't take the attack personally, and don't take the recommendations that follow here or that you get from other people personally. If you are reading this after just becoming the victim of a website hack then I really am sorry, and I really hope you can find something helpful here, but this is not the time to let your ego get in the way of what you need to do.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><strong style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">You have just found out that your server(s) got hacked. Now what?</strong></div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Do not panic. Absolutely do not act in haste, and absolutely do not try and pretend things never happened and not act at all.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">First: understand that the disaster has already happened. This is not the time for denial; it is the time to accept what has happened, to be realistic about it, and to take steps to manage the consequences of the impact.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Some of these steps are going to hurt, and (unless your website holds a copy of my details) I really don't care if you ignore all or some of these steps but doing so will make things better in the end. The medicine might taste awful but sometimes you have to overlook that if you really want the cure to work.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Stop the problem from becoming worse than it already is:</div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">The first thing you should do is disconnect the affected systems from the Internet. Whatever other problems you have, leaving the system connected to the web will only allow the attack to continue. I mean this quite literally; get someone to physically visit the server and unplug network cables if that is what it takes, but disconnect the victim from its muggers before you try to do anything else.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Change all your passwords for all accounts on all computers that are on the same network as the compromised systems. No really. All accounts. All computers. Yes, you're right, this might be overkill; on the other hand, it might not. You don't know either way, do you?</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Check your other systems. Pay special attention to other Internet facing services, and to those that hold financial or other commercially sensitive data.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">If the system holds anyone's personal data, make a full and frank disclosure to anyone potentially affected at once. I know this one is tough. I know this one is going to hurt. I know that many businesses want to sweep this kind of problem under the carpet but I'm afraid you're just going to have to deal with it.</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Still hesitating to take this last step? I understand, I do. But look at it like this:</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">In some places you might well have a legal requirement to inform the authorities and/or the victims of this kind of privacy breach. However annoyed your customers might be to have you tell them about a problem, they'll be far more annoyed if you don't tell them, and they only find out for themselves after someone charges $8,000 worth of goods using the credit card details they stole from your site.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Remember what I said previously? The bad thing has already happened. The only question now is how well you deal with it.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><strong style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Understand the problem fully:</strong></div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Do NOT put the affected systems back online until this stage is fully complete, unless you want to be the person whose post was the tipping point for me actually deciding to write this article. I'm not going to link to that post so that people can get a cheap laugh, but the real tragedy is when people fail to learn from their mistakes.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Examine the 'attacked' systems to understand how the attacks succeeded in compromising your security. Make every effort to find out where the attacks "came from", so that you understand what problems you have and need to address to make your system safe in the future.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Examine the 'attacked' systems again, this time to understand where the attacks went, so that you understand what systems were compromised in the attack. Ensure you follow up any pointers that suggest compromised systems could become a springboard to attack your systems further.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Ensure the "gateways" used in any and all attacks are fully understood, so that you may begin to close them properly. (e.g. if your systems were compromised by a SQL injection attack, then not only do you need to close the particular flawed line of code that they broke in by, you would want to audit all of your code to see if the same type of mistake was made elsewhere).</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Understand that attacks might succeed because of more than one flaw. Often, attacks succeed not through finding one major bug in a system but by stringing together several issues (sometimes minor and trivial by themselves) to compromise a system. For example, using SQL injection attacks to send commands to a database server, discovering the website/application you're attacking is running in the context of an administrative user and using the rights of that account as a stepping-stone to compromise other parts of a system. Or as hackers like to call it: "another day in the office taking advantage of common mistakes people make".</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><strong style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Make a plan for recovery and to bring your website back online and stick to it:</strong></div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Nobody wants to be offline for longer than they have to be. That's a given. If this website is a revenue generating mechanism then the pressure to bring it back online quickly will be intense. Even if the only thing at stake is your / your company's reputation, this is still going generate a lot of pressure to put things back up quickly.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">However, don't give in to the temptation to go back online too quickly. Instead move with as fast as possible to understand what caused the problem and to solve it before you go back online or else you will almost certainly fall victim to an intrusion once again, and remember, "to get hacked once can be classed as misfortune; to get hacked again straight afterward looks like carelessness" (with apologies to Oscar Wilde).</div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">I'm assuming you've understood all the issues that led to the successful intrusion in the first place before you even start this section. I don't want to overstate the case but if you haven't done that first then you really do need to. Sorry.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Never pay blackmail / protection money. This is the sign of an easy mark and you don't want that phrase ever used to describe you.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Don't be tempted to put the same server(s) back online without a full rebuild. It should be far quicker to build a new box or "nuke the server from orbit and do a clean install" on the old hardware than it would be to audit every single corner of the old system to make sure it is clean before putting it back online again. If you disagree with that then you probably don't know what it really means to ensure a system is fully cleaned, or your website deployment procedures are an unholy mess. You presumably have backups and test deployments of your site that you can just use to build the live site, and if you don't then being hacked is not your biggest problem.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Be very careful about re-using data that was "live" on the system at the time of the hack. I won't say "never ever do it" because you'll just ignore me, but frankly I think you do need to consider the consequences of keeping data around when you know you cannot guarantee its integrity. Ideally, you should restore this from a backup made prior to the intrusion. If you cannot or will not do that, you should be very careful with that data because it's tainted. You should especially be aware of the consequences to others if this data belongs to customers or site visitors rather than directly to you.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Monitor the system(s) carefully. You should resolve to do this as an ongoing process in the future (more below) but you take extra pains to be vigilant during the period immediately following your site coming back online. The intruders will almost certainly be back, and if you can spot them trying to break in again you will certainly be able to see quickly if you really have closed all the holes they used before plus any they made for themselves, and you might gather useful information you can pass on to your local law enforcement.</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><strong style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Reducing the risk in the future.</strong></div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">The first thing you need to understand is that security is a process that you have to apply throughout the entire life-cycle of designing, deploying and maintaining an Internet-facing system, not something you can slap a few layers over your code afterwards like cheap paint. To be properly secure, a service and an application need to be designed from the start with this in mind as one of the major goals of the project. I realise that's boring and you've heard it all before and that I "just don't realise the pressure man" of getting your beta web2.0 (beta) service into beta status on the web, but the fact is that this keeps getting repeated because it was true the first time it was said and it hasn't yet become a lie.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">You can't eliminate risk. You shouldn't even try to do that. What you should do however is to understand which security risks are important to you, and understand how to manage and reduce both the impact of the risk and the probability that the risk will occur.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">What steps can you take to reduce the probability of an attack being successful?</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">For example:</div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Was the flaw that allowed people to break into your site a known bug in vendor code, for which a patch was available? If so, do you need to re-think your approach to how you patch applications on your Internet-facing servers?</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Was the flaw that allowed people to break into your site an unknown bug in vendor code, for which a patch was not available? I most certainly do not advocate changing suppliers whenever something like this bites you because they all have their problems and you'll run out of platforms in a year at the most if you take this approach. However, if a system constantly lets you down then you should either migrate to something more robust or at the very least, re-architect your system so that vulnerable components stay wrapped up in cotton wool and as far away as possible from hostile eyes.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Was the flaw a bug in code developed by you (or a contractor working for you)? If so, do you need to re-think your approach to how you approve code for deployment to your live site? Could the bug have been caught with an improved test system, or with changes to your coding "standard" (for example, while technology is not a panacea, you can reduce the probability of a successful SQL injection attack by using well-documented coding techniques).</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Was the flaw due to a problem with how the server or application software was deployed? If so, are you using automated procedures to build and deploy servers where possible? These are a great help in maintaining a consistent "baseline" state on all your servers, minimising the amount of custom work that has to be done on each one and hence hopefully minimising the opportunity for a mistake to be made. Same goes with code deployment - if you require something "special" to be done to deploy the latest version of your web app then try hard to automate it and ensure it always is done in a consistent manner.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Could the intrusion have been caught earlier with better monitoring of your systems? Of course, 24-hour monitoring or an "on call" system for your staff might not be cost effective, but there are companies out there who can monitor your web facing services for you and alert you in the event of a problem. You might decide you can't afford this or don't need it and that's just fine... just take it into consideration.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Use tools such as tripwire and nessus where appropriate - but don't just use them blindly because I said so. Take the time to learn how to use a few good security tools that are appropriate to your environment, keep these tools updated and use them on a regular basis.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Consider hiring security experts to 'audit' your website security on a regular basis. Again, you might decide you can't afford this or don't need it and that's just fine... just take it into consideration.</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">What steps can you take to reduce the consequences of a successful attack?</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">If you decide that the "risk" of the lower floor of your home flooding is high, but not high enough to warrant moving, you should at least move the irreplaceable family heirlooms upstairs. Right?</div><ol style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: decimal; margin-bottom: 1em; margin-left: 30px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Can you reduce the amount of services directly exposed to the Internet? Can you maintain some kind of gap between your internal services and your Internet-facing services? This ensures that even if your external systems are compromised the chances of using this as a springboard to attack your internal systems are limited.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Are you storing information you don't need to store? Are you storing such information "online" when it could be archived somewhere else. There are two points to this part; the obvious one is that people cannot steal information from you that you don't have, and the second point is that the less you store, the less you need to maintain and code for, and so there are fewer chances for bugs to slip into your code or systems design.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Are you using "least access" principles for your web app? If users only need to read from a database, then make sure the account the web app uses to service this only has read access, don't allow it write access and certainly not system-level access.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">If you're not very experienced at something and it is not central to your business, consider outsourcing it. In other words, if you run a small website talking about writing desktop application code and decide to start selling small desktop applications from the site then consider "outsourcing" your credit card order system to someone like Paypal.</li>
<li style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">If at all possible, make practicing recovery from compromised systems part of your Disaster Recovery plan. This is arguably just another "disaster scenario" that you could encounter, simply one with its own set of problems and issues that are distinct from the usual 'server room caught fire'/'was invaded by giant server eating furbies' kind of thing.</li>
</ol><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;"><strong style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-size: 14px; font-weight: bold; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">... And finally</strong></div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">I've probably left out no end of stuff that others consider important, but the steps above should at least help you start sorting things out if you are unlucky enough to fall victim to hackers.</div><div style="background-attachment: initial; background-clip: initial; background-color: transparent; background-image: initial; background-origin: initial; background-position: initial initial; background-repeat: initial initial; border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; clear: both; font-size: 14px; margin-bottom: 1em; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; word-wrap: break-word;">Above all: Don't panic. Think before you act. Act firmly once you've made a decision, and leave a comment below if you have something to add to my list of steps.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-69900667988870901732010-12-24T12:33:00.001-05:002010-12-24T12:34:39.446-05:00R.drawable cannot be resolvedI'm jumping into Android head first and wanted to make a button that when I press it, it trigger's a notification on the notification bar at the top of the screen. I was browsing through the documentation and ran into this error.<br />
<br />
If you look at the <a href="http://developer.android.com/guide/topics/ui/notifiers/notifications.html">Android Notification Documentation</a> example, you'll notice this line in step 2: <span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="kwd" style="color: #000088;">int</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pln" style="color: black;"> icon </span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pun" style="color: #666600;">=</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pln" style="color: black;"> R</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pun" style="color: #666600;">.</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pln" style="color: black;">drawable</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pun" style="color: #666600;">.</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pln" style="color: black;">notification_icon</span></span><span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px; white-space: pre;"><span class="pun" style="color: #666600;">;</span></span>. If you use their example in a tutorial you'll find that this icon doesn't exist and you can't compile your app. The reason for this is that there is no notification_icon image that exists within <b>/res/drawable-*/</b>. By default, icon.png exists within these directories. If you <b>change the <i>notification_icon</i> to <i>icon</i></b> it will work fine.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-85872691459435480102010-12-10T12:52:00.001-05:002011-08-03T09:07:02.179-04:00PHPMyAdmin error: Unable to change masterI experienced this error while trying to utilize PHPMyAdmin to setup a replication process where an Amazon RDS instance was the slave and my master was my dedicated server. The issue here is that the connection was made successfully but that I do not have permission to adjust the slave/master status of the RDS instance. Amazon has confirmed that this is the case. That's unfortunate, I was hoping it would ease our transition to Amazon's services.<br />
<br />
The error that PHPMyAdmin returned was "Unable to change master"Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-68645168428522525312010-12-10T10:19:00.004-05:002011-08-03T11:09:14.068-04:00How to remotely manage an Amazon RDS instance with PHPMyAdminThe biggest thing I was considering with Amazon Relational Database Service was how to manage it. A command line interface is NOT efficient for database management so I needed to be sure that I would be able to utilize software on my computer to manage my data. PHPMyAdmin was my software of choice. It supports multiple servers and has pretty much everything I need.<br />
<br />
So what does it take to get everything up and running? First, <a href="http://aws.amazon.com/rds/">signup for Amazon RDS</a> and get your instance up and running. <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/GettingStartedGuide/">Amazon's RDS Getting Started Guide</a> is a great resource and I'd highly recommend it. The one thing I had trouble with was the DB Security Group setup. When you go to add access for an CIDR/IP it provides a recommended value. It took some messing around to determine that this default value isn't actually what needed to be there. <i>If you're not able to connect to your instance when it's all said and done, be sure to double check this value.</i> The IP they provided did not match the IP address that was provided to us by our ISP. Once you've created your DB Instance and setup the security group you're good to go.<br />
<br />
I'm going to assume you've already got PHPMyAdmin up and running. What you need to do is modify <b>config.inc.php</b> to recognize the new server. Your config file should look something like this:<br />
<br />
<pre class="prettyprint">/* Configure according to dbconfig-common if enabled */
if (!empty($dbname)) {
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'changeme';
$cfg['Servers'][$i]['hide_db'] = '(mysql|information_schema|phpmyadmin)';
/* Server parameters */
if (empty($dbserver)) $dbserver = 'localhost';
$cfg['Servers'][$i]['host'] = $dbserver;
if (!empty($dbport)) {
$cfg['Servers'][$i]['connect_type'] = 'tcp';
$cfg['Servers'][$i]['port'] = $dbport;
}
//$cfg['Servers'][$i]['compress'] = false;
/* Select mysqli if your server has it */
$cfg['Servers'][$i]['extension'] = 'mysqli';
/* Optional: User for advanced features */
//$cfg['Servers'][$i]['controluser'] = $dbuser;
//$cfg['Servers'][$i]['controlpass'] = $dbpass;
/* Optional: Advanced phpMyAdmin features */
$cfg['Servers'][$i]['pmadb'] = $dbname;
$cfg['Servers'][$i]['bookmarktable'] = 'pma_bookmark';
$cfg['Servers'][$i]['relation'] = 'pma_relation';
$cfg['Servers'][$i]['table_info'] = 'pma_table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma_table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma_pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma_column_info';
$cfg['Servers'][$i]['history'] = 'pma_history';
$cfg['Servers'][$i]['designer_coords'] = 'pma_designer_coords';
/* Uncomment the following to enable logging in to passwordless accounts,
* after taking note of the associated security risks. */
// $cfg['Servers'][$i]['AllowNoPassword'] = TRUE;
/* Advance to next server for rest of config */
$i++;
}
</pre><br />
PHPMyAdmin uses <b>$cfg['Servers'][$i]</b> so that it can support multiple servers on one installation. Having more than 1 server will give you the option to select a server when you login. After that last <b>} </b>you'll want to add the following code, but of course with your own Amazon RDS instance URL.<br />
<br />
<pre class="prettyprint">$cfg['Servers'][$i]['auth_type'] = 'HTTP';
$cfg['Servers'][$i]['hide_db'] = '(mysql|information_schema|phpmyadmin)';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'xxxxx.l2kj35ncj3.us-east-1.rds.amazonaws.com';
</pre><br />
You're ready to go, simply refresh your PHPMyAdmin page if you're already logged in and you'll see the new server.<br />
<br />
Remember, if you have trouble connecting, your IP/Permissions must be wrong!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-81178442234859857462010-07-12T14:36:00.000-04:002010-07-12T14:36:57.053-04:00Free EIN / Tax ID SearchI was looking online for a free EIN / Tax ID search and kept coming up with paid results. There are 2 problems with paid results.<br />
<br />
<ol><li>It's not free</li>
<li>It's not the government's web site, so it's likely not accurate for newer businesses</li>
</ol>The solution is to get it directly from IRS.gov here: <a href="http://www.irs.gov/app/ePostcard/">http://www.irs.gov/app/ePostcard/</a><br />
<br />
Another great benefit here is that you can link directly to a search via the search results URL: <a href="http://www.irs.gov/app/ePostcard/search.do?nameSearchTypeStarts=false&names=&nameSearchTypeAll=false&city=&state=All...&country=US&ein1=11&ein2=1111111&dispatchMethod=search&submitName=Search">http://www.irs.gov/app/ePostcard/search.do?nameSearchTypeStarts=false&names=&nameSearchTypeAll=false&city=&state=All...&country=US&ein1=11&ein2=1111111&dispatchMethod=search&submitName=Search</a><br />
<br />
Simply replace the EIN1 and EIN2 variables in the URL from 1's to whatever the Tax ID is that you're looking up.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-59199867482035275292010-03-25T08:59:00.001-04:002010-03-25T09:03:01.337-04:00Setting up a local virtual server in LinuxIf you're like me, then you design web sites on your local server before pushing the update out to the site. I tend to take http://www.domain.com and make my local server http://domain/. This allows me to fully test and run the site just as it runs on the server, but without the lag/extra steps with working on the server itself, not to mention my changes don't effect the visitor's experience until I push the update.<br />
<br />
To do this, go to:<br />
<br />
<blockquote>/etc/hosts/</blockquote><br />
It will look like this:<br />
<br />
<br />
<blockquote>127.0.0.1 localhost</blockquote><br />
You need to update this file so your browser knows to look locally for the domain. Add a line for your domain name...<br />
<br />
<blockquote>127.0.0.1 domain</blockquote>OR<br />
<blockquote>127.0.0.1 domain2.loc</blockquote><br />
<br />
Next you need to tell apache about your new domain. Go to /etc/apache2/sites-available/ and create a file for your new domain. Since my new domain is literally "domain" that's what I will call my file, with no file extension. Within that file I'll put this....<br />
<br />
<blockquote>NameVirtualHost domain:80<br />
<br />
<VirtualHost domain:80><br />
ServerName domain<br />
DocumentRoot /var/www/domain/<br />
</VirtualHost></blockquote><br />
Once you've got this setup you're good to go. All you need to do is restart apache...<br />
<br />
<blockquote>/etc/init.d/apache2 restart</blockquote><br />
Now I can access this local domain by simply typing http://domain/ and it won't effect the users browsing my site.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-61756612318337794992010-03-24T21:16:00.000-04:002010-03-24T21:16:46.327-04:00Internet Explorer (IE) and image/pjpeg, what's that all about?I had a user report to me today that jpg image uploads were not functioning. I had him send me the images so that I could try uploading them to my site. They worked just fine. So what's the problem? Some genius over at <b>Microsoft decided that instead of using image/jpeg as the mime type for JPG's they would use image/pjpeg</b>.<br />
<br />
If you're checking mime types for your image uploads, be sure to include image/pjpeg in the list or you'll find yourself dealing with bug reports.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-79105287454708419192010-03-16T13:48:00.000-04:002010-03-16T13:48:30.548-04:00Server Load Average and what to do about itTo take a look at your load average, to your server's command line and type "top" and it'll show you the top processes your server is running.<br />
<br />
I was going to write up some descriptions on this as my research continued, but I found the perfect source. So rather than rewrite it the guide and try to explain things I don't have an expert's opinion on, I'm going to forward to a real source, that knows what they're talking about.<br />
<br />
<a href="http://http://blog.scoutapp.com/articles/2009/07/31/understanding-load-averages">Understanding Linux CPU Load - when should you be worried?</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-75479851011064607022010-03-10T14:11:00.003-05:002010-05-18T10:33:36.957-04:00Determine if PHP file is being access via CronI ran into an issue where I needed to determine which config settings to load in my API. It picks up automatically whether I'm working locally or on the server. It kept loading the local configuration based on my code. So I asked some smarter people for some assistance and was given the right answer. This will determine whether it's being loaded via command line.<br />
<br />
<pre class="brush: php">if (php_sapi_name() == 'cli') {
return true;
} else {
return false;
}
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-25028997654993724702009-12-04T08:27:00.001-05:002011-08-03T11:09:49.273-04:00Timezone List in MySQLBelow you can find a list of all timezones and their offsets.<br />
<br />
<pre class="prettyprint">CREATE TABLE IF NOT EXISTS `time_zone` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL DEFAULT '',
`offset` float NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=40 ;
INSERT INTO `time_zone` (`id`, `name`, `offset`) VALUES
(1, '(-12:00) Enitwetok, Kwajalien', -12),
(2, '(-11:00) Midway Island, Samoa', -11),
(3, '(-10:00) Hawaii', -10),
(4, '(-9:30) French Polynesia', -9.5),
(5, '(-9:00) Alaska', -9),
(6, '(-8:00) Pacific Time (US & Canada)', -8),
(7, '(-7:00) Mountain Time (US & Canada)', -7),
(8, '(-6:00) Central Time (US & Canada), Mexico City', -6),
(9, '(-5:00) Eastern Time (US & Canada), Bogota, Lima', -5),
(10, '(-4:00) Atlantic Time (Canada), Caracas, La Paz', -4),
(11, '(-3:30) Newfoundland', -3.5),
(12, '(-3:00) Brazil, Buenos Aires, Falkland Is.', -3),
(13, '(-2:00) Mid-Atlantic, Ascention Is., St Helena', -2),
(14, '(-1:00) Azores, Cape Verde Islands', -1),
(15, 'Casablanca, Dublin, London, Lisbon, Monrovia', 0),
(16, '(+1:00) Brussels, Copenhagen, Madrid, Paris', 1),
(17, '(+2:00) Kaliningrad, South Africa', 2),
(18, '(+3:00) Baghdad, Riyadh, Moscow, Nairobi', 3),
(19, '(+3:30) Tehran', 3.5),
(20, '(+4:00) Abu Dhabi, Baku, Muscat, Tbilisi', 4),
(21, '(+4:30) Kabul', 4.5),
(22, '(+5:00) Ekaterinburg, Karachi, Tashkent', 5),
(23, '(+5:30) Bombay, Calcutta, Madras, New Delhi', 5.5),
(24, '(+5:45) Kathmandu', 5.75),
(25, '(+6:00) Almaty, Colombo, Dhaka', 6),
(26, '(+6:30) Yangon, Naypyidaw, Bantam', 6.5),
(27, '(+7:00) Bangkok, Hanoi, Jakarta', 7),
(28, '(+8:00) Hong Kong, Perth, Singapore, Taipei', 8),
(29, '(+8:45) Caiguna, Eucla', 8.75),
(30, '(+9:00) Osaka, Sapporo, Seoul, Tokyo, Yakutsk', 9),
(31, '(+9:30) Adelaide, Darwin', 9.5),
(32, '(+10:00) Melbourne, Papua New Guinea, Sydney', 10),
(33, '(+10:30) Lord Howe Island', 10.5),
(34, '(+11:00) Magadan, New Caledonia, Solomon Is.', 11),
(35, '(+11:30) Burnt Pine, Kingston', 11.5),
(36, '(+12:00) Auckland, Fiji, Marshall Island', 12),
(37, '(+12:45) Chatham Islands', 12.75),
(38, '(+13:00) Kamchatka, Anadyr', 13),
(39, '(+14:00) Kiritimati', 14);
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-36576857683766929412009-12-04T08:22:00.002-05:002011-08-03T11:09:58.856-04:00Country List in MySQLBelow you'll find a list of all the countries in the world. Useful for utilizing them on your web site. <br />
<br />
<pre class="prettyprint">CREATE TABLE IF NOT EXISTS `country` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=242 ;
INSERT INTO `country` (`id`, `name`) VALUES
(1, 'United States'),
(2, 'Canada'),
(3, 'Mexico'),
(4, 'Afghanistan'),
(5, 'Albania'),
(6, 'Algeria'),
(7, 'Andorra'),
(8, 'Angola'),
(9, 'Anguilla'),
(10, 'Antarctica'),
(11, 'Antigua and Barbuda'),
(12, 'Argentina'),
(13, 'Armenia'),
(14, 'Aruba'),
(15, 'Ascension Island'),
(16, 'Australia'),
(17, 'Austria'),
(18, 'Azerbaijan'),
(19, 'Bahamas'),
(20, 'Bahrain'),
(21, 'Bangladesh'),
(22, 'Barbados'),
(23, 'Belarus'),
(24, 'Belgium'),
(25, 'Belize'),
(26, 'Benin'),
(27, 'Bermuda'),
(28, 'Bhutan'),
(29, 'Bolivia'),
(30, 'Bophuthatswana'),
(31, 'Bosnia-Herzegovina'),
(32, 'Botswana'),
(33, 'Bouvet Island'),
(34, 'Brazil'),
(35, 'British Indian Ocean'),
(36, 'British Virgin Islands'),
(37, 'Brunei Darussalam'),
(38, 'Bulgaria'),
(39, 'Burkina Faso'),
(40, 'Burundi'),
(41, 'Cambodia'),
(42, 'Cameroon'),
(44, 'Cape Verde Island'),
(45, 'Cayman Islands'),
(46, 'Central Africa'),
(47, 'Chad'),
(48, 'Channel Islands'),
(49, 'Chile'),
(50, 'China, Peoples Republic'),
(51, 'Christmas Island'),
(52, 'Cocos (Keeling) Islands'),
(53, 'Colombia'),
(54, 'Comoros Islands'),
(55, 'Congo'),
(56, 'Cook Islands'),
(57, 'Costa Rica'),
(58, 'Croatia'),
(59, 'Cuba'),
(60, 'Cyprus'),
(61, 'Czech Republic'),
(62, 'Denmark'),
(63, 'Djibouti'),
(64, 'Dominica'),
(65, 'Dominican Republic'),
(66, 'Easter Island'),
(67, 'Ecuador'),
(68, 'Egypt'),
(69, 'El Salvador'),
(70, 'England'),
(71, 'Equatorial Guinea'),
(72, 'Estonia'),
(73, 'Ethiopia'),
(74, 'Falkland Islands'),
(75, 'Faeroe Islands'),
(76, 'Fiji'),
(77, 'Finland'),
(78, 'France'),
(79, 'French Guyana'),
(80, 'French Polynesia'),
(81, 'Gabon'),
(82, 'Gambia'),
(83, 'Georgia Republic'),
(84, 'Germany'),
(85, 'Gibraltar'),
(86, 'Greece'),
(87, 'Greenland'),
(88, 'Grenada'),
(89, 'Guadeloupe (French)'),
(90, 'Guatemala'),
(91, 'Guernsey Island'),
(92, 'Guinea Bissau'),
(93, 'Guinea'),
(94, 'Guyana'),
(95, 'Haiti'),
(96, 'Heard and McDonald Isls'),
(97, 'Honduras'),
(98, 'Hong Kong'),
(99, 'Hungary'),
(100, 'Iceland'),
(101, 'India'),
(102, 'Iran'),
(103, 'Iraq'),
(104, 'Ireland'),
(105, 'Isle of Man'),
(106, 'Israel'),
(107, 'Italy'),
(108, 'Ivory Coast'),
(109, 'Jamaica'),
(110, 'Japan'),
(111, 'Jersey Island'),
(112, 'Jordan'),
(113, 'Kazakhstan'),
(114, 'Kenya'),
(115, 'Kiribati'),
(116, 'Kuwait'),
(117, 'Laos'),
(118, 'Latvia'),
(119, 'Lebanon'),
(120, 'Lesotho'),
(121, 'Liberia'),
(122, 'Libya'),
(123, 'Liechtenstein'),
(124, 'Lithuania'),
(125, 'Luxembourg'),
(126, 'Macao'),
(127, 'Macedonia'),
(128, 'Madagascar'),
(129, 'Malawi'),
(130, 'Malaysia'),
(131, 'Maldives'),
(132, 'Mali'),
(133, 'Malta'),
(134, 'Martinique (French)'),
(135, 'Mauritania'),
(136, 'Mauritius'),
(137, 'Mayotte'),
(139, 'Micronesia'),
(140, 'Moldavia'),
(141, 'Monaco'),
(142, 'Mongolia'),
(143, 'Montenegro'),
(144, 'Montserrat'),
(145, 'Morocco'),
(146, 'Mozambique'),
(147, 'Myanmar'),
(148, 'Namibia'),
(149, 'Nauru'),
(150, 'Nepal'),
(151, 'Netherlands Antilles'),
(152, 'Netherlands'),
(153, 'New Caledonia (French)'),
(154, 'New Zealand'),
(155, 'Nicaragua'),
(156, 'Niger'),
(157, 'Niue'),
(158, 'Norfolk Island'),
(159, 'North Korea'),
(160, 'Northern Ireland'),
(161, 'Norway'),
(162, 'Oman'),
(163, 'Pakistan'),
(164, 'Panama'),
(165, 'Papua New Guinea'),
(166, 'Paraguay'),
(167, 'Peru'),
(168, 'Philippines'),
(169, 'Pitcairn Island'),
(170, 'Poland'),
(171, 'Polynesia (French)'),
(172, 'Portugal'),
(173, 'Qatar'),
(174, 'Reunion Island'),
(175, 'Romania'),
(176, 'Russia'),
(177, 'Rwanda'),
(178, 'S.Georgia Sandwich Isls'),
(179, 'Sao Tome, Principe'),
(180, 'San Marino'),
(181, 'Saudi Arabia'),
(182, 'Scotland'),
(183, 'Senegal'),
(184, 'Serbia'),
(185, 'Seychelles'),
(186, 'Shetland'),
(187, 'Sierra Leone'),
(188, 'Singapore'),
(189, 'Slovak Republic'),
(190, 'Slovenia'),
(191, 'Solomon Islands'),
(192, 'Somalia'),
(193, 'South Africa'),
(194, 'South Korea'),
(195, 'Spain'),
(196, 'Sri Lanka'),
(197, 'St. Helena'),
(198, 'St. Lucia'),
(199, 'St. Pierre Miquelon'),
(200, 'St. Martins'),
(201, 'St. Kitts Nevis Anguilla'),
(202, 'St. Vincent Grenadines'),
(203, 'Sudan'),
(204, 'Suriname'),
(205, 'Svalbard Jan Mayen'),
(206, 'Swaziland'),
(207, 'Sweden'),
(208, 'Switzerland'),
(209, 'Syria'),
(210, 'Tajikistan'),
(211, 'Taiwan'),
(212, 'Tahiti'),
(213, 'Tanzania'),
(214, 'Thailand'),
(215, 'Togo'),
(216, 'Tokelau'),
(217, 'Tonga'),
(218, 'Trinidad and Tobago'),
(219, 'Tunisia'),
(220, 'Turkmenistan'),
(221, 'Turks and Caicos Isls'),
(222, 'Tuvalu'),
(223, 'Uganda'),
(224, 'Ukraine'),
(225, 'United Arab Emirates'),
(226, 'Uruguay'),
(227, 'Uzbekistan'),
(228, 'Vanuatu'),
(229, 'Vatican City State'),
(230, 'Venezuela'),
(231, 'Vietnam'),
(232, 'Virgin Islands (Brit)'),
(233, 'Wales'),
(234, 'Wallis Futuna Islands'),
(235, 'Western Sahara'),
(236, 'Western Samoa'),
(237, 'Yemen'),
(238, 'Yugoslavia'),
(239, 'Zaire'),
(240, 'Zambia'),
(241, 'Zimbabwe');
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-50074452292166863872009-11-21T10:37:00.001-05:002009-11-21T10:41:03.165-05:00Setting up a local Virtual Host using WAMP/ApacheSetting up a virtual host will allow you to essentially run an exact copy of your site locally. You'll need to decide on a local domain name. My standard is to only maintain the primary name. So for instance if the site is http://www.domain.com then I will use http://domain/ for the local copy. Some people decide to use http://domain.loc/.<br />
<br />
Once you've decided, open <b>C:\Windows\System32\drivers\etc</b> and open the <b>hosts</b> file.<br />
<br />
It should look like this when opened:<br />
<br />
<pre>127.0.0.1 localhost
::1 localhost
</pre><br />
Add a new line<br />
<br />
<pre>127.0.0.1 localhost
<b>127.0.0.1 domain</b>
::1 localhost
</pre><br />
Replace "domain" with "domain.loc" if you want.<br />
<br />
Next you're going to need to locate your Apache installation. In WAMP, you're going to need to open <b>C:\wamp\bin\apache\Apache2.2.11\conf\extra\httpd-vhosts.conf</b> and add the line:<br />
<br />
<br />
<pre class="brush: php"><virtualhost *:80>
ServerAdmin webmaster@localhost
DocumentRoot "c:/wamp/www/domain"
ServerName domain
ErrorLog "logs/domain.log"
CustomLog "logs/domain.log" common
<directory "c:/wamp/www/domain">
Options Indexes FollowSymLinks
AllowOverride all
Order Allow,Deny
Allow from all
Allow from 127.0.0.1
</directory>
</VirtualHost></pre><br />
AFTER<br />
<br />
<pre class="brush: php">NameVirtualHost *:80
<virtualhost *:80>
DocumentRoot "c:/wamp/www"
ServerName localhost
</VirtualHost></pre><br />
If you're using .loc, all you should have to do is add .loc to the ServerName, NOT to the paths defining the location to load.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-23394409917330928272009-11-20T14:56:00.001-05:002009-11-20T14:56:39.784-05:00Regex LibraryI was doing a search for some regex that I could modify to meet my specific needs for a project (I haven't learned it yet). I stumbled on this site that has tons and tons of regex examples. I figured it was a link I definitely wanted to keep so I'd post it here. Who knows, maybe you'll find it useful too.<br />
<br />
<a href="http://www.roscripts.com/PHP_regular_expressions_examples-136.html">http://www.roscripts.com/PHP_regular_expressions_examples-136.html</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-75595850918970748682009-11-18T09:01:00.000-05:002009-11-18T09:01:33.996-05:00PHP Force File Download<span style="font-family: Arial; font-size: small;"><span style="font-size: 13px;">When setting up a file download on a web site you never want to link to the file directly. By linking to the file directly you're letting the browser determine the best action to take. If the file is capable of being opened in the browser (.txt, .jpg, .pdf) then that's what the browser will do. However you can easily force the browser to give a download prompt.</span></span><br />
<br />
<pre class="brush: php">$file = '/home/user/public_html/file.zip';
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($file)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($file));
header('Connection: close');
readfile($file);
exit();</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-37618625340641499032009-11-18T08:51:00.000-05:002009-11-18T08:51:32.775-05:00Run PHP via CronIt's simple, run the following command using an absolute path to the file.<br />
<br />
<pre class="brush: php">php -q /home/user/public_html/file.php</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-76283199469591668692009-10-02T09:53:00.000-04:002009-10-02T09:53:34.986-04:00Warning: number_format() expects parameter 1 to be doubleI ran into this error when I was working on the Google Custom Search API. I've never run into it before. I'm passing the estimated number of search results through to a number_format() which is currently passing through the number 10. Unfortunately it's throwing this error. I haven't figured it out yet, if anyone knows please post the solution so others can find it as well.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-43176181538247514812009-08-04T07:33:00.001-04:002009-08-04T07:33:59.811-04:00OpenX Javascript or CSS not loadingThe get.max_value_length value of your web server settings does not allow to use long URL paths. This might lead to JavaScript and CSS files not properly being included. To fix this you have 2 options:<br />
<br />
<ol><li>Modify your config setting for OpenX to disable combining/compressing CSS/JS files (this only effects the admin panel).<br />
<br />
<br />
<br />
<pre class="brush: php">[ui]combineAssets=0</pre></li>
<li>Modify php.ini to extend the length of your GET variable values. The default setting for PHP 5.3 is 512. <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuZ9jiXRkplwe6pTQR9uT7VIA7o0DRCbcQUzFm6AaPUg84qBFT8MQFlzFk2E2BiUAmheuzWAtZ2GR404RK3GV8-iGWvLI9WcgZ6v9S7HnU0uDpLczq_C8XkU3552o4Qo4nHP4SVW8XOqE/s1600-h/max-value-length.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuZ9jiXRkplwe6pTQR9uT7VIA7o0DRCbcQUzFm6AaPUg84qBFT8MQFlzFk2E2BiUAmheuzWAtZ2GR404RK3GV8-iGWvLI9WcgZ6v9S7HnU0uDpLczq_C8XkU3552o4Qo4nHP4SVW8XOqE/s320/max-value-length.png" /></a></div></li>
</ol>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-63392026218625296072009-08-04T07:14:00.002-04:002009-08-04T07:17:01.483-04:00How to find the locaion of php.iniTo find the location of your php.ini file, copy and paste the below code into a php file and upload it to your server.<br />
<br />
<pre class="brush: php"><?php
phpinfo();
?></pre><br />
When you access the file it will look like the below image. The red arrow is pointing to the location of your php.ini file. In Linux environments this is the most common location.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin95IsDwFktvAJ2EDCHKLMzyjeCTKxvTSlZs6TOTH4-viIP0cJUQGdBgbR9GDWeXGt5aw4q3SPVIs5B-C007WdAY44LDDnhtjijVYZA4lUWU18rpcLVOh2Oc0KxiVjmXLzGx2B_hRTbe0/s1600-h/php-ini.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEin95IsDwFktvAJ2EDCHKLMzyjeCTKxvTSlZs6TOTH4-viIP0cJUQGdBgbR9GDWeXGt5aw4q3SPVIs5B-C007WdAY44LDDnhtjijVYZA4lUWU18rpcLVOh2Oc0KxiVjmXLzGx2B_hRTbe0/s320/php-ini.png" /></a></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-51658087487962738312009-08-04T06:50:00.001-04:002009-08-04T06:51:51.248-04:00A quick guide to Smarty cachingWhen you first jump into <a href="http://www.smarty.net/">Smarty Template Engine</a> caching it can be a bit confusing and overwhelming till you get your feet wet and begin to understand some core concepts of how Smarty works. Now that I'm beginning to understand it, I see how we can't live without it!<br />
<br />
<b>Basic Caching</b><br />
<br />
Smarty has a <b>_compiled</b> folder which is used to cache the parsed versions of templates (ie - Smarty's "template code" is replaced with actual PHP and stored in the _compiled folder). Smarty also has a <b>_cache</b> folder which will actually store individual templates.<br />
<br />
For smaller web sites, Smarty's basic caching is very effective and simple. You simply enable caching and define a lifetime<br />
<br />
<pre class="brush: php">caching = 2; // lifetime is per cache
// set the cache_lifetime for index.tpl to 5 minutes
$smarty->cache_lifetime = 300;
$smarty->display('index.tpl');
// set the cache_lifetime for home.tpl to 1 hour
$smarty->cache_lifetime = 3600;
$smarty->display('home.tpl');
// NOTE: the following $cache_lifetime setting will not work when $caching = 2.
// The cache lifetime for home.tpl has already been set
// to 1 hour, and will no longer respect the value of $cache_lifetime.
// The home.tpl cache will still expire after 1 hour.
$smarty->cache_lifetime = 30; // 30 seconds
$smarty->display('home.tpl');
?></pre><br />
<b>Group Caching</b><br />
<br />
Smarty offers the ability to group your templates. So if you need to lets say, clear the templates for the news section of your web site, you can simply execute <span style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; font-family: 'andale mono', 'monotype.com', 'courier new', courier, monospace; font-size: 11px;"><span style="color: #0000bb;">$smarty</span><span style="color: #007700;">-></span><span style="color: #0000bb;">clear_cache</span><span style="color: #007700;">(</span><span style="color: #0000bb;">null</span><span style="color: #007700;">,</span><span style="color: #dd0000;">'news'</span><span style="color: #007700;">);</span></span> and all of your news template's caches will be cleared. This same technique can be utilized for caching dynamic pages with a ?id= within the URL. You can apply multiple group tags to identify a group, or an individual element. In the below example, index.tpl will be used to view all articles, but to decrease database load you want to cache each article's contents. By defining <b>news|</b><i><b>$article_id</b></i> you are creating a sub group of news for each article id, meaning they won't be overwritten by other articles.<br />
<br />
<pre class="brush: php">caching = 1;
$my_cache_id = $_GET['article_id'];
if(!$smarty->is_cached('index.tpl', 'news|'.$my_cache_id)) {
// No cache available, do variable assignments here.
$contents = get_database_contents();
$smarty->assign($contents);
}
$smarty->display('index.tpl', 'news|'.$my_cache_id);
?></pre><br />
By utilizing the <b>is_cached()</b> function we see the core benefit of Smarty. If the cache exists, we don't need to run queries to or any parsing on the article itself, so we can skip all of this. This is very beneficial to reduce SQL server load. It's much less server processing to see if a file exists than it is to run queries/parsing on an article.<br />
<br />
That's the basics of Smarty caching.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-2838337351602144405.post-8409211419963921092009-07-30T03:37:00.000-04:002009-07-30T03:37:37.196-04:00Smarty syntax error: unrecognized tag 'dynamic' and Block functionsI ran into this error while working with Smarty caching. This error is caused by a "dynamic" block function not being registered with Smarty. A block function is a function which essentially will take a section of content and execute a function on that content. Because of this, Smarty will not cache it. Notice in <a href="http://www.smarty.net/manual/en/caching.cacheable.php">this example</a> the <span style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; color: #0000bb; font-family: 'andale mono', 'monotype.com', 'courier new', courier, monospace; font-size: 11px;">smarty_block_dynamic</span> function simply returns the content. Because it was defined as "dynamic" you can use the Smarty dynamic tags to wrap content and avoid the caching engine.<br />
<br />
This is not a default tag in Smarty and <b>will fail </b>if you have not registered the block function as provided in the example.Unknownnoreply@blogger.com0