Saturday, August 05, 2006

TemplateMonster Template Installation

After having used XAMPP to install Apache, MySQL and PHP, I am now ready to install a web site template from TemplateMonster.

I purchased and downloaded a template and copied the unzipped files to ../htdocs/shop. During the install of the template, which is just like the install of the dummy catalog that comes with osCommerce, make sure to check the box to save sessions to the database, not files. I had problems with files. It complained about a tmp directory not existing. I created one but it still gave me problems.

I also went in and changed the directory security in my httpd.conf file to protect the admin directory. See previous post for details.

There were some sql errors after installing the template. I had to modify some of the queries to make them work. I found help on the osCommerce site.

First change is here. Do what is suggested in post dated 11 Nov 2005 17:16:06.
Second change seems to be related to MySQL4 vs MySQL5. I have MySQL5 running. In order to fix the queries, I had to find out which .php file(s) the queries were in. I couldn't search the .php files using Windows Explorer because Explorer is stupid. I had to download a little utility called XP_FileFilter.exe from here, that helps you enable searching for files containing text with files that have "unregistered extensions".

I did what was suggested in the post dated 15 Jun 2006 07:18:13 of the second change link above. The change needed to be made in the \htdocs\shop\index.jsp file. (Thank you XP_FileFilter!)

Now the admin pages...
I browsed to the admin site, entered my username and password, and got this:

Fatal error: Cannot re-assign $this in C:\Program Files\xampp\..\includes\classes\upload.php on line 31

Fix is here. Change $this = null; to unset($this);

Other sql query fixes
modified products_new.php - changed from clause to have inner join instead of comma
modified index.php - changed all from clauses to have inner joins instead of commas
modified index.php - changed a reference from p2c.products_id to p.products_id in one of the queries. p2c was not an alias in the query.

Tuesday, August 01, 2006

osCommerce 2.2 and PHP 5.2

osCommerce 2.2ms2
PHP 5.2.0RC2-dev

Driven by the desire to be able to use slick web site templates provided by TemplateMonster, I discovered I would need to install osCommerce. TemplateMonster has web site templates that run on osCommerce 2.2.

osCommerce is an online shop e-commerce solution that offers a wide range of out-of-the-box features that allows online stores to be setup fairly quickly with ease and is available for free as an Open Source based solution.

osCommerce can be installed on any server where a web server is running that has been installed with PHP.

NOTE: The following few paragraphs describe my attempt to get this working by manually installing each app. I scrapped my manual installation of these apps and went with XAMPP's installation instead. The details are further down in the post.


So to get started I installed a PHP Hypertext Preprocessor on my server running Apache 2.2. After two failed attempts with PHP 4.4.2 and PHP 5.1.4, I discovered that I had to use PHP 5.2.0RC2-dev, which is the only version that runs on Apache 2.2. I'm hoping for a release version soon.

I unzipped the zip file to c:\php and followed the directions outlined in the install.txt file.

Highlights:
Added "c:\php" to my PATH environment variable.
Added to Apache httpd.conf:
LoadModule php5_module "c:/php/php5apache2_2.dll"
AddType application/x-httpd-php .php
PHPIniDir "C:/php"

Tested the PHP installation with a simple test.php file that I stuck in my default Apache doc folder:
C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\test.php

The contents of test.php are:
<?phpinfo()?>

Then just browse to http://localhost/test.php and you should get a page showing a bunch of system info. NOTE: I had to use the php.ini-dist file instead of the php.ini-recommended file to get test.php to display anything. I didn't compare the two to find out why.

Installing osCommerce
Looks like there are problems getting osCommerce to run with PHP5.

The milestone release that I have claims to have fixed some PHP5 issues. Continuing with installation. Follow directions in documentation.pdf.

php.ini - turned register_globals On

Step 2 of osCommerce install does not work.

