<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Blair Robot Project Blog &#187; TMS</title>
	<atom:link href="http://robot.mbhs.edu/wordpress/tag/tms/feed/" rel="self" type="application/rss+xml" />
	<link>http://robot.mbhs.edu/wordpress</link>
	<description></description>
	<lastBuildDate>Thu, 04 Mar 2010 16:10:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The Joys of Configuring Postfix</title>
		<link>http://robot.mbhs.edu/wordpress/2009/the-joys-of-configuring-postfix/</link>
		<comments>http://robot.mbhs.edu/wordpress/2009/the-joys-of-configuring-postfix/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 18:57:02 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[postfix]]></category>
		<category><![CDATA[Teque]]></category>
		<category><![CDATA[TMS]]></category>

		<guid isPermaLink="false">http://robot.mbhs.edu/wordpress/?p=608</guid>
		<description><![CDATA[Configuring postfix is well-known to be the hardest, least intellectually stimulating task any IT person will ever pass off to a hapless subordinate.  I, unfortunately, would seem to be that hapless subordinate.  Eric recommended (and, in fact, convinced me) that I write a perl script to act as a delivery agent for postfix. [...]]]></description>
			<content:encoded><![CDATA[<p>Configuring postfix is well-known to be the hardest, least intellectually stimulating task any IT person will ever pass off to a hapless subordinate.  I, unfortunately, would seem to be that hapless subordinate.  Eric recommended (and, in fact, convinced me) that I write a perl script to act as a delivery agent for postfix. This would offer grate flexibility, customizability, blah, blah, blah.  Not to drag out the story, I got to a point where I realized I had a 200 line mess that didn&#8217;t work half of the time, wasn&#8217;t properly interacting with postfix, and needed another 1000 or so lines to do what was really required of it.  So I dropped the project, and fell back to using mysql aliases, which looked to me like the easiest option when I need relatively dynamic mailing lists integrating with custom software that uses mysql.</p><span id="more-608"></span>
<p>My task was in two parts &#8211; write a relatively simple system that enabled users of <abbr title="Team Management System">TMS</abbr> to receive mail at <code>username@robot.mbhs.edu</code>, as well as a limited set of aliases (like <code>webmaster@robot.mbhs.edu</code> &#8211; that&#8217;s me!).  The second task was to create an alumni mailing list (at the same domain, on the same host), to which only a certain group of people (the &#8217;senders&#8217;) could send mail.  I thought it might be nice to use some good, old-fashioned third party software the way the school does for all its other mailing lists (or maybe google groups would be a nice idea?), but Eric wouldn&#8217;t hear of it &#8211; he wanted in-house.  Irony: he and the other Teque folks spent at least a month making fun of me for my fondness for in-house software.</p>
<p>The first part was relatively simple, using the tutorial <a href="http://www.postfix.org/MYSQL_README.html">here</a>.  The second part was slightly harder.  For starters, the alumni list was stored on binx, and I was hosting the listserv from ogodei.  So some crontabs were in order.  From binx, I printed the list from mysql to a file (not shown).  From ogodei, I did the opposite:</p>
<pre class="0">
root@ogodei:/var/www/ctda# cat /etc/postfix/alumni-email-manager.pl
#!/usr/bin/perl

use DBI;

$dbh=DBI->connect("dbi:mysql:web;user=web;password=********");
open FH,"/var/local/roboweb/alumni_emails";
$dbh->do("start transaction");
$dbh->do("truncate table alumni_list_temp");
while(<FH>) {
    $email=$_;
    $email=~s/\n//;
    $dbh->do("insert into alumni_list_temp (destination) values ('$email')");
}
$dbh->do("commit");
close FH;
$dbh->disconnect;
</pre>
<p>Then I had to actually set up the mailing list, along with the relevant permissions to ensure that people outside of the senders list could not write to the list. (We have no moderation system, since our in-house ability does not extend to rewriting mailman.)</p>
<pre>
root@ogodei:/var/www/ctda# cat /etc/postfix/main.cf
# See /usr/share/postfix/main.cf.dist for a commented, more complete version


# Debian specific:  Specifying a file name will cause the first
# line of that file to be used as the name.  The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname  

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# appending .domain is the MUA's job.
append_dot_mydomain = no   

# Uncomment the next line to generate "delayed mail" warnings
#delay_warning_time = 4h

readme_directory = no

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_recipient_restrictions = check_recipient_access mysql:/etc/postfix/protected_users.cf, reject_unauth_destination

smtpd_restriction_classes = whitelist
whitelist = check_sender_access mysql:/etc/postfix/whitelist.cf, reject

myhostname = team.robot.mbhs.edu
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = team.robot.mbhs.edu, localhost.robot.mbhs.edu, localhost, robot.mbhs.edu, www.robot.mbhs.edu, ogodei.mbhs.edu, tms.robot.mbhs.edu
relayhost = 
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_command =
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
home_mailbox = Maildir/

alias_maps = mysql:/etc/postfix/mysql-aliases1.cf, mysql:/etc/postfix/mysql-aliases2.cf, mysql:/etc/postfix/mysql-aliases3.cf
</pre>
<p>Scattered throughout, but not shown here, are various debugging lines from me trying to figure out why postfix was completely ignoring my instructions.</p>
<pre>
root@ogodei:/var/www/ctda# cat /etc/postfix/mysql-aliases1.cf 
hosts=127.0.0.1
user = web
password = #######

dbname = web

query = SELECT destination FROM mail_aliases WHERE source='%u'
result_format = %s@robot.mbhs.edu

root@ogodei:/var/www/ctda# cat /etc/postfix/mysql-aliases2.cf 
hosts=127.0.0.1
user = web
password = ##########
dbname = web
query = SELECT email FROM users WHERE username='%u'

root@ogodei:/var/www/ctda# cat /etc/postfix/mysql-aliases3.cf 
hosts=127.0.0.1
user = web
password = ########
dbname = web
query = SELECT destination FROM alumni_list_temp WHERE '%u'='alumni'
</pre>
<p>The filenames being undescriptive, here&#8217;s what they do: the first handles the aliases, and redirects it to either another alias or a username (for example, <code>webmaster@robot.mbhs.edu</code> might redirect to <code>web.dev@robot.mbhs.edu</code>, which might redirect to <code>scott@robot.mbhs.edu</code>).  Ruleset 2 handles actual usernames.  Ruleset three handles the alumni mailing list.</p>
<p>Footnote: yes, as those of you who have actually been reading this blog have noticed, this is the same project I outlined in <a href="http://robot.mbhs.edu/wordpress/2009/risky-plans/">Risky Plans</a>.  The others have not made much progress either, but I have release <a href="http://firstsearch.robot.mbhs.edu/">FIRSTSearch</a>!</p>]]></content:encoded>
			<wfw:commentRss>http://robot.mbhs.edu/wordpress/2009/the-joys-of-configuring-postfix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maintaining a Separate Draft Copy of a Website</title>
		<link>http://robot.mbhs.edu/wordpress/2009/maintaining-a-separate-draft-copy-of-a-website/</link>
		<comments>http://robot.mbhs.edu/wordpress/2009/maintaining-a-separate-draft-copy-of-a-website/#comments</comments>
		<pubDate>Sun, 21 Jun 2009 05:53:44 +0000</pubDate>
		<dc:creator>Scott</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Website Development]]></category>
		<category><![CDATA[302]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[TMS]]></category>

		<guid isPermaLink="false">http://robot.mbhs.edu/wordpress/?p=379</guid>
		<description><![CDATA[On websites with traffic outside of a group of coworkers, you may find it desirable to modify a copy of the website, and then periodically upload the new version.  Both the main robotics website and TMS (&#8220;Team Management System&#8221;) are developed apart from the main website, and then the drafts are periodically &#8220;pushed&#8221; onto [...]]]></description>
			<content:encoded><![CDATA[<p>On websites with traffic outside of a group of coworkers, you may find it desirable to modify a copy of the website, and then periodically upload the new version.  Both the main robotics website and TMS (&#8220;Team Management System&#8221;) are developed apart from the main website, and then the drafts are periodically &#8220;pushed&#8221; onto the main site.</p>
<p>While this technique may not seem particularly impressive to some, some problems come up when you actually try to implement it. The most major problem is that when you push, all the links are now broken.  A link to <code>/draft/page.html</code> needs to become <code>/page.html</code> when the page is pushed, and this is hard to automate.  (A simple regexp is <em>not</em> enough: what about favicons and stylesheets?)  The more minor problem that comes up is design-based, and depends on how you plan to store your pages.  If you use a simple filesystem-oriented storage method, there will be no problem.</p>
<span id="more-379"></span>
<p>There are three approaches to handling the link problem.  The first is to manually change the URLs in the links, maybe writing a few scripts to help.  This quickly degenerates into chaos; however, it is the only one that works well with a simple, filesystem-oriented website.  If you have a serving script, you can make all your links be to urls of the form <code>$prefix/page.html</code>.  Then, in your serving script, you can have,</p>
<div class="geshi no php"><ol><li class="li1"><div class="de1"><span class="kw1">if</span><span class="br0">&#40;</span><span class="kw3">ereg</span><span class="br0">&#40;</span><span class="st0">&quot;^/draft&quot;</span><span class="sy0">,</span><span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&quot;REQUEST_URI&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="re1">$prefix</span><span class="sy0">=</span><span class="st0">&quot;/draft&quot;</span><span class="sy0">;</span></div></li>
<li class="li1"><div class="de1"><span class="kw1">else</span> <span class="re1">$prefix</span><span class="sy0">=</span><span class="st0">&quot;&quot;</span><span class="sy0">;</span></div></li></ol></div>
<p>This is the method TMS uses.  The flaw is that you have to be careful to begin <em>every</em> link with <code>$prefix</code>.</p>
<p>The third method might be a bit tacky, but is much more effective and reliable.  Like #2, it requires a serving script.  Insert the following at the top of your serving script: </p>
<div class="geshi no php"><ol><li class="li1"><div class="de1"><span class="kw1">if</span><span class="br0">&#40;</span><span class="sy0">!</span><span class="kw3">ereg</span><span class="br0">&#40;</span><span class="st0">&quot;^/draft&quot;</span><span class="sy0">,</span><span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&quot;REQUEST_URI&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">ereg</span><span class="br0">&#40;</span><span class="st0">&quot;edu/draft&quot;</span><span class="sy0">,</span><span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&quot;HTTP_REFERER&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div></li>
<li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw3">header</span><span class="br0">&#40;</span><span class="st0">&quot;Location: /draft&quot;</span><span class="sy0">.</span><span class="re1">$_SERVER</span><span class="br0">&#91;</span><span class="st0">&quot;REQUEST_URI&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span></div></li>
<li class="li1"><div class="de1">&nbsp; &nbsp; <span class="kw3">exit</span><span class="sy0">;</span></div></li>
<li class="li1"><div class="de1"><span class="br0">&#125;</span></div></li></ol></div>
<p>Any link on a draft page will <em>appear</em> to link to the main page; however, when the link is clicked, the browser will receive an HTTP 302 redirect to the drafts page.</p>
<p>If you are using a serving script with meta-information stored into a database, you may come into another problem: should you store two completely separate copies of the database, or should you only separate the content and have a single database. TMS only separates the content &#8211; as a result, when a page exists in the draft pages but not in the main pages, the user will get a &#8220;page not available&#8221; message if he tries to access that page.  In addition, deleting pages can be annoying, since you can&#8217;t actually remove the page from the database until the drafts have been pushed.  In contrast, the main site takes the middle road.  The pages and their meta-information are all kept separate from the drafts and their meta-information, but all other data, like quotes and articles, is the same regardless of whether the draft copy is being viewed or not.  Depending on your needs, you might want to pick another option.</p>]]></content:encoded>
			<wfw:commentRss>http://robot.mbhs.edu/wordpress/2009/maintaining-a-separate-draft-copy-of-a-website/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
