In x-cart, we couldn’t upload an image because the form gave us an error. After a lot of troubleshooting, here’s what we found to make the upload script work:
We made sure these folders and their subfolders had ‘write’ (777) permissions set:
1.
2.
3.
Also, we made sure the directory set in the PHP configuration option ‘upload_tmp_dir’ (in the php.ini file) had the permissions set to 777.
Pretty easy fix. Where we got tripped up was the fact that the log folder had to have write permissions. Why that is related to the image files, I’ll never know!
SecureCRT is a great SSH and telnet terminal client. It’s not free, but for the price, it’s well worth it. It handles ssh2 very nicely, and has a username system that’s better than PuTTY, in my opinion.
The only thing that I don’t like about it is that it makes a little beep by default when you hit certain keys; For example, if you type cd somedir and hit tab, it’ll autofill what it can (the functionality actually comes from the Linux shell), however, if it can’t complete a filename because there are two similar ones, it’ll play a little beep. As with another post of mine, little beeps for things are extremely annoying when I’m wearing headphones, so here’s how to remove the beep in SecureCRT version 3.3 (I realize this is an old version, but I’ve never needed to upgrade):
Go to Options -> Session Options. Click on “Options”, uncheck the “Audio Bell”.
This will remove that little beep in most situations.
I consider myself fairly good at regular expressions, which is a way to match specific patterns within a string of text; however, today, I learned a new little nugget of information regarding pattern matching.
We needed to match any filename that ended in html or php, but didn’t start with the word “form”. The regex syntax that I learned today was the Zero-width negative lookahead assertion which follows the form (?!pattern). This matches only if the subexpression denoted by the parenthesis does not match at this position on the right. Therefore (?!form) would match as long as form wasn’t at the specified position.
The whole regular expression was: ^(?!form).*\.(php|html)$
The first carot ^ denotes the start of the string, then our negative lookahead makes sure it doesn’t start with the word “form”. After that the dot star matches anything until it finds a period (the backslash or escape character makes it look for a period instead of it’s default “any character”. Then it looks for php or html (the pipe or | represents the boolean OR), and finally the $ indicates the end of the string. It does a lot in just a few characters.
Incidentally, (?=pattern) is a zero-width positive lookahead, which means that it must match that pattern at the position indicated in the overall regular expression. (?!pattern) is the zero-width negative lookahead. (?<=pattern) is a zero-width positive lookbehind assertion, and (? pattern) is a nonbacktracking subexpression or so called greedy subexpression. So far, I haven’t needed to make things specifically greedy, usually it’s the opposite, I’m forcing it to not be greedy. What that means is that it’ll match the largest part of the string that it can; For example, if you used the regex /*.\.txt/ and the string was some.txt.txt, a greedy expression would return “some.txt.txt”, while an ungreedy expression would return “some.txt”. It’s a minor detail that can really throw you off on occasion.
My secure and messages log files were getting really big, and after analyzing them to see if there was a reason, I decided to clear them out.
To do so, I first typed: cat > messages, then typed a couple of blank lines, and hit control-c to quit. I did the same for the secure log file. This cleared the file, but no new messages were being added to the logs. After kicking myself for being stupid, I searched around and found two important things.
First, it’s easier to clear a file by simply typing “> filename”, and second, the syslog daemon is reponsible for writing to those files. Restarting it restores its ability to write to the file. I restarted it by going to /etc/init.d and running ./syslogd restart
Over the past week, there have been 10 separate attempts to do a brute force attack on my server. Each day, I’d check my logs and manually ban the IP address responsible for the attempted crack. They’ve been attempting to break in through SSH and FTP.
While they didn’t succeed in breaking in, they did succeed in slowing down the server to the point that it was unresponsive for a few minutes during each attack.
Fortunately, IPTables has a cool feature that checks for recent connections. You tell it how many connection attempts from a particular IP address for a length of time, and if that amount succeeds, that IP address is banned for the specified amount of time.
It consists of 2 easy commands. The first one sets up the recent table:
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --set
In this case, it’s looking for connections on port 22 (SSH). Do the same for any other port that you want to limit like this such as your ftp ports.
The next command tells it to drop packets that exceed your specifications:
iptables -I INPUT -p tcp --dport 22 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 2 -j DROP
This tells iptables to drop the 3rd connection from a particular IP address if it happens within 60 seconds of the previous 2. You’ll probably want to set it a little harsher than that such as 3-5 minutes, or if you really want to be strict, set it for an hour or more. The downside is that the longer the timeframe, the greater chance that a legitimate person will get blocked because they mistyped their password a couple of times.
I’ve found that a range of 3-5 minutes is enough. My logs show a couple of attempts, 5 minutes later, a couple more, 5 minutes later a couple more. The rest are just dropped. My server doesn’t show down in the slightest with this kind of load, and I believe it’ll take the crackers a few hundred years to break a password at 2 attempts every 3-5 minutes.
At home, I run Windows XP x64, and I’ve had a tough time finding an antivirus program that will work on this operating system. I waited a year for McAfee or Symantec to come out with a version for this OS, but as of yet, neither of them had one that I could find on their unuser-friendly websites.
After searching around, I found Avast, which is free for non-commercial home use. I installed it and ran a full scan, and it found a couple of dormant virus files. It has a real-time scanner, which hasn’t noticably affected the speed of my system (something I can’t say for either McAffee or Symantec).
What are your thoughts of Avast and antivirus software in general? I haven’t been too thrilled with McAfee, as their update process has always been a bit unstable and problematic, and all of their products except for VirusScan has been a joke. Symantec has been pretty good to me, up until I got an OS that they don’t seem to support.
At any rate, until Windows can design a user-rights system that’s as good as Linux, we’re stuck with Antivirus software, and Avast is the only thing I’ve found to work on the 64 bit version of XP. It’s free, which is nice, but only time will tell if it actually prevents virus infections.
Lately, discussions seem to rage about whether to lay out your web pages using tables or divs. One side of the coin suggests all HTML related to laying out a page should use CSS, and thus the use of divs and spans to achieve this. It’s reported to be faster to render divs than tables because the browser can’t render a table until it reads the closing table tag. Using divs also typically makes the webpage’s file size smaller, which allows it to download faster, saves room on your hard drive, and it is rumored that search engines like div style pages better perhaps because of keyword density issues. If the overall html is less then the percentage of content on a page would be more, and some say that this is a benefit when dealing with search engine spiders.
On the practical side though, using divs and CSS to do your entire layout can be kludgy at best. Sure it’s fine for really simple layouts, but most layouts quickly move beyond this simplistic approach. Most of today’s browsers render CSS a little different, which sometimes results in the need for browser specific CSS kludges. Also, with a tableless layout, you often have to resort to odd hacks to make things work that people took for granted with tables such as the so-called faux columns and sliding door hacks. Complicate this with browser differences, and it can quickly end up looking like a nice bowl of spaghetti.
In fairness, CSS layouts can do things that tables cannot. Floating elements are really cool, but come with their own set of problems; For example, try to float 9 different elements with varying heights so that it ends up a 3×3 grid. Tables did this without a second thought. Without tables, you have to add an invisible span so that the next “row” actually drops all the way without getting hung up on a shorter element. Height parameters, in this case, just make a mess because they tend to leave way too much whitespace.
In theory, CSS should be used for all layouts. In practice, it’s sometimes way more of a pain than it should be.
Let me give you another example. I had a set of links sitting next to each other horizontally in a menu bar. I wanted a small form that consisted of a username and password box to sit on that same menu bar so that it all looked nice and level. For 3 hours, I played with tons of different ways to do with CSS, but ran into problem after problem. I tried floating left and right, but it wouldn’t line up with the menu links. I tried using various other html elements like putting both the links and the form into their own divs and using the divs padding, margin, positioning, etc to make them line up, but Firefox and Internet Explorer kept putting the two in different positions so making it look right in IE made Firefox screw up, etc. I could have put conditional CSS code for IE, but I’m stubborn and wanted to make it work without resorting to kludgy CSS. Eventually, I gave up and made a 2 cell table with 1 row and set the form to 0 pixel margin and padding and it worked fine in both browsers. The table solution took me all of 5 minutes. The CSS solution was not resolved after 2-3 hours.
I agree with the purists that all layouts should be rendered using CSS, but CSS isn’t practical for all layout situations yet. Tables, while seemingly archaic, are handled far closer to the same on Firefox and IE, which makes them more appealing in the cases where CSS falls short.
For the time being, I’m going to continue to learn new ways to deal with CSS shortcomings, but I’m not ready to abandon my old friend, the HTML table.
Outlook Express is installed for free by default with Windows and thus, it’s a common default choice among people new to the Internet and Email. Outlook Express does the basics of what an email client must do, but that’s the extent of its scope. You can have multiple email accounts, but all of your email drops into the same folder. To get around this, you can use rules to forward your email to other folders based on the “To” address. It does nothing for spam or phishing scams, and the extent of its security measures is the fact that it doesn’t auto-download embedded images.
Mozilla Thunderbird is another free email client, but it does a lot more than Outlook Express. It has a built-in spam filter, which learns over time what a person considers spam based on what they flag as spam. It is aware of spam assassin headers and can be configured to trust spam assassin’s headers. Between the two, it catches nearly all spam and gets better over time as it continues to analyze new spam email.
Thunderbird also has a phishing detection feature, where it will notify you if it thinks the email is a phishing scam. Phishing essentially is the attempt to mislead somebody into thinking they are going to a particular site, when in fact, they are going to a scammer’s site. Typically, phishing scams revolve around getting people to mistakenly put in their username and password, which is saved so that the scam artist can then log into their real account and gather personal information. This is a crucial feature for those new to the Internet as that warning can save a person from having their identity or credit card information stolen. Most people that have been on the Internet for a while can spot a scam. One such trick is to move your mouse over the link and look at where it’s really going in the status bar. If the address doesn’t match up to the real website, then it’s probably a scam. For example, if somebody wants you to log into “Paypal”, and the address is really going to www.paypal.com.someothersite.com, then it’s a scam.
Thunderbird can use multiple inboxes for each email address that you use, and it has a rules system that is at least as good as Outlook Express. It also allows you to set up RSS folders to take advantage of syndicated content on the Internet from your chosen sites.
As far as email is concerned, Mozilla has it covered.
The only drawback to using Thunderbird exclusively is that it doesn’t have a built in calendar & meeting system like you can get with Microsoft Outlook (the full version, not Express) and Exchange. There are calendar plugins, but to my knowledge, there isn’t a server available that will manage a shared calendar between many people like you can get with Exchange. If you know of such a system, please write a comment as I’d love to use it.
Bottom line, the best free email client available is Mozilla Thunderbird. If you need the ability to schedule meetings, then Microsoft Outlook with an Exchange server is probably the best option; however, Outlook and Exchange are not free. The prices vary depending on how many people you need and how you purchase Outlook such as by itself or inside Microsoft Office, but a small office will typically spend a few thousand dollars in licensing and setup fees.
Ruby on Rails has a bunch of built in tools to make it easy to create HTML form elements. In fact, there are so many different ones that it’s sometimes confusing to know which one to use.
Here is an example of how to build a static drop down box with the display text and the value:
Select helper:<%= select( "controller-name", "column", { "Tools" => "T", "Reference Resources" => "Resources"}) %>
Replace controller-name with the Rails controller that you’re going to use, “column” would be the database column where you plan to store the data, and the info between the {} is the options list. For example, { “Tools” => “T” } creates: <option value=”T”>Tools</option>
Of course, you can pass in a collection or array that was generated from a database query so that the option list is dynamic.
Invision Powerboard 1.2 and 1.3 are still used by many people because they’re free, where the newest versions are not. However, the coding for them isn’t 100% compatible with the latest versions of PHP and MySQL. Many web hosting companies are moving to PHP5 and MySQL5, and this will break the default installation of IPB. Here is a collection of the changes you’ll need to make to your files so that IPB 1.2 or 1.3 will work with PHP5 & MySQL 4.1 or greater.
If your forum is experiencing any of these issues, the rest of this article may fix your problem. Make sure you back up your files and database before making any changes, just in case.
Symptoms:
Blank ‘Profile’ page
Blank ‘My Controls’ page
MySQL errors when reporting post
MySQL errors on ‘The Moderating Team’ page
Files affected:
sources/misc/contact_member.php
sources/Profile.php
sources/Usercp.php
sources/misc/stats.php
Step 1:
Open sources/Usercp.php
Find:
var $parser;
Change To:
//var $parser;
Save and upload sources/Usercp.php
Step 2:
Open sources/Profile.php
Find:
var $parser;
Change To:
//var $parser;
Save and upload sources/Profile.php
Step 3:
Open sources/misc/contact_member.php
Find:
var $email = “”;
var $forum = “”;
var $email = “”;
Change To:
//var $email = “”;
var $forum = “”;
var $email = “”;
Find:
$DB->query(”SELECT m.name, m.email, mod.member_id FROM gallerymoderators mod, gallerymembers m WHERE mod.forum_id=’$fid’ and mod.member_id=m.id”);
Change To:
$DB->query(”SELECT m.name, m.email, moder.member_id FROM gallerymoderators moder, gallerymembers m WHERE moder.forum_id=’$fid’ and moder.member_id=m.id”);
Save and upload sources/misc/contact_member.php
Step 4:
Open sources/misc/stats.php
Find:
//——————————————–
// Do we have any moderators? NORMAL MODS 1st
//——————————————–
$DB->query(”SELECT m2.id, m2.name, m2.email, m2.hide_email, m2.location, m2.aim_name, m2.icq_number,
f.id as forum_id, f.read_perms, f.name as forum_name, c.state
FROM gallerymoderators mod
LEFT JOIN galleryforums f ON(f.id=mod.forum_id)
LEFT JOIN gallerycategories c ON(c.id=f.category AND c.state != 0)
LEFT JOIN gallerymembers m2 ON (mod.member_id=m2.id)
“);
Change To:
//——————————————–
// Do we have any moderators? NORMAL MODS 1st
//——————————————–
$DB->query(”SELECT m2.id, m2.name, m2.email, m2.hide_email, m2.location, m2.aim_name, m2.icq_number,
f.id as forum_id, f.read_perms, f.name as forum_name, c.state
FROM gallerymoderators moder
LEFT JOIN galleryforums f ON(f.id=moder.forum_id)
LEFT JOIN gallerycategories c ON(c.id=f.category AND c.state != 0)
LEFT JOIN gallerymembers m2 ON (moder.member_id=m2.id)
“);
Find: (this edit isn’t in 1.2, so you should be able to skip this step if that’s your version)
//——————————————–
// Do we have any moderators? GROUP MODS 1st
//——————————————–
$DB->query(”SELECT m.id, m.name, m.email, m.hide_email, m.location, m.aim_name, m.icq_number,
f.id as forum_id, f.read_perms, f.name as forum_name, c.state
FROM gallerymoderators mod
LEFT JOIN galleryforums f ON(f.id=mod.forum_id)
LEFT JOIN gallerycategories c ON(c.id=f.category AND c.state != 0)
LEFT JOIN gallerymembers m ON ((mod.is_group=1 and mod.group_id=m.mgroup))
“);
Change To:
//——————————————–
// Do we have any moderators? GROUP MODS 1st
//——————————————–
$DB->query(”SELECT m.id, m.name, m.email, m.hide_email, m.location, m.aim_name, m.icq_number,
f.id as forum_id, f.read_perms, f.name as forum_name, c.state
FROM gallerymoderators moder
LEFT JOIN galleryforums f ON(f.id=moder.forum_id)
LEFT JOIN gallerycategories c ON(c.id=f.category AND c.state != 0)
LEFT JOIN gallerymembers m ON ((moder.is_group=1 and moder.group_id=m.mgroup))
“);
Save and upload sources/misc/stats.php
Step 5:
Add the following code to the top of index.php and admin.php:
//– mod_php5 begin
$HTTP_SERVER_VARS = isset($_SERVER)?$_SERVER:array();
$HTTP_GET_VARS = isset($_GET)?$_GET:array();
$HTTP_POST_VARS = isset($_POST)?$_POST:array();
$HTTP_POST_FILES = isset($_FILES)?$_FILES:array();
$HTTP_COOKIE_VARS = isset($_COOKIE)?$_COOKIE:array();
$HTTP_ENV_VARS = isset($_ENV)?$_ENV:array();
$HTTP_SESSION_VARS = isset($_SESSION)?$_SESSION:array();
//– mod_php5 end
———
Portions of this article was paraphrased from a post by FuSoYa at http://forums.invisionize.com/index.php?showtopic=73882
If you’re getting started with Ruby on Rails, one of the better platforms to program in is Eclipse largely due to RadRails and the SVN plugin called Subclipse. Eclipse and the community versions of the plugins are free, so it’s definitely worth taking a look at.
This article is assuming that you have a working (but possibly outdated) version of Rails installed.
If not, and you’re running on Windows, I recommend searching for the InstantRails package and installing that first.
If you’re running Mac or Linux, you’ll need to install/upgrade Ruby to the latest version and then you can proceed with the following gem commands.
To Upgrade Rails:
gem update –system
gem update
gem update rails
gem cleanup
If you run into errors (possibly when you try and add your first rails project) try:
gem uninstall rails
gem install rails
gem cleanup
Eclipse:
Go to www.eclipse.org and find the latest version to download. The page is currently at:
http://download.eclipse.org/eclipse/downloads/drops/R-3.3.1.1-200710231652/index.php
Download the “Platform Runtime Binary (About 40mb)” for your Operating System.
Unzip this folder to whereever you want the install files of Eclipse to be.
Open the folder and find the Eclipse executable, and make a shortcut of it.
Move this shortcut into your start menu, desktop, or whatever you use to get to your programs.
Aptana Plugin:
Go to: www.aptana.com
Click on “get it now” for the community edition.
scroll to the bottom of the page and click “download” for the community edition.
click on the eclipse plugin tab
Click on download
In Eclipse: click on help, software updates, find and install.
Search for new features to install.
Click next
Click “new remote site”
Name it “Aptana”
Enter in the URL (which at the time of this writing is:
http://update.aptana.com/update/3.2/)
Follow the prompts, and select to download “Aptana” when it asks for it.
Subversion Plugin (called Subclipse):
http://subclipse.tigris.org/
Click on help, software updates, find and install.
Search for new features to install
Click next, then “new remote site”
Name it “Subclipse”
Enter in the URL found on the Subclipse website. Currently it is:
http://subclipse.tigris.org/update_1.2.x
Follow the prompts, but uncheck the integration box because you don’t have those plugins installed.
Click Install All and Restart Eclipse when it asks you.
Aptana Rad Rails:
Open Eclipse
On the Aptana Home Page (must have Aptana installed first), at the bottom of the Languages section, there’s a link to install Aptana RadRails.
Uncheck the Ruby Mylyn Connector Feature.
Follow the prompts, install all, reboot Eclipse when it asks you.
Show SVN Repository:
In Eclipse, click on Window, Show View, Other.
Open up, SVN folder, click on SVN Repository, Click OK.
Add Rails and Rake Paths to Eclipse:
Click window, preferences, click on plus sign next to Rails, click on Configuration. Browse to your rails files.
On my Windows computer, (using the Instant Rails package), the paths were at:
C:\InstantRails\InstantRails\ruby\bin\rails
C:\InstantRails\InstantRails\ruby\bin\rake
C:\InstantRails\InstantRails\ruby\bin\mongrel_rails
Of course, this totally depends on where you installed Ruby.
Click Apply to save them.
Other Eclipse Configuration Options:
Click window, preferences.
Click on Team, SVN
Check “Select unversioned resources on commit”
Click on Apply.
In the preferences window, click on “Team”, “Ignored Resources”, Add Pattern.
Add “.project” and “.log”. If your computer saves that annoying Thumbs.db file, you might want to ignore that one too.
Good luck, and I hope this was useful to you.
If you want to copy files to another computer, it’s more secure to use scp (secure copy) than ftp.
Using SCP:
scp -pr * username@example.net:destination_path
In the command, -p stands for “preserve”, in other words, it keeps the last modified time, access time, etc the same, and -r recursively copies subdirectories.
Using Rsync:
If you want to just copy files that have changed, a better solution is to use Rsync:
rsync -ra –progress –verbose –delete –rsh=/usr/bin/ssh –size-only * username@example.net:destination_path
-r in this command is for recursive copies, and -a stands for archive, which keeps the modified times the same. –progress and –verbose outputs everything it’s doing and lets you know how much more it needs to check, –delete deletes anything that doesn’t exist at the source location any longer, –rsh makes sure you’re using ssh for security reasons, –size-only updates anything where the filesize has changed. Normally, it compares hashes of the files but that takes more time to process. The * is the source location, which would normally be a path somewhere if it’s in a cronjob, and the last part is the destination location, which doesn’t need a trailing slash; for example, public_html/images
To automate Rsync, you’ll need to have ssh keys installed so that you can bypass the need to enter in a password.
Installing an ssh key:
Run this command on the source computer:
ssh-keygen -t dsa
This will create a pair of keys at $home_dir/.ssh/ and by default, the public key will be called id_dsa.pub
Security Note: When you create your key, it will ask for a password. If you leave it blank, you’ll be able to ssh to the destination box without needing a password, which is useful when you need ssh in an automated script; however, this makes it less secure in the case where somebody compromises your user account - they would then have access to all of the machines with your public key installed. However, if you use a password, you’ll need to enter that password each time you want to ssh, which will be problematic in automated scripts.
Copy the contents of the public key to the destination computer at:
$home_dir/.ssh/authorized_keys
Troubleshooting:
Occasionally, I’ve gotten this error, which prevented me from copying files inside a particular directory, and it confused me at first because my user had read permissions, but it wouldn’t copy until I gave the directory execute permissions too:
rsync: recv_generator: failed to stat “/path/to/file”: Permission denied (13)
The way I got around this was to run: ‘chmod 777 thefile’, but ‘chmod 700 thefile’ should work too assuming that you don’t want anybody seeing the file but you. A 7 in that command sets it to rwx or read, write, and execute.
SCP is great for copying the contents of a folder, while Rsync is great to mirror or back up files, and with a combination of the two, you’ll rarely need to use FTP again.
This is more of a set of modifications rather than an actual module, but the end result is the same.
First thing you’ll need to do is backup your existing site and database. I’d recommend using a test install of Xcart so that nothing in production gets messed up. With that in mind, the first step is to alter the pricing table by using the following alter table command. If you have a different version of MySQL, you might need to tweak this a bit.
ALTER TABLE `xcart_pricing` ADD COLUMN `numpymnts` INTEGER UNSIGNED NOT NULL DEFAULT 1,
ADD COLUMN `paymentprice` DECIMAL(12,2) NOT NULL DEFAULT 0 AFTER `numpymnts`,
ADD COLUMN `sourceproductcode` VARCHAR(255) DEFAULT 0 AFTER `paymentprice`,
ADD COLUMN `sortby` INTEGER UNSIGNED NOT NULL DEFAULT 0 AFTER `sourceproductcode`,
ADD COLUMN `mastervariant` SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `sortby`,
ADD COLUMN `price_override` SMALLINT(5) UNSIGNED NOT NULL DEFAULT 0 AFTER `mastervariant`,
ADD INDEX `numpymnts`(`numpymnts`),
ADD INDEX `paymentprice`(`paymentprice`),
ADD INDEX `sortby`(`sortby`),
ADD INDEX `sourceproductcode`(`sourceproductcode`),
ADD INDEX `mastervariant`(`mastervariant`),
ADD INDEX `price_override`(`price_override`)
, ENGINE = MyISAM;
The new columns are as follows:
numpyments = number of payments
paymentprice = price the export expects to see (might be one payment or the total)
sourceproductcode = product code (sku) that export expects to see
sortby = the order in which the variants show up on the admin page
mastervariant = overrides the ’starting at’ price
price_override = use this table for the price instead of the orders table for reporting
Next, you’ll need to modify some of the admin template files, such as:
Modify Files:
/skin1/modules/Product_Options/product_variants.tpl - add fields to the variants html table - don’t add the price_override column.
/modules/Product_Options/func.php - edit func_get_product_variants and add in the columns that were added to the product_variants.tpl file
When you submit the variants, the form goes to:
product_modify.php
section=variants
mode = product_variants_modify
productid = [variable]
submode = “data”
geid = “”
Once sumbitted, the code is run in this ELSEIF block in modules/Product_Options/product_variants.php:
} elseif ($mode == ‘product_variants_modify’ && $vs && $submode != ‘prices’) {
In here, you need to edit the $query_price_data array to include the additional fields; for example:
## BB Edit - added additional fields
$query_price_data = array(
"price" => $v['price'],
"variantid" => $k,
"productid" => $productid,
"quantity" => 1,
"membershipid" => 0,
"numpymnts" => $v['numpymnts'],
"paymentprice" => $v['paymentprice'],
"sortby" => $v['sortby'],
"sourceproductcode" => $v['sourceproductcode'],
"mastervariant" => $v['mastervariant']
);
Next, you need to edit the modify options page, otherwise, if you change options, it’ll remove your new field data.
When submitting this form, it passes these variables to product_modify.php:
section=options
mode=product_options_add
classid= your classid
productid = your productid
geid=”"
If you change add[is_modifier] (price modifier = ‘y’, else it’s blank), it rebuilds the variants by calling func_rebuild_variants in modules/Product_Options/func.php
//Rebuild variants: . . . . product_modify.php?productid=18§ion=options&classid=71
In func_rebuild_variants, change the $_product[’prices’] $data variable to:
$data = array(
"productid" => $productid,
"quantity" => $p['quantity'],
"membershipid" => $p['membershipid'],
"variantid" => $variantid,
"price" => $p['price'],
"numpymnts" => $p['numpymnts'],
"paymentprice" => $p['paymentprice'],
"sortby" => $p['sortby'],
"sourceproductcode" => $p['sourceproductcode'],
"mastervariant" => $p['mastervariant']
);
This will keep your data from being lost in the new columns. And that’s it, as far as back end functionality for the multi pay option. Depending on how your templates are set up, you’ll probably want to use the new columns to force the “mastervariant” column to show up in the “starting at” price. Do this by ordering that query by mastervariant in descending order. The rest of the columns really come in handy when you need to see the full price such as in reports, modifying omniture code, and to produce export files where the fulfillment company wants to see the full amount instead of the per payment price.
I recently redesigned my photography website, The Lens Flare. I had Internet Explorer 7 and Firefox 2 installed, and thus wrote the site to make it work with those browsers. Once I had it working on those 2 browsers, I tried it on IE6 and the template was horribly screwed up. Here, I’ll explain what I had to change to make it look good in the 2 current browsers and IE6.
Apparently, IE6 has a bug people have dubbed the double padding bug or double margin bug. The problem can usually be fixed by using the CSS option: “display:inline” on your DIVs that have the double spacing problem. This fixed most of the spacing issues, but it didn’t fix them all.
To fix the last spacing problem, I had to resort to an Internet Explorer Kludge called conditional comments to include a separate CSS file when IE6 is loaded.
To do this, you put the following code after your other CSS files in your HEAD tag:
<!--[if IE 6]><link rel=”style sheet” href=”ie6.css” type=”text/css” media=”all” /><![endif]-->
This loads the ie6.css file when somebody is using IE6.
The main CSS file has the following directions for the col2 div:
.col2 {
width:338px;
position:relative; float:left;
margin:0px 0px 0px 5px; padding:0px;
display:inline;
}
The ie6.css file overrides col2 with the following directives:
.col2 {
width:338px;
margin:0px; padding:0px;
display:inline;
}
In IE6, floating the div to the left and adding a margin on the left side messed things up. From what I can tell, it started the location of the div in a slightly different place than IE7 and Firefox does and therefore has to be positioned differently to appear in the same place on the screen.
Also, another trick I learned while dealing with IE6’s limitations was a handly CSS tidbit called: “overflow:hidden”.
There are several places in my layout where I have a 2 pixel tall div with a background color to act as a horizontal rule. For example, this gray line:
.gray-line {
position:relative;
width:99%;
height:2px;
background-color:#ddd;
margin:0px; padding:0px;
overflow:hidden;
}
However, without the overflow:hidden aspect, IE6 renders a line about 5-8 pixels tall.
Lastly, “background-repeat: no-repeat” solved one last IE6 problem. Since it seems to use different heights for things, in places where I’m using a background image, the image would start to repeat itself again for about 2-3 pixels. Setting this directive on those areas solved that problem. Combine that with overflow:hidden and we’re good to go.
Xcart is a fairly popular e-commerce shopping cart program, and one of the add-on modules that you can buy from a third party company is called CDSEO. This rewrites all of the links to be SEF using a folder-style syntax instead of the regular ?variable=value syntax.
However, it causes some problems with X-Cart. One such problem is the Review Product form on the product detail page (product.php).
To fix this bug, you need to add hidden fields to the form instead of having them inside the form’s “action”.
In other words, change:
<form method=”post” action=”/product.php?mode=review&productid={$product.productid}” id=”reviewform”>
To:
<form method=”post” action=”/product.php?productid={$product.productid}” id=”reviewform” method=”post”>
<input type=”hidden” name=”productid” value=’{$product.productid}’ />
<input type=”hidden” name=”mode” value=”review” />
Next, you’ll need to edit vote.php at the document root of your Xcart install and add a slash at the beginning of the link.
So change:
func_header_location(”product.php?productid=$productid”);
to:
func_header_location(”/product.php?productid=$productid”);
This is because the CDSEO module creates a pseudo-directory and thus your browser thinks that it’s in that folder and tries to redirect you to the wrong path.