Added "php_value register_long_arrays 1" to htdocs/catalog/.htaccess file.
(didn't help)

XAMPP to the rescue!!

After unsuccessful efforts to get it working, I decided to scrap it all and use XAMPP, an easy to install Apache distribution containing MySQL, PHP, Perl and a bunch of other apps, including an add on install for Tomcat.

I used the Windows installer version of XAMPP. Then I used the Windows installer version of the Tomcat add-on.

Other things:
Enabled innodb engine in mySQL because I wanted full transaction support in my databases. Modified ..\xampp\mysql\bin\my (no extension). Commented out:
#skip-innodb
Uncommented all the innodb lines after the skip-innodb line. I also increased most of the memory settings throughout the file since I have more the 64M on my machine.

Set jvm memory settings for Tomcat.
Modified ..\xampp\tomcat_start.bat. Added line:
set JAVA_OPTS=-xms256m -xmx256m

After installing Tomcat as a service as mentioned below, I ran ..\tomcat\bin\tomcat5w.exe to set memory options, since the service does not use tomcat_start.bat.

Enabled name-based virtual hosts.
Modified ..\xampp\apache\conf\httpd.conf. Uncommented lines:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_http_proxy.so
Include conf/extra/httpd-vhosts.conf

Modified ..\xampp\apache\conf\extra\httpd-vhosts.conf. Uncommented line:
NameVirtualHost *:80

Added in all my virtual hosts.

Used apache -S and apache -t at a command prompt to check syntax.

NOTE: I did have a problem because I copied the sample virtual host entries in httpd-vhosts.conf and then modified them. I assumed that @rel_logfiledir@ was some sort of macro and just left it in my virtual host definitions for the error logs. This caused apache to fail on startup with a message in the Windows Event Viewer as follows:

The Apache2 service terminated with service-specific error 1 (0x1).

After a bit of trial and error, I figured out it was the @rel_logfiledir@ that was causing the problem.

I went through the security section of the docs and secured everything as was suggested. I downloaded and installed mySQL Administrator and mySQL Query Browser from mysql.com since I am more familiar with those mySQL tools than the ones that come bundled with XAMPP.

osCommerce Installation
Unzipped and followed instructions in documentation.pdf.
xampp\apache\bin\php.ini - turned register_globals On
Everything installed fine following the instructions in the pdf and on screen.

Address Some Security Warnings
When I ran the default osCommerce catalog site, I had two warnings at the top. The first advised me to delete the install folder for security reasons. The second said:

Warning: I am able to write to the configuration file: C:/Program Files/xampp/htdocs/catalog/includes/configure.php. This is a potential security risk - please set the right user permissions on this file.

I just had to make the file read only.

I discovered that the osCommerce administration tools were wide open to anyone savvy enough to browse to the \catalog\admin URL.

Securing the osCommerce Admin Tools
Create an adminosc user in apache. The following command does this and asks for a password:

C:\Program Files\xampp\apache\bin>htpasswd -c "c:\program files\xampp\apache\passwd\passwords" adminosc

Add the following to httpd.conf to secure the admin directory:

<directory>
AuthType Basic
AuthName "osCommerce Admin Files"
AuthUserFile "C:/Program Files/xampp/apache/passwd/passwords"
Require user adminosc
</directory>

Email
Although XAMPP comes with Mercury Mail Transport, I didn't want to deal with configuring a mail server on my server, so I decided to just use my ISP's mail server for all email needs.

I was having trouble getting email to work using my ISP's mail server. I had to:


  • Change php.ini's email settings (SMTP = mail.xmission.com). Left other settings commented out, except smtp_port of course.

  • Changed the tep_mail function in \xampp\htdocs\shop\includes\functions\general.php as suggested here.

  • Changed settings in osCommerce admin's E-mail Options page. Changed "E-Mail Transport Method" to smtp and "E-Mail Linefeeds" to CRLF since I'm running on a Windows box.

Tomcat
Configure Tomcat to run as a service. By default, the XAMPP installation provides batch files to start and stop Tomcat. I want to run it as a service so that when the system reboots, I don't have to login to start Tomcat.

To run Tomcat as a service, simple open a cmd prompt here \xampp\tomcat\bin and type:

service.bat install

Then open the Services control panel, edit the properties of the newly installed service and change startup type to "automatic" instead of "manual".

Changed the Logon user of the service to use a tomcat user account that I setup. Didn't want the Tomcat service running under an admin account for security reasons. I edited the tomcat folder security settings, giving full control to this user as well.

tomcat user
  • Member of "Users"
  • User cannot change password
  • Password never expires

Virtual hosts with Apache and Tomcat

I wanted the ability to host multiple domains from one instance of Tomcat and also wanted to keep the domain name in tact in the browser address bar. I had already been hosting multiple web sites, but when the user would type something like "www.somedomain.com", I would have to redirect them to "www.whitesandsolutions.com/somedomain/do/home" or something like that. What I wanted was the www.somedomain.com to remain in tact.

After a bit of reading, I decided to install the Apache web server and use the virtual host functionality. Click here for the Apache virtual hosts documentation. Name-based virtual hosts were exactly what I needed. Making it all work correctly took a bit of trial and error. Here are some notes of mine. I may not have it configured in the best possible way, but it does work...

Install Apache Web Server 2.2
Install Tomcat 5.5.17

Here is my Apache httpd.conf file. All commented lines have been removed for brevity:

ThreadsPerChild 250
MaxRequestsPerChild 0
ServerRoot "C:/Program Files/Apache Software Foundation/Apache2.2"
Listen 80
LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
LoadModule asis_module modules/mod_asis.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_default_module modules/mod_authn_default.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authz_default_module modules/mod_authz_default.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule cgi_module modules/mod_cgi.so
LoadModule dir_module modules/mod_dir.so
LoadModule env_module modules/mod_env.so
LoadModule imagemap_module modules/mod_imagemap.so
LoadModule include_module modules/mod_include.so
LoadModule isapi_module modules/mod_isapi.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule mime_module modules/mod_mime.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule userdir_module modules/mod_userdir.so
ServerAdmin your.name@yourcompany.com
ServerName 123.123.123.123
DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Satisfy all
</Directory>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
<FilesMatch "^\.ht">
Order allow,deny
Deny from all
</FilesMatch>
ErrorLog logs/error.log
LogLevel warn
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog logs/access.log common
</IfModule>
<IfModule alias_module>
ScriptAlias /cgi-bin/ "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin/"
</IfModule>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
DefaultType text/plain
<IfModule mime_module>
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
</IfModule>
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
NameVirtualHost *:80
<VirtualHost *:80>
ServerName 123.123.123.123
ServerAdmin your.name@yourcompany.com
DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
ErrorLog logs/error.log
</VirtualHost>
<VirtualHost *:80>
ServerName www.domain1.com
ServerAdmin your.name@yourcompany.com
DocumentRoot "C:/Tomcat 5.5/webapps/domain1/ROOT/"
ServerAlias domain.com
ErrorLog logs/error.log
ProxyPass / http://localhost:8081/
ProxyPassReverse / http://localhost:8081/
</VirtualHost>
<VirtualHost *:80>
ServerName www.domain2.com
ServerAdmin your.name@yourcompany.com
DocumentRoot "C:/Tomcat 5.5/webapps/domain2/ROOT/"
ServerAlias domain2.com
ErrorLog logs/error.log
ProxyPass / http://localhost:8082/
ProxyPassReverse / http://localhost:8082/
</VirtualHost>
<VirtualHost *:80>
ServerName www.domain3.com
ServerAdmin your.name@yourcompany.com
DocumentRoot "C:/Tomcat 5.5/webapps/domain3/ROOT/"
ServerAlias domain3.com
ErrorLog logs/error.log
ProxyPass / http://localhost:8083/
ProxyPassReverse / http://localhost:8083/
</VirtualHost>


If I remember correctly, the relevant changes I made from the version of this file as it was installed by default was to uncomment a couple of LoadModule lines and then add the virtual host lines at the bottom. I wanted to include the whole thing though for reference.

Once this was done, I then had to configure Tomcat. Here is my Tomcat server.xml file:

<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.core.AprLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.storeconfig.StoreConfigLifecycleListener"/>
<GlobalNamingResources>
<Environment name="simpleValue" type="java.lang.Integer" value="30"/>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" maxHttpHeaderSize="8192"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
connectionTimeout="20000" disableUploadTimeout="true" />
<Connector port="8009"
enableLookups="false" redirectPort="8443" protocol="AJP/1.3" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
<Service name="domain1">
<Connector port="8081"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" acceptCount="100" connectionTimeout="20000"
proxyName="www.domain1.com"
proxyPort="80" disableUploadTimeout="true" />
<Engine name="domain1" defaultHost="domain1-host">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>

<Host name="domain1-host" appBase="webapps/domain1"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
<Service name="domain2">
<Connector port="8082"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" acceptCount="100" connectionTimeout="20000"
proxyName="www.domain2.com"
proxyPort="80" disableUploadTimeout="true" />
<Engine name="domain2" defaultHost="domain2-host">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Host name="domain2-host" appBase="webapps/domain2"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
<Service name="domain3">
<Connector port="8083"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" acceptCount="100" connectionTimeout="20000"
proxyName="www.domain3.com"
proxyPort="80" disableUploadTimeout="true" />
<Engine name="domain3" defaultHost="domain3-host">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
<Host name="domain3-host" appBase="webapps/domain3"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
</Host>
</Engine>
</Service>
</Server>

The Tomcat directory structure looks like this:



The rest is all standard stuff. Create your ROOT.xml context files, and deploy your web sites. I created an index.jsp file for each of my apps so that when the user typed in www.domain1.com it would redirect to www.domain1.com/do/home. My index.jsp file looks like this:

<%@ taglib uri="/WEB-INF/lib/struts-logic.tld" prefix="logic" %>
<logic:redirect href="
http://www.domain1.com/do/home">;

And I added index.jsp to my welcome-file-list in my ROOT.xml context file:

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>


Comments are welcome. If you have better, more efficient ways of setting this up, please let me know.

Wednesday, March 29, 2006

New Company - RemindMeCall

I started a new company with a friend of mine, Chris Brockbank, called RemindMeCall, http://www.remindmecall.com. It's been a blast getting it going. I developed the web site and the web application, and Chris has been testing the app and doing some marketing.

We have a number of people excited about the product. One company, Charmed Moments, has six of their top distributors using our system, in preparation for a big sales conference they are having in August. They're using it to place reminder calls to the guests invited to their parties. They anticipate it will boost attendance at the parties, and therefore, boost the sales at the parties. Kim Roylance, President and Co-founder, is hoping to create some compelling case studies from these six distributors over the next couple of months and then present it at the sales conference in August. This could mean hundreds of new subscribers for us!

There are two other large direct sales companies we will be speaking with in the next 3-4 weeks.

Another market for the system is the medical industry, including dentists, optometrists, chiropractors, etc. All of these professionals deal with appointments, and having even one "no-show" results in a loss of $100+ dollars. We have an optometrist in Idaho who is using the system and is planning on having his wife attend his next convention, setting up a booth, and selling the product.

She can do this because RemindMeCall has a great upside if you sell it: 25% commission, plus incentives to increase that up to 40%. And this is recurring revenue, meaning each month that your clients continue to use the system, you as a sales person receive your cut of their monthly subscription. It's easy to see how your monthly intake could just keep growing and growing!

There are so many possibilities for the use of this system. See personal uses and business uses.

I am currently working on providing a web service interface to the product, which opens the door for software vendors to integrate their systems with RemindMeCall's suite of services. All the software products used by doctors, dentists, chiropractors, optometrists, etc., could provide appointment reminders easily and effectively by integrating with our web service interface.

It'll be interesting to see how it all turns out.