iPhone OS 3.0 and still no mail rules

June 25th, 2009 by Sjan Evardsson

I’ll admit it, I love my iPhone. I use it all the time for keeping track of tasks, taking notes, keeping grocery lists, buying movie tickets, updating my Netflix queue, getting directions, finding out where to get a widgit, snapping quick pictures of my cat being goofy, listening to music, playing word games, Twitter, and sometimes even phone calls! While I am looking forward to being in a position to upgrade my hardware (still on a version 1) to the 3GS, there is one feature that is still lacking from the iPhone.

Mail rules. C’mon, how hard can it be? When I plug in my iPhone to sync with iTunes, why can’t the rules from Mail.app (at least) be synced at the same time. And then applied when I check my mail. I find the idea of “leave your computer turned on and downloading mail” to be unacceptable. I work from a MacBook Pro, which is usually with me when I am on the road. And if it isn’t, it is either sleeping or shut down entirely to save energy.

OK, this is my feeble attempt at a demand on Apple: get mail rules working in the iPhone Mail app for the next OS update, or else! (Or else, uh, I guess I will continue to be annoyed?)

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

SPDO now on SourceForge

June 19th, 2009 by Sjan Evardsson

Hooray! SPDO is now officially on SourceForge. Now I can begin dismantling the local Wiki and the (mostly) empty blog page.

Things are just getting started for it over there, but you can download the source, checkout the source via SVN, issue bugs in Trac and read the Wiki and Documentation. (I may end up moving all the Wiki info into the Trac Wiki just to reduce the number of apps I have to deal with over there.)

The plan is to push out a version 1.0 release at the end of July, assuming there are no show stoppers. Please, test and report. Also, if you are a PHP/Python dev and handy with SQL and would like to help out let me know.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

Margin vs Markup, or Basic Business Math

June 13th, 2009 by Sjan Evardsson

I was a bit surprised to find myself in the position, earlier this week, to have to explain to some co-workers how I determined a cost multiplier (another way of doing price markup) from the profit margin that I was given. I took it from the discussion that took place that in dealing with developers in the past they ran into the issue where they were saying “margin” and the developer was thinking “markup” or just didn’t get difference between the two.

I decided to test out what they were saying. I asked a few people I know (not all developers): “What would the retail price of a $100 cost item be, at a 50% profit margin?” The answer I got most often was $150. Um, so I guess they were right. $150 for an item that costs $100 is a markup of 50%, not a margin of 50%.

Wow, ok, I thought everyone knew this stuff. Since that doesn’t seem to be the case, this is Basic Business Math for all those devs who have to deal with it (and we all do at some point).

What is the difference between Profit Margin and Markup?

Too often, the terms Profit Margin and Markup are confused. For instance, if you ask someone what the selling price of an item that costs $100 would be if you set your profit margin at 50%, the odds are (too) good that they will reply $150. This is incorrect. And here is why.

Profit Margin refers to the percentage of the selling price that is profit. So in the example above, an item that costs $100 and sells for $150 has a profit margin of 33.333% (rounded to the nearest hundredth of a percent). That is because 2/3 of the price is cost while only 1/3 is profit. (By the way, for a 50% profit margin you would sell the item at $200, or 2 times the cost, commonly referred to as “keystone”. – See the next section.)

Markup refers to the amount you add to cost to get the selling price (sometimes referred to as “cost plus”). As we have already seen, the markup for a 50% Profit Margin is 100%. There are several ways of adding markup to the item cost. Some sellers prefer to use Markup rather than Profit Margin to determine the price of everything. In other words, they will take the cost and add some set percentage to determine the price. In some industries the standard Markup is keystone, or cost + 100%, while in others it is double keystone (cost + 200%) or even triple keystone (cost + 300%). Others prefer to set a Profit Margin to operate on and use that to determine Markup.

How do we tie Markup to Profit Margin?

