When I started this little thing a month and a half ago, I didn't expect anyone to notice it right away. The Internet is a big place and Rockets is, for now, quite small.
But a few people have found their way here (welcome guys!) and so I now need a way to send some welcome emails for new users.
I've added a function called (send-mail), which sends an email to a given address. Behind the scenes it uses the Unix command sendmail, so you will need to have that installed on your server (simply type "sudo apt-get install sendmail" on Ubuntu or Debian).
To avoid emails falling into spam traps, you need to be sending from a valid email address that has the same domain as the server that is sending it. The (send-mail) function will take care of all the headers and things automatically.
For example, for new users, I simply use:
(send-mail UserEmail "email@example.com" "Rocket Man" "Welcome to the newLISP on Rockets blog!" welcome-email)
where welcome-email is the string of the body of the email.
Documentation is something I have a particular fondness for. I actually got my start in the software industry as a technical writer, so I appreciate it when things are well-documented. Of course now that I am a developer I find writing documentation to be a chore!
The way I've done documentation in Rockets is to automatically generate it from the comments in the core file that contains all of Rockets' functions. However in order for this to work I had to go back and clean up and standardize all the comments, something that I had been putting off. Oh well, sometimes chores need to be done!
One thing I always disliked about most programming documentation is the requirement to understand and translate some weird meta-language or syntax for the usage of each statement. Usually it was easier to just look at the example and figure out what the author meant. So for Rockets, all my usage statements are in fact examples, albeit using names and strings that describe their actual function. So for example (open-database "database name") is both the usage and the example of opening a database.
This is something really simple, the perfect assignment for a Monday morning.
Go to your site's root directory (usually /var/www) and edit the .htaccess file (type sudo nano .htaccess)
Add the following line to the end of the file:
ErrorDocument 404 /rockets-404.lsp
Now any 404 (page not found) errors will redirect to this page instead of displaying the generic Apache error.
This would be a PERFECT message to test out adding comments to.. if you know what I mean. Hint, hint.Comments (13)
Yes, with Rocket Captcha(tm) and everything!
You can't do anything once you sign in (like post messages or anything) yet but... you'll have an account!
Sometimes you want your application to remember where you were, but the application wants to redirect you to somewhere else.
This is most annoying when you sign in. You probably want to stay on the page you were on instead of being redirected back to the main page.
Rockets adds a global variable called (active-page). You have to set it before you call the navigation bar so it knows which page to highlight. But it also passes this variable as a hidden field in the navigation bar itself, alongside the user email and password, so that the verification script (rockets-verify.lsp) can redirect you back to that page if you either succeeded or failed in signing in.
Paging code is really easy in SQLite. You do a SELECT statement as normally but add the LIMIT clause with two numbers separated by a comma. The first number is the offset, aka where you start from, and the second number is the number of results you want back. So if you wanted ten results starting from the thirtieth, you just SELECT ... LIMIT 30,10 and that's it!
Displaying the current paging links is something I might want to do a lot, so I made a function in Rockets to do it. The function works like this:
(display-paging-links int-start-page int-total-pages int-current-page str-page-url)
So to display the top ten pages you'd call (display-paging-links 1 10 1 "rockets-main").
Neat and easy!
Eliminating duplicate code is a great thing. If you have code that is duplicated on many pages, if you want to change it you have to remember to change it on all your pages.
I originally made a framework function (display-navbar) that displays a navigation bar and sign-in form. This was great, but (display-navbar) needs to take a list as an argument to decide what menus to actually show. I didn't want to repeat this list on each page, but I also needed a way to show which page was currently active.
One way would be just to define a new function, (display-rockets-nav "active page") that would then call (display-nav) and specify which page is actually active. But then I would want to make sure this function is defined on every page. Well, I already have a set of common functions in the partial "rockets-common-functions.lsp". I could just put it in there.
The other option is to define a new partial page, "rockets-navbar.lsp", and call this partial each time. Which approach is better? They both require the same amount of code (I have to add a line to either call the function or display the partial). The only real difference is that if I go the function route I would have to have two functions, one in the framework, and one in the application, that had similar names, and I'd have a function calling a function. If I put it in a partial file, it looks like it is doing something different.
Ultimately it's an aesthetic choice. If you make your own application you might decide to do it differently. I might even change my mind at some point!
An existential question, indeed...
For no apparent reason I decided to write a whole essay about it: http://newlisponrockets.com/rockets-why.lsp
Cookie security is something many sites don't bother with, because who would ever fake a cookie? Well, as it turns out, a lot of people could do just that.
Cookie security best practices have been known for a while. This article from 2005 lays them out pretty nicely: http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
Basically, you want to have a random number as your cookie, but then the value should not just be the user Id. It should be hard to guess. And what if a user registers and then copies your carefully-selected random number cookie but just changes the user id? Then they could log in as any user they wanted!
So what we do is add some salt to the cookie in the form of ANOTHER random number, each one unique to each user. The salt is stored in the user database, so it isn't available to the public. This makes every cookie unique for each user.
You also want to be running everything under SSL (aka https) to avoid issues with people stealing cookies with things like FireSheep over WiFi connections, but that's something that can be up to the site administrator.