<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7386613993853768674</id><updated>2012-02-13T18:17:16.901Z</updated><category term='bit'/><category term='odor'/><category term='speed'/><category term='senzor'/><category term='wizard'/><category term='javascript'/><category term='authentication'/><category term='voodoo'/><category term='ajax'/><category term='rsa'/><category term='programming'/><category term='guru'/><category term='className'/><category term='parfume'/><category term='cents'/><category term='loading'/><category term='LDAP'/><category term='form'/><category term='toolbox'/><category term='firefox'/><category term='PHP'/><category term='click'/><category term='httpd.conf'/><category term='encryption'/><category term='gmp'/><category term='second life'/><category term='PostgreSQL'/><category term='css'/><category term='php.ini'/><category term='js'/><category term='Active Directory'/><category term='optimization'/><category term='class'/><category term='dependency'/><category term='virtual'/><category term='SSL'/><category term='nose'/><category term='Apache'/><category term='ubuntu'/><category term='caching'/><category term='smell'/><category term='coins'/><category term='opera'/><title type='text'>Web Development</title><subtitle type='html'>What a web developer would find interesting</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-552174836133992558</id><published>2008-03-02T14:27:00.003Z</published><updated>2008-03-02T14:32:12.101Z</updated><title type='text'>Save Windows XP</title><content type='html'>M$ plans to end most sales of Windows XP on June 30 2008. &lt;br /&gt;Let's sign &lt;a href="http://weblog.infoworld.com/save-xp/"&gt;InfoWorld's petition&lt;/a&gt; to ensure Windows XP continues to be available after the deadline because it's very inappropriate for M$ to be forcing the customer to make high impact changes to their business for zero gain.&lt;br /&gt;&lt;br /&gt;Come on, &lt;a href="http://weblog.infoworld.com/save-xp/"&gt;sign it&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-552174836133992558?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/552174836133992558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=552174836133992558' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/552174836133992558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/552174836133992558'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2008/03/save-windows-xp.html' title='Save Windows XP'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-1777489068397091770</id><published>2008-02-19T15:05:00.003Z</published><updated>2008-02-19T15:08:22.411Z</updated><title type='text'>Micro$oft's evil plans</title><content type='html'>Here's a very good story to read: &lt;a href="http://www.groklaw.net/article.php?story=20071023002351958"&gt;Evangelism Is War&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here's a snippet of it: &lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Our mission is to establish Microsoft's platforms as the de facto standards throughout the computer industry. Our enemies are the vendors of platforms that compete with ours: Netscape, Sun, IBM, Oracle, Lotus, etc. The field of battle is the software industry. Success is measured in shipping applications. Every line of code that is written to our standards is a small victory; every line of code that is written to any other standard, is a small defeat. Total victory, for DRG, is the universal adoption of our standards by developers, as this is an important step towards total victory for Microsoft itself: "A computer on every desk and in every home, running Microsoft software." &lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-1777489068397091770?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/1777489068397091770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=1777489068397091770' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/1777489068397091770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/1777489068397091770'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2008/02/microofts-evil-plans.html' title='Micro$oft&apos;s evil plans'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-325608873915360359</id><published>2007-12-17T18:19:00.000Z</published><updated>2007-12-17T16:43:45.874Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='form'/><category scheme='http://www.blogger.com/atom/ns#' term='click'/><category scheme='http://www.blogger.com/atom/ns#' term='opera'/><title type='text'>Form submit weirdness in Opera 9.20</title><content type='html'>Here's one for you: &lt;br /&gt;&lt;br /&gt;I have a few input form elements on a page, one of them is of type 'submit'. Because I don't use a form to submit this information, I set an event listener for one of the inputs like so: &lt;code&gt;onkeypress="if(event.keyCode==13)myAction()"&lt;/code&gt; so that if enter is pressed, an action is performed. Similarly for the 'submit' input &lt;code&gt;onclick="myAction()"&lt;/code&gt;, so if the button is clicked the same action will be performed. &lt;br /&gt;&lt;br /&gt;Here's what happens: if the enter key is pressed in the text control, &lt;code&gt;myAction&lt;/code&gt; is executed twice. It's executed only once if I click on the button...&lt;br /&gt;&lt;br /&gt;I investigated the problem and here are a few observations:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;If the type of the submit element is changed to 'button' the action is performed only once when enter is pressed, as expected&lt;/li&gt;&lt;br /&gt;&lt;li&gt;If I remove the event listener from the text input element and leave the type of the 'submit' element unchanged, &lt;code&gt;myAction&lt;/code&gt; is executed only once, as expected&lt;/li&gt;&lt;br /&gt;&lt;li&gt;What happens in myAction does not affect the form elements in any way, &lt;code&gt;myAction&lt;/code&gt; can be replaced with &lt;code&gt;alert&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;This behaviour doesn't happen in Firefox&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In Firefox, only if the elements are in a form (and they are not in my case) then the form is submitted when enter is pressed in one of the text input elements&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;My conclusion: Opera detects a 'submit' element and launches a click event on it when enter is pressed in one of the text input elements, assuming that they're all part of a form. I think this is not something a web developer would expect, would you? &lt;br /&gt;&lt;br /&gt;I need the event listeners for Firefox, so I'm going to change the submit element to 'button' which is more appropriate anyway.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-325608873915360359?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/325608873915360359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=325608873915360359' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/325608873915360359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/325608873915360359'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/12/form-submit-weirdness-in-opera-920.html' title='Form submit weirdness in Opera 9.20'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-6942732771224951993</id><published>2007-12-16T17:27:00.000Z</published><updated>2007-12-16T19:03:19.825Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='SSL'/><category scheme='http://www.blogger.com/atom/ns#' term='rsa'/><category scheme='http://www.blogger.com/atom/ns#' term='gmp'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='encryption'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>RSA encryption</title><content type='html'>I recently started to develop a new web application. I want this one to run many windows, only one web page loaded fully at the beginning: index.php. Once this is loaded all the communication will take place AJAX style through the httpRequest object.&lt;br /&gt;&lt;br /&gt;One of the challenges was authentication. SSL is out of the question, because I don't want any page refreshing or browser redirection and I also want to enable the user to keep the state of their windows in case the session expires. The logging in must happen through a window that asks for the user name and the password, sends the information to the server and if the credentials match, log the user in, keeping all the previously opened windows with all the data in them. Of course if a different user logs in, only public information will be kept in the browser, not information marked as private by the previous user.&lt;br /&gt;&lt;br /&gt;I don't want the password to travel on the internet in plain text, I want to encrypt just the password. I don't want to slow down the interaction by using some very slow encryption algorithm that takes a lot of time to complete.&lt;br /&gt;&lt;br /&gt;Before I made my decision, I had searched for some ways to encrypt information with JavaScript and I had found a lot of websites (&lt;a href="http://www.psi.toronto.edu/~vincent/blog/jscrypt.html"&gt;here&lt;/a&gt;'s an example) that provide encryption algorithms that require keys. I don't understand what's the purpose of these algorithms, if they require a key which needs to be sent to the client on the internet, then an attacker can intercept the key as well and decrypt the information with no problem. Perhaps they are designed just for use by one person offline to encrypt some data and store it somewhere along with the key?!?&lt;br /&gt;&lt;br /&gt;One secure way to authenticate people to my web application could have been, MD5 encryption on the client side and sent to the server to compare to the stored MD5 of the password. There are several problems with this method:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;the md5 can be intercepted and sent in the future by the attacker to log in as the victim.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;if you have an md5 hash and you want to know the text it represents, find a &lt;a href="http://md5.rednoize.com/"&gt;site that stores md5 hashes&lt;/a&gt; and search for it, if the password is pretty weak, it's a good chance you'll decrypt it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;we use LDAP to log in people and ldap requires plain text password to be sent to it, so storing just the md5 is out of the question.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;RSA is by far the most popular cryptosystem and it's very secure. Because even though it requires some key exchange, there's a private key involved that doesn't travel between the server and the client. The most comprehensive and complete web site I found on this subject is &lt;a href="http://www.codeproject.com/KB/scripting/JscriptRSA.aspx"&gt;this&lt;/a&gt;. I'm not going to talk too much about RSA, about how it works and why it's secure. &lt;a href="http://www.codeproject.com/KB/scripting/JscriptRSA.aspx"&gt;Gaurav Saini's article&lt;/a&gt; explains everything.&lt;br /&gt;&lt;br /&gt;The code Gaurav provided in his article encrypts and decrypts a number. What you need more is a way to generate the keys and a way to transform texts to numbers. As I said, I wanted something good enough without sacrificing speed (I'm not developing web applications for banks and the data used in this future web application is not very sensible). So instead of working with huge prime numbers as SSL does and generating them on demand, I chose to take a big list of prime numbers from &lt;a href="http://prime-numbers.org"&gt;this website&lt;/a&gt;, making sure that their product won't exceed JavaScript's integer upper limit. That saves a lot of processing time and to be sure they're not easy to guess, they are chosen randomly and assigned to either p or q with each request to the log in form.&lt;br /&gt;&lt;br /&gt;I had to create a php version for the decrypt function as well, because their product and the 'phi' value is sent to the client from the server, the client encrypts the password and the server decrypts it upon receiving the information from the client. The password is then sent to the LDAP server along with the user name.&lt;br /&gt;&lt;br /&gt;Transforming the text into numbers is the easy part. There are many ways, but I chose to use &lt;code&gt;text.charCodeAt(i)&lt;/code&gt; to get the unicode code of each character, encrypt it using the key provided earlier by the server, put the codes together with a char delimiter, decrypt each code on the server and transform it to character using &lt;code&gt;html_entity_decode('&amp;amp;#'.$code.';',ENT_NOQUOTES,'UTF-8');&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;I had a tiny problem with php because php's upper limit on integers is a lot smaller than JavaScrpt's. I wanted to use the &lt;a href="http://uk.php.net/gmp"&gt;GMP library&lt;/a&gt; to work with large numbers, but unfortunately php5-gmp can not be installed on Ubuntu JeOS :-( so I found another one that comes bundled with PHP5, &lt;a href="http://uk.php.net/manual/en/ref.bc.php"&gt;MCMath&lt;/a&gt; which worked like a charm.&lt;br /&gt;&lt;br /&gt;A more complete RSA implementation that works with large numbers can be found at &lt;a href="http://ohdave.com/rsa/"&gt;this address&lt;/a&gt;, but it's not very well explained. This version is interesting, instead of encrypting each character, it uses a key of a fixed length, takes chunks of the text transformed to the digit code, adds the bit shifted value of the corresponding position of the key to make a large string of digits which is treated as a number and encrypted. However this algorithm relies on a Delphi library to generate the key, which needs to be changed depending on what you use on the server side.&lt;br /&gt;&lt;br /&gt;Please tell me about your unique and innovative way of sending passwords from client to server.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-6942732771224951993?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/6942732771224951993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=6942732771224951993' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/6942732771224951993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/6942732771224951993'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/12/rsa-encryption.html' title='RSA encryption'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-8139544885934504977</id><published>2007-08-17T15:10:00.000+01:00</published><updated>2007-08-17T15:43:51.631+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='speed'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><category scheme='http://www.blogger.com/atom/ns#' term='className'/><category scheme='http://www.blogger.com/atom/ns#' term='opera'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Firefox 2.0.0.6 vs Opera 9.20</title><content type='html'>This post is not just to let you know what browsers I'm using at the moment.&lt;br /&gt;It's rather about this speed problem a colleague of mine and I are having for a web application.&lt;br /&gt;&lt;br /&gt;Just to make it simple, there are two divs, each contain a huge table, each with around 100 rows of 20 columns each, in each cell there is either some text, a checkbox or a select tag with around 5 options. Just to sum things up, there are like 800 checkboxes and 800 selects. They are loaded by pulling data from the server through a HttpRequest object.&lt;br /&gt;&lt;br /&gt;We were expecting loading to take a long time and it really does :-)&lt;br /&gt;What is really surprising is what happens when they're both loaded and their classNames are changed, one gets a class name that has among others "display: none" to hide it and the other gets "currentDiv" class name which sets a few properties.&lt;br /&gt;&lt;br /&gt;I'm really surprised about how ling time it takes Firefox 2 to do this operation. I checked with FireBug exactly what part of the code takes the most to run and this is it:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;myDiv.className = "currentDiv";&lt;br /&gt;&lt;br /&gt;This is where it spends around 10 seconds.&lt;br /&gt;&lt;br /&gt;I thought instead of changing the class name, to try and change the style.display property, but there was no visible difference. &lt;a href="http://www.quirksmode.org/dom/classchange.html"&gt;Here's a nice test on this subject&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;Just for tha hell of it, I also took down any other CSS properties from the "currentDiv" class and especially these kind of lines: &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;div.currentDiv table td.commentTd{ ... }&lt;br /&gt;&lt;br /&gt;I thought maybe the rendering engine has to go through all cells of the table in this specific div and change the visual attributes. Well, again, no improvement.&lt;br /&gt;&lt;br /&gt;I was curious what had Opera to say about this matter and I tested the same code on Opera 9.20. Result: under 2 seconds including loading the div. Absolutely surprising.&lt;br /&gt;&lt;br /&gt;I'm not giving up on Firefox, yet, I still love it :-) But I'm looking forward to Firefox 3 with its new and improved JavaScript engine ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-8139544885934504977?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/8139544885934504977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=8139544885934504977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8139544885934504977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8139544885934504977'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/08/firefox-2006-vs-oper-920.html' title='Firefox 2.0.0.6 vs Opera 9.20'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-3727897719816469816</id><published>2007-08-15T11:21:00.000+01:00</published><updated>2007-08-15T14:15:34.322+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='js'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='caching'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Prevent browser caching of web pages</title><content type='html'>I'm having problems with cached web pages in some of my web applications.&lt;br /&gt;There is this particular application that is in continuous development, while employees are using it and whenever I make some modifications the old version conflicts with the new one throwing errors or displaying some mixed information: some from the old html code and some new information the web page retrieves by AJAX.&lt;br /&gt;&lt;br /&gt;I got a fix for the html code, now it isn't cached any more. I use this code in PHP:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;header("Cache-Control: no-cache, must-revalidate");&lt;br /&gt;&amp;nbsp;&amp;nbsp;header("Expires: Tue, 29 Mar 1983 07:20:55 GMT");&lt;br /&gt;&lt;br /&gt;This really works, everything I modified in the PHP code is updated every time someone browses the web page, but not the JS and CSS files that are linked from the html code :-(&lt;br /&gt;&lt;br /&gt;I found some more tips for preventing caching &lt;a href="http://www.webdevelopersnotes.com/tips/webdesign/prevent_caching_of_web_pages_by_browsers.php3"&gt;here&lt;/a&gt;. They consist in adding some meta tags in the head section of the web page:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;meta http-equiv="expires" value="Tue, 29 Mar 1983 07:20:55 GMT"/&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;meta http-equiv="pragma" content="no-cache"/&amp;gt;&lt;br /&gt;&lt;br /&gt;The value of the first one is a date in the past, obviously. I'll let you guess the miracle that happened on that particular date I chose to put in there :-)&lt;br /&gt;&lt;br /&gt;I tried this as well and it doesn't work for js and css files, unfortunately :-(&lt;br /&gt;&lt;br /&gt;This wouldn't have been a problem if my js code was inline, but I never insert inline JavaScript code if there are more than 20 lines. I always like to split the code in many files each representing a module that can be taken and put on another website and works without changing anything except maybe a few variables.&lt;br /&gt;&lt;br /&gt;Another idea was to send a header for each js or css file, but that would mean changing the js and css files to .php and send the headers I wrote at the begining of this post. I really don't want to do that, I want to keep them as js and css, because it's makes the application neat and organised. Many editors highlight code according to the file extension, I don't want to switch to choosing manually the highlighting style.&lt;br /&gt;&lt;br /&gt;Some other ideas I got from &lt;a href="http://raibledesigns.com/rd/entry/prevent_caching_of_javascript_and"&gt;Matt Raible&lt;/a&gt; and &lt;a href="http://codingforums.com/archive/index.php?t-31770.html"&gt;this forum&lt;/a&gt;. The idea is simple, very simple, just add a random number as a variable sent by GET method. This will foul the browser to think that it's always a new file without affecting the file itself.&lt;br /&gt;&lt;br /&gt;Some other idea is to use subfolders for each version and just change the version folder in the path provided in the html code. This won't be a big problem because I use &lt;a href="http://webdevlucian.blogspot.com/2007/07/loading-dependencies-in-javascript.html"&gt;this piece of code&lt;/a&gt; to load dependencies, if versions change, I'll need to change only the main file that loads the dependencies, but others might find this annoying.&lt;br /&gt;&lt;br /&gt;These last methods work fine, problem solved. But thinking about optimisation, the js and css files will never be cached so I lose one of the most important advantages I got by using external files, exactly what I want to get rid of: caching. Caching is meant to store information that is used often instead of loading it again and again. &lt;br /&gt;&lt;br /&gt;As I don't update these files so often I decided to use a combination of all these methods. I use the headers to make sure the html code is always updated (usually there isn't too much html code in my html files, so not too much overhead ;-) ). I added a variable called version to the end of the file and I update it when I want the code in js and css files updated as well.&lt;br /&gt;&lt;br /&gt;Here are the sample lines:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;link rel='stylesheet' type='text/css' href='stylesheet.css?version=3' /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;lt;script type="text/javascript" src="js/toolbox.js?version=3"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;Don't forget to update the version number to the files you load dynamically from other js files!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-3727897719816469816?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/3727897719816469816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=3727897719816469816' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/3727897719816469816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/3727897719816469816'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/08/prevent-browser-caching-of-web-pages.html' title='Prevent browser caching of web pages'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-8371993541957703930</id><published>2007-07-26T19:45:00.001+01:00</published><updated>2007-07-26T19:47:01.546+01:00</updated><title type='text'>I'm addicted to blogging</title><content type='html'>&lt;a href="http://mingle2.com/blog-addiction" style="color: #D64B32; text-decoration: none; display: block; width: 286px; height: 128px; padding-top: 50px; padding-left: 17px; background: url(http://mingle2.com/img/bb/blog_addiction/badge.jpg) no-repeat; font-family: Times New Roman, sans-serif; font-size: 30px;"&gt;67%&lt;span style="display: none;"&gt;How Addicted to Blogging Are You?&lt;/span&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-8371993541957703930?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/8371993541957703930/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=8371993541957703930' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8371993541957703930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8371993541957703930'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/im-addicted-to-blogging.html' title='I&apos;m addicted to blogging'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-3767416211443705754</id><published>2007-07-26T11:23:00.000+01:00</published><updated>2007-07-26T19:17:05.182+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='httpd.conf'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='PostgreSQL'/><category scheme='http://www.blogger.com/atom/ns#' term='php.ini'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><title type='text'>Installing PHP under Windows</title><content type='html'>Installing PHP is supposed to be easy under Windows using the installer.&lt;br /&gt;&lt;br /&gt;First you need to install Apache, or other web server.&lt;br /&gt;Then launch the php windows installer and follow the instructions.&lt;br /&gt;&lt;br /&gt;What I installed was Apache 2.2.4 and I tried to install PHP 5.2.2.&lt;br /&gt;Everything was fine until I wanted to use some extension functions, like pg_connect, which is the function to connect to a PostgreSQL server. It didn't work and I was very surprised, because when I installed PHP I specified that I wanted to install the PostgreSQL extension.&lt;br /&gt;&lt;br /&gt;I checked the php.ini file and the extension was indeed activated. I checked if the dll exists, it was there. So what was the problem? I figured out that php.ini was not being parsed, so I had to check the httpd.conf file for Apache where you need to specify the path for the php file.&lt;br /&gt;&lt;br /&gt;I noticed that the PHP installer was writing the httpd.conf file wrongly, giving the path in forward slash notation, but everywhere else in the file all the paths were given in back slash notation, so I changed the path notation for php specifying the correct path both to the php.ini file and to the php5 module that Apache needs to load.&lt;br /&gt;&lt;br /&gt;I restarted Apache and I got even more confused, the server couldn't recognise the php files as scripts and it displayed the code as text. That happens usually when the php module fails to load, so I changed the path only for the php5 module back to the way it was, no improvement. Then I changed the PHPIniDir attribute to the way it was before and it worked again, but I was back to no php.ini parsing. I changed only the PHPIniDir attribute to the backslash notation and I got the same result as earlier: code displayed as text.&lt;br /&gt;&lt;br /&gt;I thought maybe the php.ini has a problem, but going through all of didn't reveal any mistake. I decided to rename it for a while to see what happens. Well, surprise, surprise, PHP worked, but no extensions...&lt;br /&gt;&lt;br /&gt;My conclusion: writing the paths in backslash notations is the right thing to do, but if the server parses the php.ini file, it fails to load the php module.&lt;br /&gt;&lt;br /&gt;php.ini looks good, everything is fine, the doc_root (that the installer failed to write) is there written correctly. I also followed the instructions to install php manually and I did everything accordingly, no improvement.&lt;br /&gt;&lt;br /&gt;Is PHP meant to be used on Windows with Apache?&lt;br /&gt;&lt;br /&gt;UPDATE: I solved my problem by installing &lt;a href="http://www.apachefriends.org/en/xampp.html"&gt;XAMPP&lt;/a&gt;. Thank you very much &lt;a href="http://www.archaeogeek.com/blog/about/"&gt;Jo Cook&lt;/a&gt; for the tip.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-3767416211443705754?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/3767416211443705754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=3767416211443705754' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/3767416211443705754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/3767416211443705754'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/installing-php-under-windows.html' title='Installing PHP under Windows'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-8174431125740502005</id><published>2007-07-16T15:58:00.000+01:00</published><updated>2007-07-19T12:17:43.557+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='js'/><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='dependency'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><category scheme='http://www.blogger.com/atom/ns#' term='loading'/><category scheme='http://www.blogger.com/atom/ns#' term='toolbox'/><category scheme='http://www.blogger.com/atom/ns#' term='optimization'/><title type='text'>Loading dependencies in JavaScript</title><content type='html'>Isn't it nice to work modularized, even in JavaScript?&lt;br /&gt;I like putting all my classes in their own files and all the little functions that don't belog to any class in a file called toolbox.js &lt;br /&gt;&lt;br /&gt;That's pretty neat and organized, but when it comes to inserting all the necessary js files into your webpage, it's a pain, isn't it?&lt;br /&gt;&lt;br /&gt;Well, not for me. I add the toolbox.js to every webpage that uses JavaScript and then the most important js file for that particular page. &lt;br /&gt;&lt;br /&gt;Here's an example; I have a webpage that needs to use the EntryModule class. But this class needs a few more classes that are stored in other files, the TableEntryClass, the TextEntryClass and ColourObjectClass. All I need to do is to call this function: &lt;br /&gt;&lt;br /&gt;loadDependencies(Array('js/ColourObjectClass.js', 'js/TableEntryClass.js', 'js/TextEntryClass.js')); &lt;br /&gt;&lt;br /&gt;This function takes either a string or an array of strings that specify the js files to add to the same webpage that loaded EntryModuleClass.js &lt;br /&gt;&lt;br /&gt;Here's the code, use it wise:&lt;br /&gt;&lt;br /&gt;function loadDependencies(dependency)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;var head = document.getElementsByTagName('head')[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp; var scripts = head.getElementsByTagName('script');&lt;br /&gt;&amp;nbsp;&amp;nbsp;var i, j, newjs;&lt;br /&gt;&amp;nbsp;&amp;nbsp;if(typeof dependency == 'string')&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//search if it's loaded already&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(i=0; i &lt; scripts.length; ++i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(scripts[i].src.toLowerCase() == dependency.toLowerCase())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//if not, load it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newjs = document.createElement('script');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newjs.type = 'text/javascript';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newjs.src = dependency;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;head.appendChild(newjs);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;if(typeof dependency == 'object')//it must be an array&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //search if it's loaded already&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(i=0; i &lt; dependency.length; ++i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(j=0; j &lt; scripts.length; ++j)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(scripts[j].src.toLowerCase() == dependency[i].toLowerCase())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //if not, load it&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newjs = document.createElement('script');&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newjs.type = 'text/javascript';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newjs.src = dependency[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; head.appendChild(newjs);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;I hope you notice the care I took with declaring the variables at the begining of the function and also getting the head tag and the script tags at the begining to optimize the number of searches...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-8174431125740502005?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/8174431125740502005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=8174431125740502005' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8174431125740502005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/8174431125740502005'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/loading-dependencies-in-javascript.html' title='Loading dependencies in JavaScript'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-5271363063796480915</id><published>2007-07-14T16:33:00.000+01:00</published><updated>2007-07-14T17:38:00.756+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='parfume'/><category scheme='http://www.blogger.com/atom/ns#' term='virtual'/><category scheme='http://www.blogger.com/atom/ns#' term='smell'/><category scheme='http://www.blogger.com/atom/ns#' term='second life'/><category scheme='http://www.blogger.com/atom/ns#' term='odor'/><category scheme='http://www.blogger.com/atom/ns#' term='senzor'/><category scheme='http://www.blogger.com/atom/ns#' term='nose'/><title type='text'>Virtual Perfume</title><content type='html'>While chatting with a friend, I got this term that made my imagination run wild.&lt;br /&gt;&lt;br /&gt;I searched for "virtual perfume" and got a few interesting links like &lt;a href="http://www.vnunet.com/vnunet/news/2185993/ck-launches-second-life-virtual"&gt;this one&lt;/a&gt; about Calvin Klein launching a virtual perfume on &lt;a href="http://secondlife.com/"&gt;Second Life&lt;/a&gt;. While what CK did is just a smart marketing action to promote their brand and their new perfume, Second Life is quite a nice application, but I'd rather not start using it. It might turn out addictive and then I might find myself into the Matrix, disconnecting only to go to the toilet :-D&lt;br /&gt;&lt;br /&gt;My imagination went further then just marketing material to distribute on the web, I actually thought of the media of the future. The techniques of recording and reproduction of visual and auditory information are nowadays well established, maybe it's time to move forward and put some more time into researching how to record and reproduce information to serve the other human senses.&lt;br /&gt;&lt;br /&gt;What about having this artificial nose to sniff you and transmit the data over the internet to a device installed on your friend's machine that takes this data and makes up the exact smell? Does this sound like something belonging to the far future? I honestly think not. There are so many sensors that detect all kind of smells, mostly designed for safety, like those to sniff gas, food turned bad or illegal substances (there's such a device at the entry to the &lt;a href="http://en.wikipedia.org/wiki/Statue_of_Liberty"&gt;Statue of Liberty&lt;/a&gt;, at security check). Look there's even something simpler &lt;a href="http://www.scs.uiuc.edu/suslick/pdf/pressclippings/newsday.htm"&gt;here&lt;/a&gt;. This is just small patch that displays special visual patterns according to the smell in the air. Of course it has only a few smells that it recognises. &lt;br /&gt;&lt;br /&gt;The sniffer should detect all the simple chemical substance and their amount in the composition of the air at any given time and the reproducer should have stores (just like printers have cartridges) of many chemical substances to combine them in the exact amount specified by the sniffer in order to produce the same odor. &lt;br /&gt;&lt;br /&gt;I see a few problems here, the speed and the accuracy of sniffing every small change in the air's chemical composition, the speed and the accuracy of reproducing the small changes at the other end must be as high as possible. I'm sure these will be solved by future technologies.  Another problem will arise when the accuracy is very good, the fragrance creators will lose their market as people will be able to recreate their smell in their own homes...&lt;br /&gt;&lt;br /&gt;Every ingenious idea that you get, after breaking it into smaller parts and realizing that it's so simple, you realise it's impossible to be the only one to come up with it. So of course, I'm not the first, bummer, I was about to request a patent for it... &lt;a href="http://chemse.oxfordjournals.org/cgi/content/full/30/suppl_1/i254"&gt;Here&lt;/a&gt;'s a very nice explanation of the idea, the tests they ran and their results. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.intomobile.com/2006/12/08/nokia-works-on-smell-sensors-solar-charging.html"&gt;Nokia's idea&lt;/a&gt; is also very interesting, I think in a few years we'll use these kind of technologies. I'm so looking forward to it. Imagine including in your profile on &lt;a href="http://www.myspace.com/"&gt;myspace&lt;/a&gt; or &lt;a href="http://www.facebook.com/"&gt;facebook&lt;/a&gt; your smell, how cool would that be?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-5271363063796480915?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/5271363063796480915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=5271363063796480915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/5271363063796480915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/5271363063796480915'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/virtual-perfume.html' title='Virtual Perfume'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-2322380097038474087</id><published>2007-07-12T12:12:00.000+01:00</published><updated>2007-07-14T13:42:14.316+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='LDAP'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><category scheme='http://www.blogger.com/atom/ns#' term='Active Directory'/><title type='text'>LDAP issue</title><content type='html'>A few weeks ago I decided that it would be better if all the web applications we develop would log users in by using their &lt;a href="http://en.wikipedia.org/wiki/Active_Directory"&gt;Active Directory&lt;/a&gt; authentication details. &lt;br /&gt;&lt;br /&gt;This makes things easier for our users, they don't need to remember their username and password for each application. They will most probably use the same details everywhere anyway, but there's no point in keeping this information in many places, is there?&lt;br /&gt;&lt;br /&gt;Well this task seemed pretty SF when I got the idea, but with researching, reading and testing, I managed to make it work. So I use &lt;a href="http://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol"&gt;LDAP&lt;/a&gt; to connect to our AD server and because I use PHP on the server side, I use PHP's &lt;a href="http://uk3.php.net/manual/tw/ref.ldap.php"&gt;LDAP Functions&lt;/a&gt; which are not enabled by default.&lt;br /&gt;&lt;br /&gt;The typical sequence of LDAP calls you will make in an application will follow this pattern:&lt;br /&gt;&lt;br /&gt;  ldap_connect()    // establish connection to server&lt;br /&gt;     |&lt;br /&gt;  ldap_bind()       // anonymous or authenticated "login"&lt;br /&gt;     |&lt;br /&gt;  ldap_search()     // search for some information&lt;br /&gt;     |&lt;br /&gt;  ldap_close()      // "logout"&lt;br /&gt;&lt;br /&gt;For authentication a typical application will do this:&lt;br /&gt; - connect to the server&lt;br /&gt; - bind anonymously or with a predefined user made especially for authenticating&lt;br /&gt; - search for the user name in the directory&lt;br /&gt; - try to bind with the user name and password given and see if it works&lt;br /&gt; - disconnect from the server&lt;br /&gt;&lt;br /&gt;Well this approach is very common. &lt;a href="http://www.phpbuilder.com/board/showthread.php?t=10257921"&gt;Here&lt;/a&gt;'s a code example. If you search on google for "php ldap authentication" you'll find many code samples that do it in a similar way.&lt;br /&gt;&lt;br /&gt;Well, my approach is different. Why bind anonymously or with a special user name and password? Why not try binding directly with the given name and password? That's what I did and it worked, but I noticed a weird thing about the ldap_bind function that I didn't find in the &lt;a href="http://uk3.php.net/manual/tw/function.ldap-bind.php"&gt;documentation&lt;/a&gt;: if the user name doesn't exist in the directory, the function will bind automatically anonymously even though a password is given. &lt;br /&gt;&lt;br /&gt;To make sure the user is really authenticated after a successful bind, do a search of the directory and see if the user name exists and of course if it belongs to the right branch of the directory tree. I think this is more efficient and as secure as the other approach. The other approach does one more bind without reason and if a user enters wrong login password a bind and a search is done anyway, in my approach binding fails and returns failure quicker. Also instead of getting the search results and then the right data out of the structure, I check only the number of results which should be one for a successful authentication.&lt;br /&gt;I know, I know, I'm an optimization freak ;-)&lt;br /&gt;&lt;br /&gt;I found another weird behaviour that needed some more research. I noticed that even though my login details were correct the search returned no results. &lt;a href="http://uk3.php.net/manual/tw/function.ldap-connect.php#73691"&gt;Here&lt;/a&gt;'s the comment that helped me get to the bottom of it. So I had to change the port I was connecting to, from 389 to 3268.&lt;br /&gt;&lt;br /&gt;However I was wondering what did "search the entire tree" mean. I thought I wasn't searching the entire tree, I was searching only for users in a certain domain because I was specifying the DC attribute. Changing the port made everything work, but I just was a bit confused so I tried different filters for my &lt;a href="http://uk3.php.net/manual/tw/function.ldap-search.php"&gt;search&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;I finally found that if I include in my filter the OU (OrganisationalUnit) the search works fine even when connecting to the 389 port. Isn't that interesting? So what does exactly "search the entire tree" mean?&lt;br /&gt;&lt;br /&gt;Here's my code, take a look, give me some comments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;$LDAPFail = true;&lt;br /&gt;//ldap rdn or dn&lt;br /&gt;$ldaprdn  = $username."@mydomain.com";&lt;br /&gt;// associated password&lt;br /&gt;$ldappass = $password;&lt;br /&gt;// connect to ldap server&lt;br /&gt;@$ldapconn = ldap_connect("xxx.xxx.xxx.xxx","389");&lt;br /&gt;if ($ldapconn)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; //binding to ldap server&lt;br /&gt;&amp;nbsp;&amp;nbsp; $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;   // verify binding&lt;br /&gt;&amp;nbsp;&amp;nbsp;   if ($ldapbind)&lt;br /&gt;&amp;nbsp;&amp;nbsp;   {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $dn = "OU=MyCompany_Users;DC=mydomain,DC=com";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $filter="(SAMAccountName=".$username.")";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $sr = ldap_search($ldapconn, $dn, $filter,Array("samaccountname"));&lt;br /&gt;  &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(ldap_count_entries($ldapconn, $sr) == 1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    $LDAPFail = false;&lt;br /&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;   }&lt;br /&gt;&amp;nbsp;&amp;nbsp;   ldap_close($ldapconn);&lt;br /&gt;}&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;I hope this helps someone out there...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-2322380097038474087?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/2322380097038474087/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=2322380097038474087' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/2322380097038474087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/2322380097038474087'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/ldap-issue.html' title='LDAP issue'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-7426149289847921564</id><published>2007-07-11T21:19:00.000+01:00</published><updated>2007-07-12T09:28:24.794+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bit'/><category scheme='http://www.blogger.com/atom/ns#' term='coins'/><category scheme='http://www.blogger.com/atom/ns#' term='cents'/><title type='text'>The Origin of the "Bit" Term</title><content type='html'>I had this expression in my mind after reading various forums/blogs/comments: "just my two cents". People used to end their comments with it and I thought it sounded really cool, so I searched for it to see exactly what it means.&lt;br /&gt;&lt;br /&gt;Well &lt;a href="http://www.everything2.com/index.pl?node_id=49033"&gt;here&lt;/a&gt;'s what I came across, it's the most explanatory explanation I could have found ;-)&lt;br /&gt;&lt;br /&gt;Well this is how I found out that a bit used to mean a long time ago an eighth of a coin, because the coins were very valuable because they were made of gold or silver and they were worth the value of the metal they were made of. Therefore they used to split the coins into halves, quarters and eighths. Imagine how small an eighth of a coin was. &lt;br /&gt;Now I assume that the expression "bits and pieces" is as well related to old coins and subdivisions. So they used to make their money bit by bit ;-)&lt;br /&gt;&lt;br /&gt;Well, just my two cents :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-7426149289847921564?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/7426149289847921564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=7426149289847921564' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/7426149289847921564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/7426149289847921564'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/origin-of-bit-term.html' title='The Origin of the &quot;Bit&quot; Term'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7386613993853768674.post-4545533232538032405</id><published>2007-07-06T15:51:00.001+01:00</published><updated>2007-07-11T17:37:05.724+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='voodoo'/><category scheme='http://www.blogger.com/atom/ns#' term='guru'/><category scheme='http://www.blogger.com/atom/ns#' term='wizard'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Voodoo Programming</title><content type='html'>Here's a concept I just found out: voodoo programming.&lt;br /&gt;I've had people around me doing this and I had a hard time explaining to others what these guys do, now I have a quick way to categorize them. &lt;br /&gt;OK, so voodoo programming is basically programming without fully understanding. &lt;br /&gt;Just push run and if it works, call it your masterpiece :) Come on, there are so many people that do this. First step is google for the code that does what you want. Then copy, paste and run. If it works, job done, carry on with the next task...&lt;br /&gt;&lt;br /&gt;These programmers are called witch doctors, pretty nifty, don't you think?&lt;br /&gt;Well, gladly for me, I like to consider myself a guru or wizard. And yes, I'd like to be thought the same by those around me.&lt;br /&gt;&lt;br /&gt;More info &lt;a href="http://en.wikipedia.org/wiki/Voodoo_programming"&gt;here&lt;/a&gt;. Thanks for &lt;a href="mailto:monekeyboy@wired.com"&gt;Thau&lt;/a&gt;, he's the one that I heard this concept from.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7386613993853768674-4545533232538032405?l=webdevlucian.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://webdevlucian.blogspot.com/feeds/4545533232538032405/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7386613993853768674&amp;postID=4545533232538032405' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/4545533232538032405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7386613993853768674/posts/default/4545533232538032405'/><link rel='alternate' type='text/html' href='http://webdevlucian.blogspot.com/2007/07/voodoo-programming.html' title='Voodoo Programming'/><author><name>Lucian Pricop</name><uri>http://www.blogger.com/profile/17245028832744569459</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