In order to tie Markup and Profit Margin together (as in to determine one form the other) we need to understand the relationship between the two. In order to make this simpler we will convert all percentages to decimal numbers. (You remember from grade-school math that 40% is the same as 40/100 which is .4, right?)

Determine Selling Price and Profit Margin from Markup

For this section we will start with a 75% Markup.

Determining Selling Price from Markup is simple. A 75% Markup is equal to cost * .75. So you end up with:

cost + (cost * .75) =
(1 * cost) + (cost * .75) =
cost * 1.75

Cost multiplier is simply 1 + markup (as a decimal).

Selling price is cost * multiplier.

Determining Profit Margin from Markup is a bit different. We need to determine the percentage of the selling price that is profit. In order to do that we need to first determine the percentage of the selling price that is cost. We can do this without even knowing the cost (because regardless of cost the amount we are marking up is the same.) We do this by dividing 1 by the Markup. (If you are uncertain about this, think about this, 1 is 25% of 4, which can be expressed by any of the following identical numbers: 25% = .25 = 1/4) So, for a markup of 1.75 we get:

cost percentage = 1/1.75 = 0.57142857 = 57.143%
margin = 100% - 57.143% [cost percentage] = 42.857%
Or in a more compact form: margin =  1 - (1/1.75)

which gives us 0.42857143 or 42.857%.

Cost percentage of selling price is simply 1/multiplier.

Profit Margin is 1 – cost percentage.

margin = 1 – (1/multiplier)

Determine Markup and Selling Price from Profit Margin

For this section we will start with a 40% Profit Margin

For a Profit Margin of 40% (.4) we need to know that 40% (.4) of the selling price is profit. This means that the other 60% (.6) is cost percentage.

To determine a selling price directly from Profit Margin we would simply do cost/(1 – margin), or in this case, cost/ (1 – .4) = cost/.6 This is not always desirable, however, as multipliers are often easier to work with. So how do we turn cost/(1 – margin) into a multiplier?

The quick and easy way to do this is to remember that X/Y = X * (1/Y) (proof? 4/2 = 4 * (1/2)). So our Markup percentage is simply 1/(1 – margin), or in this case .667. And remember from the section on Markup that to determine a multiplier from markup we simply need to add 1

Cost percentage is 1 – profit margin.

Cost multiplier is 1/(1 – profit margin).

Selling price is cost * multiplier.

multiplier = 1 + (1/(1 – margin))

What about exchange rates?

This calculator adds in another layer of complexity, that of currency value vs the dollar. By dividing the results from the formulae above by the currency value versus the dollar we can determine Markup multipliers for a given currency value and profit margin, or profit margins for a given currency value and markup multiplier, or even currency values for a given profit margin and markup multiplier.

The actual formulae used in the script are:

mv = (1/((100 - pm)/100))/cv
cv = (1/((100 - pm)/100))/mv
pm = 100 - (1/(cv*mv))*100

Note that Profit Margin values are passed in and returned like 40 rather .4 so the multiplication and division by 100 in the actual formulae are tied to that. Here are the same formulae in their simplest forms, where m = markup multiplier, c = currency value and p = profit margin, all expressed as decimal numbers.

m = [ 1 / ( 1 - p ) ] / c
c = [ 1 / ( 1 - p ) ] / m
p = 1 - [ 1 / ( c * m ) ]

I put together a js calculator to show Profit Margin and Markup multipliers for any currency (currency exchange values are updated daily Monday through Friday but I cannot guarantee their accuracy) and put it on a page explaining the differences between Margin and Markup and how they are all determined.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

Error Handling and the PHP @ Operator

June 7th, 2009 by Sjan Evardsson

I have been trying to debug a plugin for WordPress (Shorten2Ping – I will keep plugging this because I think it is so nifty!) and I was running into a problem where the plugin would silently fail with nothing in the logs, no error printing to screen, just dead silence.

