tag:blogger.com,1999:blog-38358204506806909502024-03-13T12:14:21.101-07:00Firelit DesignThe blog of Firelit, a web development company in Grand Rapids, Michigan.Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.comBlogger109125tag:blogger.com,1999:blog-3835820450680690950.post-69094578752281355852014-11-05T13:00:00.001-08:002014-11-05T13:52:35.013-08:00Yosemite and SSL Certificate Verification Failed with cURLLet's say you're a developer, like myself, and you have just updated to Apple's latest operating system (Yosemite or 10.10) and all of a sudden the Twilio PHP SDK stops working. And, it gives you an error something like this:<br />
<br />
<span style="background-color: #f9f9f9; color: red; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;">SSL: certificate verification failed (result: 5)</span><br />
<br />
The problem disappears when you comment out the CURLOPT_CAINFO option, which makes it a bit more confusing. In other words, you can't use your own CA bundle/file. Others have also noted that it only really happens with certain certificate types, like wild-card domains (e.g., api.twilio.com doesn't work, for example).<br />
<br />
Well, it seems to be a bug on the specific version of cURL, version 7.37.1, that Apple has bundled with their operating system. Version 7.37.0 and the latest version of cURL both work fine.<br />
<br />
Check this out for all the details: <a href="http://sourceforge.net/p/curl/bugs/1404/">http://sourceforge.net/p/curl/bugs/1404/</a><br />
<br />
I haven't found a good way to fix it yet, myself, but the above link does offer some suggestions.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-69839364327503741312014-06-19T06:12:00.003-07:002014-06-19T06:16:48.173-07:00Fixing InnoDB error "the age of the last checkpoint is..."I recently switched a production database from MyISAM to InnoDB and I noticed the next day my logwatch email had a bunch of errors like this:<br />
<blockquote class="tr_bq">
<span style="color: #999999; font-family: inherit;">[140617 02:04:22] 140617 2:04:22 InnoDB: ERROR: the age of the last checkpoint is 9433709,</span><br />
<span style="color: #999999; font-family: inherit;">[140617 02:03:40] 140617 2:03:40 InnoDB: ERROR: the age of the last checkpoint is 9433931,</span><br />
<span style="color: #999999; font-family: inherit;">[140617 02:01:58] 140617 2:01:58 InnoDB: ERROR: the age of the last checkpoint is 9433673,</span></blockquote>
<div class="p1">
<span style="font-family: inherit;">Well, what does all this mean? First, as the comma at the end indicates, logwatch truncated the error message. I found that there is more information in the actual mysql.log file had more info:</span></div>
<blockquote class="tr_bq">
<span style="color: #999999;">InnoDB: which exceeds the log group capacity 9433498.</span><br />
<span style="color: #999999;">InnoDB: If you are using big BLOB or TEXT rows, you must set the</span><br />
<span style="color: #999999;">InnoDB: combined size of log files at least 10 times bigger than the</span><br />
<span style="color: #999999;">InnoDB: largest such row.</span></blockquote>
<div class="p1">
</div>
<div class="p1">
So, as it seems, the InnoDB log file settings need to be updated. I found a <a href="http://dev.mysql.com/doc/refman/5.5/en/innodb-data-log-reconfiguration.html">listing of the steps to take</a> on MySQL's website. Here are those steps fleshed out a little.</div>
<div class="p1">
<br /></div>
<div class="p1">
1) Make sure your <b>innodb_fast_shutdown</b> settings is <i>not</i> 2<b>. </b>To fix this, set it to one by runnning the following query:</div>
<div class="p1">
</div>
<blockquote class="tr_bq">
<b><span style="color: #38761d;">SET GLOBAL innodb_fast_shutdown = 1;</span></b></blockquote>
2) Shut down mysql and look for errors in the log to make sure nothing went wrong.<br />
<blockquote class="tr_bq">
<span style="color: #38761d;"><b>service mysqld stop</b></span><span style="color: #38761d;"><b>cat /var/log/mysql.log</b></span></blockquote>
3) Copy the old log files to a new place in case something goes wrong.<br />
<blockquote class="tr_bq">
<div class="p1">
<b><span style="color: #38761d;">mv <span class="s1">/</span>var<span class="s1">/</span>lib<span class="s1">/</span>mysql<span class="s1">/</span>ib_logfile<span class="s1">*</span> <span class="s1">..</span></span></b></div>
</blockquote>
<div class="p1">
4) Next edit your <b>/etc/my.cnf</b> file to increase your InnoDB log size:</div>
<blockquote class="tr_bq">
<span style="color: #38761d;"><b>innodb_log_file_size <span class="s1">=</span> 128M</b></span></blockquote>
<div>
You may see people suggesting really large values for the log file size -- I saw a value of 768M in one StackOverflow answer. If that seems like a suspiciously large, random value to you (especially considering the default is 5M) then you're on to something. But that begs the question, what should the value be? Here is a <a href="http://www.mysqlperformanceblog.com/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/">helpful article on how to properly size</a> your log files.</div>
<div>
<br /></div>
<div>
5) Lastly, watch your <b>/var/log/mysql.log</b> file and start MySQL back up.</div>
<blockquote class="tr_bq">
<b><span style="color: #38761d;">service mysqld start</span></b></blockquote>
<div>
One helpful tip, if you see this error in your log file,</div>
<blockquote class="tr_bq">
<span style="color: #999999;">/usr/libexec/mysqld: Incorrect information in file: './schema_name/table_name.frm'</span></blockquote>
<div>
then you probably tried to skip <b>step 3</b>, like I did. Turns out, <a href="http://www.mysqlperformanceblog.com/2011/07/09/how-to-change-innodb_log_file_size-safely/">this is an important step</a> and your MySQL server may not even start up, without it. It's easy to fix though, either go back and do <b>step 3</b> or remove your edits made in <b>step 4</b> and restart mysqld. You should be all set.</div>
<div>
<br /></div>
<div>
<br /></div>
Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com1tag:blogger.com,1999:blog-3835820450680690950.post-25449119410355798802013-10-21T06:31:00.001-07:002013-10-21T06:34:52.721-07:00Fixing json_encode() Problem in PHP 5.5 on Ubuntu 13.10I upgraded to <b>Ubuntu 13.10</b> over the weekend and everything went pretty well. It automatically brings <b>PHP 5.5</b> with it, too. When I tried to run a web app I was working on, though, I received this message:<br />
<br />
<pre style="color: red; margin-left: 20px;">Fatal error: Call to undefined function json_encode()
</pre>
<br />
I subsequently Googled around and came across a highly-ranked blog article which makes it sound like PHP 5.5 drops support for json_encode because of some silly licensing argument. The truth is, PHP 5.5 does <strong>NOT</strong> drop support for json_encode. For a much better and much clearer explanation, I recommend <a href="http://philsturgeon.co.uk/blog/2013/08/fud-cracker-php-55-never-lost-json-support">reading this article</a>. <br />
<br />
Now, enough of the balleyhoo! How do we fix it?<br />
<br />
It was was easy! Install the php5-json package and restart Apache. Voilà!<br />
<br />
<pre style="color: green; margin-left: 20px;">sudo apt-get install php5-json
sudo /etc/init.d/apache2 restart</pre>
<br />
Note that the author of the blog article linked above mentions that re-installing the php5-dev pacakged fixed his woes. While that didn't help me, you may want to give it a try if the above didn't help you.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com2tag:blogger.com,1999:blog-3835820450680690950.post-56422271005103179472013-07-26T19:28:00.001-07:002013-07-26T19:30:23.711-07:00Symmetric-Key Encryption: AES in PHP and what "mode" to chooseDoing some encryption? Want to use the same key for encryption and decryption? Well, I did too. Here are the results of a lot of internet searching.<br />
<br />
The <a href="http://php.net/manual/en/book.mcrypt.php">'mcrypt' extension</a> in PHP is the place to go for AES, symmetric-key encryption. AES is safe and secure – the US government has even ok'd 192-bit AES (and up) for <a href="http://csrc.nist.gov/groups/STM/cmvp/documents/CNSS15FS.pdf">top secret</a> documents. You can install it by running <span style="color: blue; font-family: Courier New, Courier, monospace;">yum install php-mcrypt</span> (if you're running Red Hat or CentOS) and then it is available for your coding pleasure.<br />
<br />
The next decision is what "mode of operation" to use for your AES encryption. There are a few different ways to do all the fancy math and permutations. Some are more secure than others. You'll notice that when using the <a href="http://www.php.net/manual/en/function.mcrypt-encrypt.php"><span style="color: blue; font-family: Courier New, Courier, monospace;">mcrypt_encrypt()</span></a> command, you have to specify the mode as the 4th parameter. You have a choice to make. PHP 5.4 currently has the following modes available (you can find all the options available to your environment by using <a href="http://www.php.net/manual/en/function.mcrypt-list-modes.php">mcrypt_list_modes</a>):<br />
<ul>
<li>cbc</li>
<li>cfb</li>
<li>ctr</li>
<li>ecb</li>
<li>ncfb</li>
<li>nofb</li>
<li>ofb</li>
<li>stream</li>
</ul>
If you're in the same boat I'm in – aka "not a cryptographer" boat – then this is just a nice list of letters. But there are a lot of cryptographers who put a lot of good info on the interwebs, thank goodness. I ran across this article on <a href="http://blog.cryptographyengineering.com/2011/11/how-not-to-use-symmetric-encryption.html">AES usage tips</a>, then there is the <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation">overly-neutral Wikipedia article</a>, and a <a href="http://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb">good-enough answer</a> to a similar question on Stack Exchange.<br />
<br />
Here are my collected thoughts on the matter:<br />
<ol>
<li>One glaring thing I came away with from all these sources is this: <b>DON'T USE <i>ECB</i></b>. </li>
<li>The second thing I came away with is this: <b>CTR would be the ideal, if it was available.</b> This is because it does some authentication to make sure the encrypted message really is an encrypted message and not some sort of cryptographic trojan horse. (The simple solution to this is to make sure you HMAC hash your encrypted text to make sure it isn't tampered with.)</li>
<li>The last thing I came away with is: <b>Use OFB or CFB</b> because they are pretty darn good and available in mycrpt.</li>
</ol>
Other thoughts? Do you know of even better articles on modes of encryption? I'm all ears!Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-79981759136608080602013-07-02T18:34:00.000-07:002013-07-02T18:35:50.050-07:00Checking the last SQL statements used by PHPActiveRecordI'm using <a href="http://www.phpactiverecord.org/">PHP-ActiveRecord</a> on a project and am loving it. But there are some things to learn and as a guy coming from the write-your-own-sql world, I do occasionally want to check what SQL queries that ActiveRecord is sending out there. I've used this bit of a code a few times to do so and it is immensely helpful for me as I try to see if I'm using this package correctly:<br />
<br />
<pre class="brush: php">echo Model::table()->last_sql;</pre>
<br />
Pop that in after you do your Model::find() or Model->save() or whatever, <b>just be sure to swap 'Model' out with your model's actual name</b>.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-72025249483790931642013-06-15T12:57:00.005-07:002013-06-15T13:02:48.028-07:00Error starting Apache (httpd) - Configuration files not readableHere is an interesting issue I ran into today while setting up a new VM. I had copied the Apache conf file and SSL/TLS certificate files onto my new server as root using wget. All of the file's ownerships and permissions looked right and I thought I was ready to go. Then I ran into these two misleading errors:<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">Could not open configuration file /etc/httpd/conf.d/ssl.conf: Permission denied</span><br />
<br />
and<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;">SSLCertificateFile: file '/etc/pki/tls/certs/mydomain.com.crt' does not exist or is empty</span><br />
<br />
Contrary to what Apache reported, the ssl.conf file did have the correct permissions and the crt file did exist and had contents. So what gives? Our trusty <a href="http://firelitdesign.blogspot.com/search/label/selinux">SELinux friend is at it again</a>, it seems. Because I had copied these files in from somewhere else, SELinux was detecting something off. It is an easy fix, though. Just run this command, specifing each of the files above:<br />
<br />
<span style="color: blue; font-family: Courier New, Courier, monospace;">restorecon -v /etc/httpd/conf.d/ssl.conf</span><br />
<br />
and<br />
<br />
<span style="color: blue; font-family: Courier New, Courier, monospace;">restorecon -Rv /etc/pki/tls/certs/</span><br />
<br />
That -R is for "recursive" and it means I want it to do the whole directory.<br />
<br />
After fixing up the SELinux permissions for these files I brought in, everything started up just fine!Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-26772831727478691212013-05-27T12:18:00.000-07:002013-05-27T12:19:39.739-07:00Using SQLite for Unit Testing in PHPUnit testing is infamous when one attempts to test database-interacting classes. I noted that some had suggested using SQLite when running phpunit to test these sorts of classes. Been working for me, so I thought I'd jot it down here.<br />
<br />
First, make sure sqlite3 is installed. On Ubuntu you'd run the following at the command prompt (assuming this step is necessary, but now I'm not quite sure):<br />
<blockquote class="tr_bq">
<span style="color: #073763; font-family: Courier New, Courier, monospace;">sudo apt-get install sqlite3 libsqlite3-dev</span></blockquote>
<div>
<br /></div>
<div>
Next, make sure PHP support for sqlite3 is installed enter this at the command prompt:</div>
<div>
<blockquote class="tr_bq">
<span style="color: #0b5394; font-family: Courier New, Courier, monospace;">sudo apt-get install php5-sqlite</span></blockquote>
<br />
And then, in the part of your PHP script where you set up PDO (if that's the class you use, as I do), you can specify sqlite's in-memory DB:<br />
<blockquote class="tr_bq">
<span style="color: #38761d; font-family: Courier New, Courier, monospace;">$conn = new PDO('sqlite::memory');</span></blockquote>
</div>
Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-881992288671501232013-04-25T10:28:00.000-07:002013-04-25T10:30:59.054-07:00Non-Profit Merchant Account TipsI feel like I've been around the block with merchant accounts. This is especially true for non-profits and online donations – I've been working in this field for a number of years. If you want to accept donations online and you want to do it without giving PayPal a big chunk of it, merchant accounts are the way to go. You'll need a platform or a good programmer, but those are pretty easy to come by these days (wink, wink).<br />
<br />
If you're a non-profit the risk you pose to the financial world is low giving you a little leverage when securing a merchant account. Here are few tips for those who are looking:
<br />
<br />
<ul>
<li><b>Say 'no thanks' to contracts</b> - The merchant service provider doesn't really need you to sign a contract. They just don't want you to leave and who can't blame them, that's how they make money. But you don't need no stinkin' contract. There is too many providers who will give you a good deal on a merchant account without one. Plus, you need an out if they decided to raise their prices on you one day (which happens, sometimes without warning).</li>
<li><b>Opt for 'interchange plus' pricing</b> - There are a few pricing options out there. Interchange plus usually ends up being the best deal because they give you wholesale rates plus a little overhead added on. In this case, if a donor uses a debit card that has a really low discount rate (say 0.5%, thanks to the <a href="http://en.wikipedia.org/wiki/Dodd%E2%80%93Frank_Wall_Street_Reform_and_Consumer_Protection_Act">Durbin amendment</a>) then your saving a ton of money. Other common, not-as-good options include 'tiered' and 'ERR' pricing. You might say that tiered pricing is credit card processor lingo for '<i>round it up and I'll keep the change</i>' and ERR pricing is synonymous for '<i>round it up and add some extra just in case</i>'.</li>
<li><b>Ask for an itemized list of fees</b> - The merchant world is all about fees, fees and more fees. And merchant service providers, generally speaking, do their best to hide fees. They do this so often that even when they're trying to be transparent, they're still hiding fees. It is really crazy and one of the few industries that can somehow get away with it (not sure why that is). When you get a merchant account quote, tell them you want to know about them all: gateway fees, statement fees, PCI compliance fees, IRS fees, Visa/MC fees, AMEX fees, discount rates, per-transaction fees, per-auth fees, batching/settlement fees, .... <i>everything!</i></li>
</ul>
<div>
Hope this helps and if you have any questions, reply below.</div>
Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-28555040881501981972012-10-17T09:01:00.003-07:002012-10-17T09:02:00.174-07:00Installing Multi-Byte PHP Functions<span style="color: #236e25; white-space: pre-wrap;"><span style="font-family: inherit;">I received this error today:</span></span><br />
<span style="color: #236e25; font-family: monospace; white-space: pre-wrap;"><br /></span>
<span style="white-space: pre-wrap;"><span style="color: #cc0000; font-family: Courier New, Courier, monospace;">Fatal error: Call to undefined function mb_strlen() </span></span><br />
<span style="color: #236e25; white-space: pre-wrap;"><span style="font-family: Courier New, Courier, monospace;"><br /></span></span>
<span style="color: #236e25;"><span style="white-space: pre-wrap;">And it would look the same, no matter what multi-byte PHP function I might be using: mb_strpos(), mb_substr(), etc. And it is beginning to be important to have this extensions installed if you are working with international, multi-byte character sets like UTF-8.</span></span><br />
<span style="color: #236e25;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="color: #236e25;"><span style="white-space: pre-wrap;">The fix is super easy. All you need to do is install the PHP multi-byte extension with yum (if you're on CentOS or RHEL). Do the following from the command line:</span></span><br />
<span style="color: #236e25;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="color: #236e25; font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">yum install php-mbstring</span></span><br />
<span style="color: #236e25; font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;">service httpd restart</span></span><br />
<span style="color: #236e25; font-family: Courier New, Courier, monospace;"><span style="white-space: pre-wrap;"><br /></span></span>
<span style="color: #236e25; font-family: inherit;"><span style="white-space: pre-wrap;">That installs the extension and restarts Apache. Then you're good to go!</span></span>Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-20568323564024159362012-09-20T08:43:00.002-07:002012-09-20T09:34:30.089-07:00MacBook Pro Retina & Linksys RoutersI have two Linksys wireless routers (WRT160N and E1200). One at an office, the other at home. I bought a MacBook Pro Retina a couple days ago (OS v10.8.1). I've now found that my new MBP doesn't play nice with Linksys.<br />
<br />
Typically what happens is that, while still connected (according to the status bar), the connection chokes for about 30 seconds -- nothing flows through the pipes. What is even crazier is that it does the same for everyone else on the network (Macs and PCs).<br />
<br />
This doesn't happen at Starbucks or the Apple store (which I am pretty sure don't use Linksys routers).<br />
<br />
I can't find anything online about this so I'm asking the question: Has any one else had any issues with the MBP or rMBP on Linksys routers?<br />
<br />
PS. The routers do have the latest firmware.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-18261128414617378052012-06-16T11:42:00.004-07:002012-06-16T11:54:12.745-07:00Installing Memcached on CentOSI have a web server running CentOS and wanted to get some good caching going for PHP use. This is how I installed <a href="http://memcached.org/">memcached</a>, from the command line:<br />
<br />
<ul>
<li>Install memcached</li>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">yum install memcached</span></li>
</ul>
<li>Install Pecl (if you don't yet have it, <a href="http://www.electrictoolbox.com/install-php-pecl-centos/">installing pear installs pecl</a>)</li>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">yum install php-pear</span></li>
</ul>
<li>Install Pecl's Memcached package (for PHP)</li>
<ul>
<li>Install dependencies, as needed</li>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">yum install php-devel</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">yum install gcc</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">yum install zlib-devel</span></li>
</ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">pecl install memcache</span></li>
<li>Use a text editor to add "extension=memcache.so" to php.ini (may be in the /etc folder)</li>
</ul>
<li>Restart the service</li>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">service memcached start </span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">service httpd restart</span></li>
</ul>
</ul>
<div>
And when you want some raw stats, you can get them via telnet:</div>
<div>
<ul>
<li><span style="font-family: 'Courier New', Courier, monospace;">telnet localhost 11211</span></li>
</ul>
<div>
And type "stats" to see hits, misses and more!</div>
</div>
<div>
<br /></div>
<div>
<a href="http://www.php.net/manual/en/memcached.get.php">Here</a> <a href="http://www.php.net/manual/en/memcached.set.php">are</a> <a href="http://www.webdeveloperjuice.com/2010/01/25/10-baby-steps-to-install-memcached-server-and-access-it-with-php/">some</a> examples of memcached use in PHP.</div>Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-69304109217742454762012-04-10T12:16:00.000-07:002012-04-10T12:16:00.763-07:00iPad POS ListI did some research a while back and compiled a list of Point of Sale (POS) systems that function on the iPad (and some on the iPhone, too). It is strangely harder than you'd think to find a complete list, like this. So, here they are, in no particular order:<br />
<ul>
<li><a href="http://www.getpose.com/" style="color: #1155cc;" target="_blank">http://www.getpose.com/</a></li>
<li><a href="http://www.poslavu.com/" style="color: #1155cc;" target="_blank">http://www.poslavu.com/</a></li>
<li><a href="http://revelsystems.com/" style="color: #1155cc;" target="_blank">http://revelsystems.com/</a></li>
<li><a href="http://www.erply.com/" style="color: #1155cc;" target="_blank">http://www.erply.com/</a></li>
<li><a href="http://www.cashierlive.com/" style="color: #1155cc;" target="_blank">http://www.cashierlive.com/</a></li>
<li><a href="http://www.vendhq.com/" style="color: #1155cc;" target="_blank">http://www.vendhq.com/</a></li>
<li><a href="http://thinkown.com/" style="color: #1155cc;" target="_blank">http://thinkown.com/</a></li>
<li><a href="http://www.shopkeep.com/" style="color: #1155cc;" target="_blank">http://www.shopkeep.com/</a></li>
</ul>Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com1tag:blogger.com,1999:blog-3835820450680690950.post-58382130906533191652012-04-04T06:09:00.003-07:002012-06-16T11:53:32.076-07:00Filezilla Password FileHave an FTP password in <a href="http://filezilla-project.org/">Filezilla</a> and need to get it? I often do, for some strange reason.<br />
<br />
If you run Windows 7, go to C:\Users\YOUR_USERNAME\AppData\Roaming\FileZilla<br />
<br />
You'll see a series of .xml files and sitemanager.xml stores all the goods (yes, in plain text... they let the OS/file-system handle security). Get what you need.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-86465331825853710102012-03-28T12:25:00.001-07:002012-04-06T21:44:46.696-07:00Floating Section Scrolls with Page (HTML & JS)<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-buaFBDGg_Ho/T3Ndi7C715I/AAAAAAAAAAc/w5GTOBKag_Y/s1600/temp.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://4.bp.blogspot.com/-buaFBDGg_Ho/T3Ndi7C715I/AAAAAAAAAAc/w5GTOBKag_Y/s1600/temp.png" /></a></div>
I had the need yesterday to make a section or block of HTML scroll with the page. I wanted it to stay in a spot on the page, relative to all else, until the visitor scrolled the page down. Then I wanted it to stay at the top of the page, never scrolling off the page. It was to be a section (eg, a navigation bar or image) that essentially had an initial "parked" position in the design, but should always be visible, even when the user scrolls down. Check out the illustration to the right and an <a href="http://lyricgarden.com/fun/we-are-young">example</a> of the code in use.<br />
<br />
I've seen different implementations of this. The most popular solution is a "chaser" where the element's absolute position is updated dynamically after each page scroll event. You have probably seen sites like this. They are a bit annoying and clunky - the element is constantly hiding and showing after every scroll.<br />
<br />
After no luck finding a solution that I liked, I created one. It is below for your enjoyment. It uses <a href="http://jquery.com/">jQuery</a> to make things easier (ie, this framework is required). Take, use and be merry.<br />
<br />
<b>AND, the javascript:</b><br />
<br />
<pre class="brush: jscript">$(function() {
window.floater = {};
/* Settings */
window.floater.element = $('#float'); // Element to float
window.floater.topMargin = 20; // Margin from top of window
/* Global Vars & Initial Position */
window.floater.captured = false;
window.floater.posi = window.floater.element.offset();
window.floater.marginLeft = parseInt(window.floater.element.css('margin-left').replace('px', ''), 10);
$(window).scroll(function() {
var curScroll = {
top: $(window).scrollTop(),
left: $(window).scrollLeft()
};
if (curScroll.top >= (window.floater.posi.top - window.floater.topMargin)) {
if (!window.floater.captured) {
window.floater.captured = true;
var scrollAtTrigger = curScroll.top;
if ((window.floater.posi.top - scrollAtTrigger) < window.floater.topMargin) scrollAtTrigger = window.floater.posi.top - window.floater.topMargin;
}
window.floater.element
.css({
position: 'fixed',
top: (window.floater.posi.top - scrollAtTrigger)+'px',
left: (window.floater.posi.left - window.floater.marginLeft - curScroll.left)+'px'
});
} else {
window.floater.captured = false;
window.floater.element.css({ position: 'static' });
}
});
$(window).resize(function() {
var posiFix = window.floater.element.css({position: 'static'}).offset();
window.floater.element.css({position: 'fixed'});
window.floater.posi.left = posiFix.left;
$(window).scroll();
});
});
</pre>
<br />
The nuts and bolts: Put the float wherever you'd like it to be on the page initially. Then, when the document is loaded, the JavaScript goes to work. It sets up two events: one page-scroll event and one page-resize event. This is where the hard work is done. Once the page scrolls past a certain point, the position of the floater is set to fixed which means it remains a certain position relative to the window or viewport. There is no flickering or chasing using this method. It is clean and smooth.<br />
<br />
Note: The floater's initial CSS position must be set as 'static' (which is a CSS default if it is undeclared). If you need to set it to 'relative' or 'absolute', use a wrapper to position it.<br />
<br />
Note 2: I've noticed on Firefox 6.0 that there is a weird bug (?) that causes iframes to refresh if their positioning switches from 'static' to 'fixed'. So, if you plan on playing a YouTube video in your floater, beware: it my refresh and reset your video on scroll.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-26100342793977068892012-03-27T12:55:00.000-07:002012-03-27T12:55:52.536-07:00Lyrics - Beautifully DisplayedA friend and I decided the world needed a lyric site that looked good and didn't bombard you with ads. We put together <a href="http://lyricgarden.com/">Lyric Garden</a> for this purpose. We're only starting with a few songs to see how things go. Check it out.Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-67756013115048357602012-03-22T20:10:00.000-07:002012-04-06T22:03:16.546-07:00Turn your iPod Touch into a PhoneThis was kind of a fun little project, so I thought I'd share. Just a heads up, before you get too far along, this is not free. I know Google is in the habit of giving away things like free phone calls, but this stuff (like making real phone calls) generally costs money.<br />
<br />
<b>First</b>, you'll need an <i>app for that</i>. I downloaded the <a href="http://itunes.apple.com/us/app/bria-iphone-voip-sip-phone/id373968636?mt=8">Bria VoIP SIP phone app</a>. (It is also available <a href="http://itunes.apple.com/us/app/bria-ipad-voip-sip-phone-video/id440744818?mt=8">for the iPad</a>.) This handy little app turns your iPod touch (or iPad) into a VoIP phone -- in other words, you can make phone calls over WiFi or a data connection.<br />
<br />
<b>Next</b>, you'll need a phone number (also called a DID). There are a lot of service providers out there but I've used <a href="http://flowroute.com/">Flowroute</a>, a company with servers in the southeast, for my interconnect. They charge about 1 cent per minute for calls to anywhere in the US plus $1.40 a month for the number. Needless to say, you can make a lot of long distance calls on the cheap.<br />
<br />
<b>Lastly</b>, you'll need to configure your Bria app to work with Flowroute. To do this, log into Flowroute and click on the "interconnection" tab. There you'll find the info you'll need. Then start the Bria app on your iPod and go to "settings" and click the plus sign to add a new account.<br />
<br />
<table style="margin: auto;">
<tbody>
<tr><td style="width: 150px;"><b>Bria Setting</b></td><td><b>Flowroute Setting</b></td></tr>
<tr><td>"Display as"</td><td><i>Your phone number</i> (eg, "15551230000")</td></tr>
<tr><td>"Username"</td><td><i>Your phone number</i> (eg, "15551230000")</td></tr>
<tr><td>"Password"</td><td>"Password"</td></tr>
<tr><td>"Domain"</td><td>"SIP Registrar / Proxy"</td></tr>
<tr><td>"Out. Proxy"</td><td>"SIP Registrar / Proxy"</td></tr>
<tr><td>"Auth Name"</td><td>"Username & Auth Username"</td></tr>
</tbody></table>
<br />
And that is it. Easy peasy. Click "Register" and your portable Apple device is a VoIP phone and you can make reliable, clear phone calls on the cheap. (Note: You'll need a pair of headphones that have a mic built in, like the headphones that come with the newer iPods.)Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-21488406903354157052012-02-26T08:08:00.006-08:002012-03-23T08:10:52.285-07:00Google and Privacy - Freakin' me outI love Google and their innovative (and FREE) products and services. But lately, they're starting to freak me out.<br />
<br />
For one, I noticed that all the display ads on the sites I visited started to look the same. That's right, Google knew what sites I had visited in the past and were showing ads for these sites. It was mildly disturbing. I guess I should have known that they had all that data on me, but when you start fixing my ads it is a little creepy. And how do you stop this? You can't unless you install an extension on your browser. That's right, there is actually no natural, install-free way to stop it. Google's extension for doing this is called <a href="https://chrome.google.com/webstore/detail/gbiekjoijknlhijdjbaadobpkdhmoebb">IBA Opt-out</a> (stands for Interest Based Ads).<br />
<br />
(Aside: Does anyone else think that the weird random combination of lower-case letters in the Chrome Web Store URLs make it look like a spam site?)<br />
<br />
Google web search has added a new feature lately that is creepin' me out, too. There is a new <a href="http://mashable.com/2012/01/10/google-launches-social-search/">integration with your social contacts</a>. I don't have a Google+ account yet I keep seeing what friends of mine recommend when I search for something on the web. I don't care what they recommend! I am searching Google not asking my friend Bill what he thinks. I could care less. And showing pictures of my friends at the top after I search is not as endearing as you'd think. It is like I having a friend whisper his answer in my ear every time I ask someone else a question.<br />
<br />
If you go to Google websites even occasionally, it is hard to miss that they have a <a href="http://www.google.com/policies/privacy/preview/">new privacy policy</a> that starts March 1st. I applaud the simplicity of the policy. However, I suspect that it isn't as innocent as it appears. Google now wants the ability to share your information <a href="http://waterford.patch.com/articles/attorneys-general-challenge-google-s-new-privacy-policy-f33c950b">across all of their products</a>. That's right, you could have a Google Docs account and a Gmail account and now Google wants to be able to use that information to shape your ads on Google Search. And even better, they can use your <a href="http://techcrunch.com/2012/02/28/no-more-no-more-no-more-no-more/">Google+ demographic data for their ads</a>! <b>(See 3/23/12 Update.)</b><br />
<br />
To rant a bit longer, what about the strange Google Chrome login that has started to appear in my browser? I don't even remember asking it to sync EVERYTHING between my two computers and their browsers. But it assumed I did. How nice (that's sarcasm, by the way).<br />
<br />
This all is starting to make me want to diversify. Microsoft, for instance, appears to have a nice <a href="http://office.microsoft.com/en-us/">replacement for Google Docs</a>. Maybe it also time to switch to <a href="http://wordpress.com/">WordPress</a> for my blog. One thing is for sure, I certainly wont be using Google+ anytime soon. That's all I need, to give Google more personal information about me.<br />
<br />
This is affecting how I see Google new products, now. I saw an article today about a new <a href="http://news.cnet.com/8301-13924_3-57383979-64/google-may-enter-tablet-market-with-7-inch-design/">Google tablet</a>. If this had come out last year, I would be excited to check it out. Now, well ... not so much. Why would I buy something from the company that has an over-zealous approach to taking my information and spreading it across all of their services and sites with or without my permission? No thanks.<br />
<br />
<b>Update 3/2/12</b>: After <a href="http://tech.slashdot.org/story/12/03/02/1358243/google-best-adaptation-of-a-novel-to-a-patent">reading this</a> I started migrating my personal Blogger blogs to a self-hosted multi-site WordPress install. This one blog (firelitdesign) is going to stay here for the time being. The rest were migrated.<br />
<br />
<b>Update 3/23/12</b>: An ex-Googler apparently also had concerns and started a project to help<a href="https://disconnect.me/tools"> block Google, Facebook and Twitter</a> from tracking your movements around the web.Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-58502053103771721642012-02-24T07:38:00.001-08:002013-01-31T10:10:02.731-08:00Forming a Michigan LLCWhen I was living in California a few years back I used LegalZoom to form an LLC. After that I moved to Washington and now I live in Michigan. In each of these last two states I formed an LLC without the help of a 3rd party. I was surprised how easy it was. So I am writing this post to help residents of Michigan. There is no reason to pay LegalZoom to do these things for you... save your money, it's easy!<Br><Br>
Quick disclaimer: I'm not a lawyer and I don't want to be one. So take this all with a grain of salt. I may be wrong on some detail and if you really want to make sure you did everything correctly, you should contact a lawyer.<Br><Br>
<b>Michigan LLC</b><Br>
Step 1 is to make sure you can actually use the name you picked out -- someone may have beaten you to it. I'd recommend doing a quick <a href="http://www.dleg.state.mi.us/bcs_corp/sr_corp.asp">Michigan search</a> and <a href="http://tess2.uspto.gov/bin/gate.exe?f=login&p_lang=english&p_d=trmk">USPTO trademark search</a> for your business name. (Michigan has some more <a href="http://www.dleg.state.mi.us/bcsc/forms/corp/pub/8009.pdf">business naming guidelines</a> that may be helpful.)<Br><Br>
Step 2 is to form the LLC. <a href="http://www.dleg.state.mi.us/bcsc/forms/corp/llc/700.pdf">Click here</a> to download the required form (BCS/CD-700). Now, the instructions are on page 2 and it is pretty clear, but I thought I'd summerize if you aren't into reading instructions. <Br><Br>
<i>Article I:</i> This will be the name of your company. Don't forget to add "LLC" to the end of the name. It is required.<Br>
<i>Article II:</i> You can just say that you're generally in compliance or list what your LLC will be doing for business.<Br>
<i>Article III:</i> Leave blank if the LLC has no end or dissolution date. <Br>
<i>Article IV:</i> This is where you put your name and address.<Br>
<i>Article V:</i> This is where you would tell Michigan that your LLC is managed by a manager (someone besides the LLC members). But for most, like freelancers and small home-businesses, you will be member-managed and will leave this field blank.<Br><Br>
Have it signed by each member and send it in. It will take about 2 or 3 weeks to hear back (unless you expedite).<Br><Br>
Lastly, after you form your Michigan LLC (and get back confirmation) you can apply for a <a href="http://www.dleg.state.mi.us/bcsc/forms/corp/corp/541.pdf">DBA name</a> (if you'll be operating under another name besides your new LLC) and <a href="https://sa2.www4.irs.gov/modiein/individual/index.jsp">get a FEIN</a> (a kind of social security number for a business). <Br><Br>
It is all quite easy. Save yourself some money and do it yourself.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com3tag:blogger.com,1999:blog-3835820450680690950.post-31429117713493755502012-01-25T19:11:00.000-08:002012-04-06T21:46:48.501-07:00jQuery UI & Disabling Text Selection on ClickPart of making a wonderfully interactive website with jQuery is the process of making certain elements clickable. Sometimes that means making a portion of text interactive without using the regular means of a hyperlink. One problem comes up when doing this, however. When a person clicks rapidly the browser usually interprets this to mean you want to highlight a word or paragraph. How do you stop this?
Call .disableSelection() on the element with jQuery. This will disable text selection. For example:
<pre class="brush: jscript">
$('#elementId').disableSelection();
</pre>
It actually binds an event on the object which prevents the default behavior. It is an undocumented feature but it is awfully handy. Remember: it requires jQuery and jQuery UI as it is part of the jQuery UI core.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-39148775216279818542012-01-13T20:21:00.000-08:002012-04-06T21:48:48.497-07:00Synchronous AJAX with JQueryYes, you read that right. I just didn't think anyone would understand SJAX.<br />
<br />
AJAX, if you don't know, stands for Asynchronous JavaScript and XML and is the term widely applied to sending HTTP POST and GET requests from client-side javascript. In JQuery, that would be <a href="http://api.jquery.com/jQuery.ajax/">$.ajax()</a> or <a href="http://api.jquery.com/jQuery.getJSON/">$.getJSON()</a> or any one of the other <a href="http://api.jquery.com/category/ajax/shorthand-methods/">similar variations</a>.<br />
<br />
The question that I had, to continue with the topic of this post, was, How do I do preform a synchronous AJAX call? That is, how would I treat an AJAX call as if it were inline javascript. The JQuery functions I mention above have a parameter where you would specify the call-back function that would run after the requested document is fully retrieved by the client, hence the response and call back are run asynchronously, or whenever the response has been received from the server. Then, how do I make this synchronous so that the code after the call does not execute until the javascript GET or POST is complete.<br />
<br />
Well, it is pretty darn easy, I've found. There is a single parameter, "async," that you set to false. That's it. I've written this whole blog post and the answer is a one-word parameter: async.<br />
<br />
<pre class="brush: jscript">$.ajax(ajaxurl, {
async: false
});
</pre>
<br />
So, now you know how to do SJAX. ;)Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-22570523356270394412011-12-01T08:43:00.000-08:002011-12-16T09:50:05.548-08:00Web App Framework Review: Sencha Touch, jQuery Mobile & moreI was recently evaluating the different frameworks for developing mobile web apps. I created an app in Sencha Touch, jQuery Mobile and JQTouch.(I also did a responsive web site using media queries, but this isn't so much a framework.) Here is my summary.<br><Br>
<a href="http://www.sencha.com/products/touch">Sencha Touch</a> is very different than anything I have used before. All of the content of the web app is built with JS. You code everything with JS. This causes things to be a bit janky, especially on older smart phones that need more time to process all that script. The biggest drawback, however, is that the online documentation is very difficult to use, especially for newbies. They have a few video tutorials online, but some are outdated and many are inconsistent (some use MVC architecture, for instance, which really throws you off if every other tutorial doesn't). All-in-all, if you are a web developer by trade and are used to manipulating DOM-level elements, this is a very frustrating framework to try to learn. Be ready to spend a serious amount of time on the learning curve. (Also, you have to pay Sencha if you want the latest and greatest version of their framework.) After attempting a few different projects with Sencha Touch over months, I grew frustrated and threw in the towel, even outsourcing the remainder of one project to India.<br><Br>
<a href="http://jquerymobile.com/">jQuery Mobile</a> is well documented and has plenty of example code for you to follow along. You develop your web app as you would a website and use different data-xxxx attributes on HTML objects to describe how objects should be styled or used. Once you have your structure, jQuery Mobile takes care of the rest, making everything look nice and employing fancy animated screen transitions. There is a small learning curve when getting started, nothing compared to Sencha Touch. And last but not least, jQuery Mobile is FOSS and appears to be in very active development. I was very happy with the example projects I put together with jQuery Mobile. They were easy to finish and worked well.<br><Br>
<a href="http://jqtouch.com/">JQTouch</a>, when I evaluated it, didn't appear to be in active development. The documentation was a little sketch and I found the demo/example code and the documentation disagreed on how things should be implemented. It took some trial and error to find out which methods were correct. I wouldn't recommend this framework for development unless they have taken great strides in recent months.<br><Br>
I want to mention <a href="http://www.alistapart.com/articles/responsive-web-design/">responsive web design</a> because it has great potential. While it doesn't give you the web app feel and isn't really a web app framework, it is definitely a good way to go if you need to develop a mobile web site. The pages load faster than they would using a web app framework (there is much less styling and JavaScript in the background). On the flip side, there are no fancy transitions, but that can be a good thing. You are in control of all the styling and the size of all the UI elements. Plus when designed right, it works on screens of all sizes -- there is no need for special mobile sub-domains or redirects.<br><Br>
In the end, no web app framework is perfect and completely replicates the native experience -- that hasn't happened, yet. With this said, I recommend jQuery Mobile and responsive web design as my favorites. They are different solutions for different problems (jQuery Mobile for a native-app experience, responsive for informational sites), but I would strongly suggest evaluating them if you have a new mobile web project coming up.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com4tag:blogger.com,1999:blog-3835820450680690950.post-91324812650465295472011-11-30T09:27:00.001-08:002011-11-30T09:32:21.870-08:00Hebrew Flash Card Web AppWhile evaluating different web app frameworks, I put together a little web app to help me get back up to speed with my biblical Hebrew vocab. And if you know anything about trying to read the Hebrew Bible, knowing a good amount of vocab is (unfortunately) essential. The flash card app is built using Sencha Touch's framework and is at <a href="http://hebrewflash.me/">http://hebrewflash.me/</a> ... check it out on your smartphone or iPod touch. The chapter divisions are based on <i>Basics of Biblical Hebrew</i> by Pratico and Van Pelt (Zondervan) so it is a great free vocab tool for students using this textbook.Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-13827673069963595222011-11-17T23:23:00.001-08:002011-11-17T23:50:56.188-08:00Partition and Mount a Drive on CentOSI have a few servers over at Softlayer. I recently procured a monthly computing instance with an additional 200 gigs of drive space. Thing is, the extra HD space doesn't come partitioned, formated or mounted. So, here is what you do:<br />
<br />
First things first. Find the name of the physical drive: <span class="Apple-style-span" style="color: blue;">fdisk -l</span><br />
<br />
This command will return a list of drives and information about each. You should find one that hasn't been partitioned with a name like /dev/sdb (or in my case /dev/xvdc for a computing instance) or similar. Check the size of the drive to make sure it is what you are looking for.<br />
<br />
Next, partition the drive: <span class="Apple-style-span" style="color: blue;">fdisk /dev/xvdc</span> (using the name of the drive, of course)<br />
<br />
Once in the fdisk utility, press <span class="Apple-style-span" style="color: blue;">p</span> to print the partitions to the screen. There should be none, because you haven't created any yet. If there are, are you sure you are using the right drive?<br />
<br />
Next press <span class="Apple-style-span" style="color: blue;">n</span> to create a new partition, press <span class="Apple-style-span" style="color: blue;">p</span> for a primary partition, <span class="Apple-style-span" style="color: blue;">1</span> for the first partition, and then use the default first and last cylinder (unless you know what you are doing, of course). Once this is set up, you can press <span class="Apple-style-span" style="color: blue;">p</span> to make sure it worked and then finally, <i>and most importantly</i>, press <span class="Apple-style-span" style="color: blue;">w</span> to write the changes to disk.<br />
<br />
In the previous command, you'll get a slightly different name for the partition you created. It probably added a letter, something like /dev/sdb1 or /dev/xvdc1 would be right. You'll need it to format the drive: <span class="Apple-style-span" style="color: blue;">mkfs -t ext3 /dev/xvdc1 </span>(I've used the ext3 file system, here, because it suited me just fine and is probably the most common.)<br />
<br />
Now, where would like the disk mounted? You'll have to create a folder as the mount point. If you want the disk to be used for a new /data directory, then you'll have to create a folder with this name: <span class="Apple-style-span" style="color: blue;">mkdir /data</span><br />
<br />
Next, add the drive and mount point to the /etc/fstab file so that it will be mounted at boot time. Use your favorite text editor, as they say. I used <span class="Apple-style-span" style="color: blue;">vi /etc/fstab</span> and I added a new row, matching the spacing of the other rows: <span class="Apple-style-span" style="color: blue;">/dev/xvdc1 /data ext3 defaults 1 2</span><br />
<br />
Lastly, you mount the drive using <span class="Apple-style-span" style="color: blue;">mount /dev/xvdc1</span> and you are all done.<br />
<br />
Head on over to <span class="Apple-style-span" style="color: blue;">cd /data</span> and check it out. Or run <span class="Apple-style-span" style="color: blue;">mount</span> without parameters to check out the details.<br />
<br />
PS. Here are a <a href="http://www.skullbox.net/newsda.php">couple</a> <a href="http://tldp.org/HOWTO/Partition/fdisk_partitioning.html">websites</a> I used when I was working through this problem myself.Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com1tag:blogger.com,1999:blog-3835820450680690950.post-56820903791819355102011-11-02T17:09:00.000-07:002011-11-02T17:10:08.858-07:00Synchronize Facebook Status & TwitterThere is so much unhelpful junk out there on the web when you do a Google search on synchronizing your Facebook status' with Twitter. So, a quick post.<br />
<br />
If you want your Facebook status to auto-tweet, go to <a href="http://www.facebook.com/twitter/">http://www.facebook.com/twitter/</a><br />
<br />
If you want your Tweets to auto-Facebook-status-update (why is there no verb for this?), go to <a href="http://apps.facebook.com/twitter/">http://apps.facebook.com/twitter/</a><br />
<br />
It's just a slight change in the sub-domain. You don't need any 3rd part software or other service. Facebook and Twitter worked this out among themselves already.Erichttp://www.blogger.com/profile/04711486359505177802noreply@blogger.com0tag:blogger.com,1999:blog-3835820450680690950.post-47748080764331998892011-10-03T10:56:00.000-07:002011-10-03T10:56:57.265-07:00jQuery Mobile Date PickerI've been working with <a href="http://jquerymobile.com">jQuery Mobile</a> on a new form. I have the need for a datepicker and was really impressed with what a man by the name of jstage has put together. It is really thurough. So, if you are looking a flexible, <a href="http://dev.jtsage.com/jQM-DateBox/">mobile date picker</a>, this is a good one. Erichttp://www.blogger.com/profile/15254841764690459317noreply@blogger.com0