I turned on display_errors in php.ini for a while to see if anything would show up. Still nothing. So I started to look through the file again. I knew it was getting as far as creating the short url in bit.ly before it died, but nothing was getting entered into the database. So I started through the make_bitly_url() function and what jumped out and slapped me in the face? $json = @json_decode($response,true); That little, innocuous-looking @ was gulping the error message from a fatal error! (Namely, “Call to undefined function json_decode()“). It turns out that I had PHP compiled with –disable-json, which is default for Gentoo unless you have json in your USE flags.

According to the PHP docs for the Error Control Operator @:

Currently the “@” error-control operator prefix will even disable error reporting for critical errors that will terminate script execution. Among other things, this means that if you use “@” to suppress errors from a certain function and either it isn’t available or has been mistyped, the script will die right there with no indication as to why.

So, if you really must supress error messages, do so, but do so with care. In the case where a suppressed error may be fatal (as in this case) be sure to add documentation to that effect. As in “If this dies a silent death it may very well be that you do not have function xyz() enabled.”

And, note to self, when debugging PHP, the first thing to do is look for and remove the error control operator.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

Interesting log activity

June 6th, 2009 by Sjan Evardsson

While trying to debug the Shorten2Ping plugin (a really nifty thing, if I could get it working) I went digging through my Apache error logs looking for any PHP errors. (Well, okay, I didn’t actually dig, I just did a last on the file.) What I saw was interesting, even though it did not help the debugging at all. In fact it kind of derailed the whole process. What I saw was an obvious attempt to find Horde on my server (which I did run temporarily a few years ago). My first guess was that there was a new exploit out for Horde. I did some digging around and found that, yes, indeedy, there is. I found the details of the exploit at securityvulns.com (which is a mirror of or mirrored by www.security.nnov.ru which is where the first relevant Google link took me.) Oddly enough I have not seen this show up on any other security sites yet, even though I see that the report on securityvulns.com is from March.

Anyhow, in case you are curious, here are the relevant lines from the log. (IPs have not been changed to protect the guilty.)

[Sat Jun 06 01:46:53 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/README
[Sat Jun 06 01:46:53 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde
[Sat Jun 06 01:46:54 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde2
[Sat Jun 06 01:46:55 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde3
[Sat Jun 06 01:46:56 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde-3.0.5
[Sat Jun 06 01:46:57 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde-3.0.6
[Sat Jun 06 01:46:58 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde-3.0.7
[Sat Jun 06 01:46:58 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde-3.0.8
[Sat Jun 06 01:46:59 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/horde-3.0.9
[Sat Jun 06 01:47:00 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/mail
[Sat Jun 06 01:47:01 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/email
[Sat Jun 06 01:47:02 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/webmail
[Sat Jun 06 01:47:03 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/newmail
[Sat Jun 06 01:47:03 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/mails
[Sat Jun 06 01:47:04 2009] [error] [client 81.210.76.194] File does not exist: /var/www/localhost/htdocs/evardsson.com/mailz

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

Keeping Gentoo Fresh

May 31st, 2009 by Sjan Evardsson

I had a converstion with a friend about Linux distros earlier today, and I was asked why I choose to run Gentoo on my web server. He told me that Gentoo was too hard to maintain on a server, and that when it came time to upgrade something (like Apache or PHP) due to security patches that it took too long, and too often failed. I was confused by this so I asked for clarification. What he described was the pain of updating anything on a “stale” Gentoo machine.

Unlike so many of the other popular distros, Gentoo does not, by default, use pre-compiled packages. So unlike doing rpm -i or apt-get install doing emerge on Gentoo requires that the package you are installing, and any missing dependencies, are pulled in as source code and compiled. When you think about adding packages like, say, Lynx, the process takes only a few minutes on a moderately decent machine. (Mine is a PII 966 and Lynx took about 4 minutes start to finish). When you talk about upgrading something like Apache, however, the length of time it takes depends not only on the speed of the machine, but how many of its dependencies are out of date. In fact, if you fail to update regularly you can run into an issue where not only are most of your files out of date, but your system profile is out of date and you need to do some serious wrenching to get the whole thing working again. In the times that this has happened to me (twice) I was able to get the system up-to-date once, and just gave up and reinstalled a newer version the second time. (These were both rarely used VMs, and not production boxes.) However, updating the profile on a “fresh” Gentoo is (in my experience) a painless procedure of rm /etc/make.profile && ln -sf /usr/portage/profiles/profile_name /etc/make.profile && emerge -uND world (uND : update newuse deep: update, take into account new use settings from the profile and make.conf, and include deep dependencies).

So how do I avoid the “stale” Gentoo syndrome? I take a three-step approach.

  1. A daily cron job runs emerge -puvD world (puvD : pretend update verbose deep : just tells you what would be emerged, in an update, verbosely, and include deep dependencies) and emails me the output. This enables me to see each morning which packages have updates available.
  2. Every day that I have the time for it I log into the machine and run emerge -uD world and follow it up with etc-update (if needed) and revdep-rebuild if any libraries were included in the updates. (I save building new kernels for Sundays, and that doesn’t happen all that often, but I do like to always run the latest.)
  3. I check the messages from emerge to see if there are any special configuration changes that need to happen post-install that cannot be handled by etc-update. For instance, changing configurations in /etc/conf.d/packagename, new profiles or anything of that sort.

Ok, so I like to keep my system on the latest and keep a shiny new everything on it. How does that compare with something like, say, Debian? In Debian (and Debian-based distros) you can update packages to a certain point, after which the package for that version of Debian is no longer supported or updated. So you need to upgrade your version, and your kernel, which you do with apt-get upgrade dist. Seems easy enough. And how does Gentoo handle version upgrades? It doesn’t need to. If you keep your system up-to-date in the way I described your system will match whatever the latest Gentoo release has. In fact, I built my web server using Gentoo 2006.0 and have been keeping it up-to-date since then. (Gentoo seems to have stopped doing the biannual releases, btw – they are now releasing updated minimal install CDs nearly weekly for each architecture.)

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

My thoughts on Git

May 30th, 2009 by Sjan Evardsson

I have been working with Git for a while now, and I have a few thoughts about it. I am used to the SVN model, where multiple developers check out of a central repository, make changes locally and then commit them back to the repo (and repair failed merges). While SVN is not perfect, at least I am comfortable with it and know what to expect from it. While some of my issues with Git may relate solely to my relative unfamiliarity with it, at least it seems like I am not the only one with issues.

In reading through the man pages and all the documentation I can find on line (including the Git – SVN Crash Course) I was totally unprepared for what actually happens. According to the Crash Course git commit -a does the same thing as svn commit, but that is not quite the case. After a commit the files still need to be moved to the repo. So as I am looking for the best way to do that I find git push. Well, it would seem to me that firing off a git push would mean that I want the files I have modified and committed to merge into the repo I checked them out of. But that isn’t quite what happens if there are any working directories checked out the repo (meaning the one you are working on). It seems that the only way to properly get the files back into the repo is to issue a git pull from the repo aimed at your working branch. Hans Fugal said it best in his post from last year: git-push is less than worthless.

What this means is that I am unable to easily move changes from my laptop to the server. Instead, in order to reduce the number of steps I need to take I check out the repo I am working on (git clone) in my home directory on the server and then use sshfs to mount that directory locally. I do my work there, and then ssh in to the working directory, fire off git commit -a and then cd to the repo to pull from the working directory. Of course this seriously hampers my ability to work offline (as in I can’t). While I am sure there are plenty of good things about Git I am not yet really seeing them. With the exception of git stash I have yet to be wowed by anything Git has to offer. In the interest of fairness, however, I have not been incredibly wowed by anything SVN has to offer either, I just find it easier to use.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

SPDO moving to SourceForge (I hope)

May 27th, 2009 by Sjan Evardsson

While school has kept me busy during my non-work hours I have not had much time to tend to other projects like SPDO. Seeing how my “Abandoned Project Takeover” has been approved on SourceForge, however, has encouraged me to set aside some time to do some house cleaning on the code to get the 1.0b ready to bump to 1.0 stable. According the information they have given me it takes 2 to 3 weeks to fully process an “APT” so I do have a little time (although not a lot). This is not the first time I have tried to do this, but last time it never made it to the approval stage and languished in the queue until it timed out. So, now that it was approved and has been in the queue for 4 business days I am hopeful.

In a lot of ways, moving the project to SourceForge is a lot like making a physical change of residence. It will require updating links, setting up the pages there including wiki, bug tracking, etc, and moving the actual code base over. (Good thing it’s small!)

As always, any suggestions, bugs, or feature requests are welcome, and (for now) should be posted at the page set aside for just that.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

Gentoo: Spamassassin crashed! What?

May 23rd, 2009 by Sjan Evardsson

Life has been rather hectic lately, and a few things have fallen by the wayside in the interim, including simple maintenance tasks like, oh, mowing the lawn, and cleaning out the folder of spam for bayseian analysis, and other fun items. So when my inbox started to be flooded with what seemed like ten times the normal amount of spam I get (very little of which Mail.app leaves in the Inbox) I decided to take a quick look at the server and see what was going on.

I ran a quick /etc/init.d/spamd status and got the response *status: crashed – Uh oh. A quick check of running processes showed that spamd (the SpamAssassin daemon) was indeed not running. I did a quick restart and thought nothing of it. Spam traffic slowed right back down. For about 10 hours. Suddenly I was getting hammered again. Checked the server and once again *status: crashed – “Ok”, I thought. I restarted it yet again and then immediately checked the status. Again it showed as crashed. Checking the running processes with ps -a | grep spamd showed something different, however. It showed the SpamAssassin daemon happily chugging along.

A bit of searching brought me to the relevant bug report for Gentoo. It seems that there is something in the way SpamAssassin starts the daemon that causes the pidfile to not be written, which leaves OpenRC with the notion that it has crashed. The fix is there in the bug report, though. By changing the spamd init file ( /etc/init.d/spamd ) with the addition of a forced pidfile SpamAssassin starts and OpenRC is happy as well. All by adding the one line you see below (in bold):

        start-stop-daemon --start --quiet \
                --nicelevel ${SPAMD_NICELEVEL:-0} \
                --pidfile ${PIDFILE} \
                --exec /usr/sbin/spamd -- -d -r ${PIDFILE} "" \
                        ${SPAMD_OPTS}

Now if I could just find a one-line fix for an overgrown lawn. And dandelions …

[Edit]:

The reason for the actual crashing was due to the overgrown spam folder for bayseian analysis. It seems that running the sa-learn utility against a 6 GB directory causes all sorts of Bad Things TM to hapen, as it parses every file (again) to determine whether it can “learn” from it. I cleaned out the directory and have had no problems since then.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon] 

New Beginnings

May 1st, 2009 by Sjan Evardsson

Just a short post to update all my regular readers out there (yes, both of you) that I start my new job next Wednesday and I started school full-time today. Yes, today. I have started in the BS – IT Security Emphasis program at Western Governor’s University. I don’t have a projected finish date yet, but their competency-based model means that I can finish my degree much faster than with a standard program. (Word from one of the admissions counselors is that IT professionals going in to the IT program tend to finish their Bachelor in around 2 years.)

Although I shouldn’t have to remind anyone I will: everything I say (well, type) here is my opinion and does not reflect the views or opinions of my employer or the school which I attend. With that said I have only one small grievance about my first day at WGU: every link in the student portal has a target of _blank or uses a js call to open a new window. Grrrr. My opinion: bad design idea.

[Post to Twitter]  [Post to Yahoo Buzz]  [Post to Delicious]  [Post to Digg]  [Post to Ping.fm]  [Post to Reddit]  [Post to StumbleUpon]