<?xml version="1.0" encoding="UTF-8"?>
<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>Tech on Tour &#187; Programming</title>
	<atom:link href="http://www.techontour.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.techontour.com</link>
	<description>Your resource for Technology News, Reviews and Tutorials</description>
	<lastBuildDate>Fri, 09 Dec 2011 17:47:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>MM_XSLTransform Error</title>
		<link>http://www.techontour.com/applications/2008/10/01/mm_xsltransform-error/</link>
		<comments>http://www.techontour.com/applications/2008/10/01/mm_xsltransform-error/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 15:44:28 +0000</pubDate>
		<dc:creator>Alex Costa</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[quick & easy tips]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://www.techontour.com/applications/2008/10/01/mm_xsltransform-error/</guid>
		<description><![CDATA[MM_XSLTransform error. [RSS URL] is not a valid XML document. &#160;Non-static method DOMDocument::loadXML() should not be called statically, assuming $this from incompatible context in file I recently came across this error and took me a lot of searching to find out the right fix for it. Here is where you can find the fix. http://groups.google.com/group/macromedia.dreamweaver.appdev/browse_thread/thread/832446ccb50569f3 [...]]]></description>
			<content:encoded><![CDATA[<p><b>MM_XSLTransform error. </b><br /> [RSS URL] is not a valid XML document. <br /> &nbsp;Non-static method DOMDocument::loadXML() should not be called statically, <br /> assuming $this from incompatible context in file</p>
<p>I recently came across this error and took me a lot of searching to find out the right fix for it. Here is where you can find the fix. </p>
<p><a target="_blank" href="http://groups.google.com/group/macromedia.dreamweaver.appdev/browse_thread/thread/832446ccb50569f3">http://groups.google.com/group/macromedia.dreamweaver.appdev/browse_thread/thread/832446ccb50569f3</a></p>
<p></p>
<p class="technorati-tags"><a href="http://technorati.com/tag/MM_XSLTransform%20Error" rel="tag">MM_XSLTransform Error</a>, <a href="http://technorati.com/tag/rss%20feed%20error" rel="tag">rss feed error</a>, <a href="http://technorati.com/tag/XSLT" rel="tag">XSLT</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/applications/2008/10/01/mm_xsltransform-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Secure Firewall for OpenVPN</title>
		<link>http://www.techontour.com/programming/2008/09/23/secure-firewall-for-openvpn/</link>
		<comments>http://www.techontour.com/programming/2008/09/23/secure-firewall-for-openvpn/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 16:41:55 +0000</pubDate>
		<dc:creator>Skilla Repok</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[firewall]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[openvpn]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=289</guid>
		<description><![CDATA[Creating a secure firewall is essential for any openvpn configuration. First of all, I&#8217;d strongly recommend grabbing a copy of Linux Firewalls. Its got a great section on iptables, with a look at all the commands available to you as well as an example firewall configuration. I have setup an openVPN which has a configuration [...]]]></description>
			<content:encoded><![CDATA[<p>Creating a <strong>secure firewall</strong> is essential for any <strong>openvpn</strong> configuration.</p>
<p>First of all, I&#8217;d strongly recommend grabbing a copy of <a href="http://www.amazon.com/Linux-Firewalls-Landmark-Robert-Ziegler/dp/0735710996">Linux Firewalls</a>.<br />
Its got a great section on <strong>iptables</strong>, with a look at all the commands available to you<br />
as well as an example firewall configuration.</p>
<p>I have setup an <a href="http://openvpn.net">openVPN</a> which has a configuration where there are three different types of user.</p>
<p>1. <strong>Customers</strong><br />
2. <strong>Suppliers</strong><br />
3. <strong>Support</strong></p>
<p>As far as the VPN knows, these are all the same thing -&gt; <strong>a node on the network</strong>. It is in the <strong>firewall</strong> that I will put my rules to govern who can &#8216;see&#8217; whom.</p>
<p>Customers are grouped into &#8220;Companies&#8221;. Every customer must be able to see every other customer<br />
in their company.</p>
<p>Every supplier node must be able to see every customer that they have supplied a system to.</p>
<p>Every support agent must be able to see every customer.</p>
<p><strong>All other connections should be blocked</strong></p>
<p><strong>Note of Caution</strong><br />
<em>The *only* way to be able to have a chance of doing this kind of configuration is by knowing what each<br />
nodes VPN ip address is, or what group of ip addresses it could be in.<br />
That means that you have to use <a href="http://openvpn.net/index.php/documentation/howto.html#policy">ccd</a> in your sever settings<br />
</em></p>
<p><strong>My Firewall</strong><br />
First, I make sure that ip forwarding is enabled on the server. You can check if it is enabled by typing</p>
<p><code>cat /proc/sys/net/ipv4/ip_forward</code></p>
<p>if it shows 0, it is disabled. <strong>1 means enabled.</strong></p>
<p><code>echo 1 &gt; /proc/sys/net/ipv4/ip_forward</code></p>
<p>forces it to be enabled</p>
<p>Then, I run my firewall rules. First I want to ensure that the default behaviour for any packet is to be dropped</p>
<p><code>iptables --policy FORWARD DROP</code></p>
<p>I want to log anything that is passed between nodes:</p>
<p><code>iptables -A FORWARD -i tun0 -j LOG --log-level 6 --log-prefix 'Forward tun0 Log'</code></p>
<p>Then, for every pair of nodes that I want to see each other I run this command:</p>
<p><code>iptables -A FORWARD -i tun0 -s 10.2.2.5 -d 10.2.2.1 -j ACCEPT</code></p>
<p>That says allow packets to go from 10.2.2.5 to 10.2.2.1. Of course, for that to work, we<br />
also need to allow packets to go the other way.</p>
<p><code>iptables -A FORWARD -i tun0 -s 10.2.2.1 -d 10.2.2.5 -j ACCEPT</code></p>
<p><strong>Another Note Of Caution</strong><br />
<em>In order for the above configuration to work, I push all routes to all nodes in my server.conf file<br />
route 10.0.0.0 255.0.0.0<br />
That means that the firewall is the &#8216;all powerful&#8217; being that can control and change who can see what<br />
at any point in time, without having to touch the vpn configuration.</em></p>
<p><strong>Scripting the firewall</strong><br />
I&#8217;ve written a little python script to ensure that I don&#8217;t make errors when creating my firewall<br />
every time a supplier/customer/support member is added.</p>
<p><strong>Config File</strong></p>
<p>The config file for the script is made up of 3 parts.<br />
1. IP addresses. These map to the ones that you have assigned to each node in the ccd directory<br />
of your server.conf setup.<br />
2. PermissionGroups. These are groups of the ipaddresses useful for setting permissions<br />
3. Permissions. These are the permissions that are setup for the firewall rules to fire against.</p>
<p><code>#config.py<br />
#IP_ADDRESSES - create an ip address for each node in the vpn.</code></p>
<p><code>IP_OPEN_VPN_SERVER = "10.8.0.1" #not really needed, for reference only</code></p>
<p><code>#CompanyA<br />
COMPANYA_CUSTOMER1 = "10.2.1.1"<br />
COMPANYA_CUSTOMER2 = "10.2.1.5"<br />
COMPANYA_CUSTOMER3 = "10.2.1.9"</code></p>
<p><code>GRP_COMPANY_A = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3]</code></p>
<p><code>#CompanyB<br />
COMPANYB_CUSTOMER1 = "10.2.2.1"<br />
COMPANYB_CUSTOMER2 = "10.2.2.5"<br />
COMPANYB_CUSTOMER3 = "10.2.2.9"</code></p>
<p><code>GRP_COMPANY_B = [COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]</code></p>
<p><code>#SUPPLIERS<br />
SUPPLIER1 = "10.3.1.1"<br />
SUPPLIER2 = "10.3.1.5"</code></p>
<p><code>#SUPPORT PEOPLE<br />
SUPPORT1 = "10.1.1.1"<br />
SUPPORT2 = "10.1.1.5"<br />
SUPPORT3=  "10.1.1.9"</code></p>
<p><code>GRP_SUPPORT = [SUPPORT1, SUPPORT2, SUPPORT3]</code></p>
<p><code>#PERMISSION GROUPS</code></p>
<p><code>#Who should support be able to see<br />
PERM_SUPPORT = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3,<br />
COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]</code></p>
<p><code>PERM_COMPANY_A = [COMPANYA_CUSTOMER1, COMPANYA_CUSTOMER2, COMPANYA_CUSTOMER3]</code></p>
<p><code>PERM_COMPANY_B = [COMPANYB_CUSTOMER1, COMPANYB_CUSTOMER2, COMPANYB_CUSTOMER3]</code></p>
<p><code>PERM_SUPPLIER1 = PERM_COMPANY_A</code></p>
<p><code>PERM_SUPPLIER2 = PERM_COMPANY_B</code></p>
<p><code>#Permissions is a dictionary of 'this ip should be able to communicate with': [these ips]<br />
#as a result, a path is created between each key and every ip in the values<br />
PERMISSION_GROUPS = {GRP_SUPPORT: PERM_SUPPORT,<br />
GRP_COMPANY_B:PERM_COMPANY_B,<br />
GRP_COMPANY_A:PERM_COMPANY_A,<br />
[SUPPLIER1]: PERM_SUPPLIER1,<br />
[SUPPLIER2]: PERM_SUPPLIER2}</code></p>
<p><code>PERMISSIONS = {}<br />
for group, permissions in PERMISSION_GROUPS.iteritems():<br />
for ipaddress in group:<br />
PERMISSIONS[ipaddress] = permissions</code></p>
<p><strong>Firewall Script</strong><br />
Now here&#8217;s the firewall script that will turn your config file into a living, breathing firewall.</p>
<p><code>#autoConfigure.py<br />
""This module deals with the ip rules for the customers, suppliers and support over the VPN!"""</code></p>
<p><code>from config import PERMISSIONS<br />
import os</code></p>
<p><code>class SomethingWentWrongException(Exception):pass</code></p>
<p><code>def runFireWallRule(rule):<br />
ans = os.system(rule)<br />
if ans==0:<br />
return True<br />
else:<br />
raise SomethingWentWrongException</code></p>
<p><code>def resetFireWall():<br />
runFireWallRule("iptables -F")</code></p>
<p><code>def loadFireWall(logging=True):<br />
#allow port forwarding<br />
runFireWallRule("echo 1 &gt; /proc/sys/net/ipv4/ip_forward")<br />
runFireWallRule("iptables --policy FORWARD DROP")<br />
if logging:<br />
runFireWallRule("iptables -A FORWARD -i tun0 -j LOG --log-level 6 --log-prefix 'Forward tun0 Log'")<br />
for rootIP, destinations in PERMISSIONS.items():<br />
"""creates routed from the rootIP to destinationIP and back again"""<br />
for destination in destinations:<br />
if rootIP!=destination:<br />
runFireWallRule("iptables -A FORWARD -i tun0 -s %s -d %s -j ACCEPT"%(rootIP, destination))<br />
runFireWallRule("iptables -A FORWARD -i tun0 -s %s -d %s -j ACCEPT"%(destination, rootIP))</code></p>
<p><code>if __name__=='__main__':<br />
resetFireWall()<br />
loadFireWall()</code></p>
<p>Try running the autoconfigure.py file, as root, and see what the output is of iptables -L</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/programming/2008/09/23/secure-firewall-for-openvpn/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wxpython Segmentation Fault</title>
		<link>http://www.techontour.com/programming/2008/09/19/wxpython-segmentation-fault/</link>
		<comments>http://www.techontour.com/programming/2008/09/19/wxpython-segmentation-fault/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 19:04:04 +0000</pubDate>
		<dc:creator>Skilla Repok</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=285</guid>
		<description><![CDATA[In some of my wx python apps, I have come across this error. It usually appears like this on the command line Segmentation Fault (core dumped) The most common reason for me getting this error, has been when a non-main thread tries to directly manipulate something in wx. Be it to Hide() a window, or [...]]]></description>
			<content:encoded><![CDATA[<p>In some of my wx python apps, I have come across this error.<br />
It usually appears like this on the command line</p>
<p><strong>Segmentation Fault (core dumped)</strong></p>
<p>The most common reason for me getting this error, has been when a non-main thread tries to directly manipulate something in wx. Be it to Hide() a window, or ShowModal() a dialog.</p>
<p>The way to get round this (and actually, the way to use wx correctly, so I&#8217;m told), is to use the event handlers to pass messages back from your sub-processes to the wx event loop.</p>
<p>To create your own event class you can do this:</p>
<p><code>#First we'll define a new event type<br />
wxEVT_THREAD_COM = wx.NewEventType()</code></p>
<p><code>#Now you can define your own event<br />
class ThreadEvent(wx.PyEvent):<br />
def __init__(self, id, data=None):<br />
wx.PyEvent.__init__(self)<br />
self.SetEventType(wxEVT_THREAD_COM)<br />
self.data = data<br />
self.id = id</code></p>
<p>Once you&#8217;ve done that, you can create an event handler in the frame you want to pass the event to.</p>
<p><code><br />
#now we'll create a handler in our main frame class<br />
class MainFrame(wx.Frame):<br />
def __init__(self):<br />
wx.Frame.__init__(....)<br />
self.Connect(-1, -1, wxEVT_THREAD_COM, self.OnThreadCommunicationEvent)</code></p>
<p><code>def OnThreadCommunicationEvent(self, event):<br />
#handle the event here<br />
if event.id==CLOSE:<br />
self.Close()<br />
elif event.id==HIDE:<br />
self.Hide()<br />
event.Skip()</code></p>
<p>To pass launch an event, you just need to get the event handler for the wx object, and then add the event!</p>
<p><code>#assuming MAIN_FRAME is a reference to the MAIN_FRAME in a foreign thread<br />
myThreadEvent = ThreadEvent(CLOSE)<br />
MAIN_FRAME.GetEventHandler().AddPendingEvent(myThreadEvent)<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/programming/2008/09/19/wxpython-segmentation-fault/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Part 3: Setting up the schedule</title>
		<link>http://www.techontour.com/programming/2008/09/17/part-3-setting-up-the-schedule/</link>
		<comments>http://www.techontour.com/programming/2008/09/17/part-3-setting-up-the-schedule/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 17:20:39 +0000</pubDate>
		<dc:creator>Skilla Repok</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=275</guid>
		<description><![CDATA[Part3: Setting up the schedule So you&#8217;ve got the python screen capturer and emailer sorted. Now all we need to do is combine the two and set up a process to perform on a regular basis. 1. ScreenMailer First, we&#8217;ll combine the two. When this module is run, it should grab a screen image and [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Part3: Setting up the schedule</strong></p>
<p>So you&#8217;ve got the <strong>python screen capturer</strong> and <strong>emailer</strong> sorted. Now all we need to do is combine the two and set up a process to perform on a regular basis.</p>
<p><strong>1. ScreenMailer</strong></p>
<p>First, we&#8217;ll combine the two. When this module is run, it should grab a screen image and send it as is to an email address.</p>
<p>You&#8217;ll need to edit a few things. First of all, change the imageName to be in a folder that you don&#8217;t mind storing some images.<br />
In my example, I&#8217;ve stored it in /tmp (on linux).</p>
<p>The other thing you&#8217;ll want to change is your user details.<br />
a) change <strong>myEmail</strong> to be your email address<br />
b) change <strong>userdetails.destination</strong> to be the destination email address (this can be the same thing!)<br />
c) change <strong>userdetails.username</strong> and <strong>username.password</strong> to have your correct values.<br />
d) if you are not using gmail, find the smtp server address and enter it in serverAddr</p>
<blockquote><p>#screenMailer.py<br />
import time<br />
import emailer<br />
import screen</p></blockquote>
<blockquote><p>def grabScreenAndSend():</p></blockquote>
<blockquote><p>imageName = &#8216;/tmp/images/image%s.gif&#8217;%int(time.time())</p></blockquote>
<blockquote><p>screen.grabScreen(imageName)</p></blockquote>
<blockquote><p>myEmail = &#8216;xyz@gmail.com&#8217;<br />
serverAddr = &#8216;smtp.gmail.com&#8217;<br />
destination = userdetails.destination<br />
timeNow = time.strftime(&#8220;%H:%M&#8221;, time.localtime())<br />
dayNow = time.strftime(&#8220;%a, %d %b %Y&#8221;, time.localtime())</p></blockquote>
<blockquote><p>emailer.sendEmail(destination, myEmail, &#8216;My Screen %s&#8217;%dayNow,<br />
&#8217;2 Minute Interval Screen Shot, taken at %s. this is just for the filter&#8217;%timeNow, serverAddr,<br />
userdetails.username, userdetails.password, [imageName])</p></blockquote>
<blockquote><p>if __name__==&#8217;__main__&#8217;:<br />
grabScreenAndSend()</p></blockquote>
<p><strong>2. Setting up the scheduler:</strong><br />
a) On linux type crontab -e to edit<br />
add this line</p>
<blockquote><p>*/2 * * * * python2.4 address_to_your_screen_mailer/screenMailer.py</p></blockquote>
<p>That will launch the screenMailer every 2 minutes of every day. If you just want the hourly report rather than every two minutes, change the screenMailer.py file so that it does not send the picture. You&#8217;ll still need it to run in order to get the hourly report to work</p>
<p>b) on windows use the scheduler, I&#8217;ll find out how to do this and edit later on!</p>
<p><strong>3. The hourly summary.</strong></p>
<p>In order to send an hourly summary, we need to create our hourlyScreenSummary.py file.<br />
It takes all of the images found in the folder given and creates a collage and then sends that.<br />
You&#8217;ll need to make some more changes for your configuration here.<br />
a) change the OUT_FILE to an appropriate location. this file will get deleted after each run.<br />
b) change the FOLDER to be the same as you set before, where all of the 2 minute pictures were saved<br />
c) change myEmail to be your email address<br />
d) change userdetails.destination to be the destination email address (this can be the same thing!)<br />
e) change userdetails.username and username.password to have your correct values.<br />
f) if you are not using gmail, find the smtp server address and enter it in serverAddr</p>
<blockquote><p>#hourlyScreenSummary.py<br />
import screenMailer<br />
import emailer<br />
import time<br />
import os<br />
import extras<br />
from config import launchCommand</p></blockquote>
<blockquote><p>#combines the whole contents of a specific folder and sends it as one image</p></blockquote>
<blockquote><p>OUT_FILE = &#8216;/tmp/montage.gif&#8217;<br />
FOLDER = &#8216;/tmp/images&#8217;</p></blockquote>
<blockquote><p>def createMontage(folderaddr):<br />
if platform.system()==&#8217;Windows&#8217; or platform.system()==&#8217;Microsoft&#8217;:<br />
createPILMontage(folderaddr)<br />
else:<br />
createLinuxMontage(folderaddr)</p></blockquote>
<blockquote><p>def createLinuxMontage(folderaddr):<br />
files=[]<br />
for filename in os.listdir(folderaddr):<br />
files.append(&#8216;%s/%s&#8217;%(folderaddr, filename))</p></blockquote>
<blockquote><p>filestring = &#8216; &#8216;.join(files)</p></blockquote>
<blockquote><p>launchCommand(&#8216;montage %s -geometry +2-2 %s&#8217;%(filestring, OUT_FILE))</p></blockquote>
<blockquote><p>def createPILMontage(folderaddr):<br />
import extras<br />
files=[]<br />
for filename in os.listdir(folderaddr):<br />
files.append(&#8216;%s/%s&#8217;%(folderaddr, filename))<br />
if len(files):<br />
nocols = 5<br />
norows = int(len(files)/5)+1<br />
newFile = extras.make_contact_sheet(files,(ncols,nrows),(160,100),<br />
(0,0,0,0),2)<br />
newFile.save(OUT_FILE)<br />
def removeImageFiles(folderaddr):<br />
files = []<br />
for filename in os.listdir(folderaddr):<br />
os.remove(&#8216;%s/%s&#8217;%(folderaddr, filename))</p>
<p>def createAndSendHourlyScreenSummary():<br />
&#8220;&#8221;"create and send an hourly screen summary&#8221;"&#8221;<br />
createMontage(FOLDER)<br />
timeNow = time.strftime(&#8220;%H:%M&#8221;, time.localtime())<br />
dayNow = time.strftime(&#8220;%a, %d %b %Y&#8221;, time.localtime())</p>
<p>myEmail = &#8216;xyz@gmail.com&#8217;<br />
destination = userdetails.destination<br />
serverAddr = &#8216;smtp.gmail.com&#8217;<br />
emailer.sendEmail(destination, myEmail, &#8216;My Hourly Screen %s&#8217;%dayNow,<br />
&#8216;Hourly Screen Summary, taken at %s this is just for the filter&#8217;%timeNow, serverAddr,<br />
userdetails.username, userdetails.password, [OUT_FILE])<br />
#now remove the contents of that file<br />
removeImageFiles(FOLDER)</p>
<p>if __name__==&#8217;__main__&#8217;:<br />
createAndSendHourlyScreenSummary()</p></blockquote>
<p>4. Add to crontab again<br />
You&#8217;ll now need to add this to crontab aswell. Add the following line after typing crontab -e at the command line:</p>
<blockquote><p>1 * * * * python2.4 (path to hourlyScreenSummary)/hourlyScreenSummary.py</p></blockquote>
<p>This will send the hourly montage to the address that you have hard coded every hour.</p>
<p>5. And finally<br />
There is one more module that you will need. I found this from http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/v/vi/vidag/montager and have editted it slightly<br />
This module is for the windows version only and is used to create a sheet of screen shots.</p>
<blockquote><p>#extras.py<br />
import Image</p>
<p>def make_contact_sheet(fnames,(ncols,nrows),(photow,photoh),<br />
(marl,mart,marr,marb),<br />
padding):<br />
&#8220;&#8221;"\<br />
Make a contact sheet from a group of filenames:</p>
<p>fnames       A list of names of the image files</p>
<p>ncols        Number of columns in the contact sheet<br />
nrows        Number of rows in the contact sheet<br />
photow       The width of the photo thumbs in pixels<br />
photoh       The height of the photo thumbs in pixels</p>
<p>marl         The left margin in pixels<br />
mart         The top margin in pixels<br />
marr         The right margin in pixels<br />
marl         The left margin in pixels</p>
<p>padding      The padding between images in pixels</p>
<p>returns a PIL image object.<br />
&#8220;&#8221;"</p>
<p># Read in all images and resize appropriately<br />
imgs = [Image.open(fn).resize((photow,photoh)) for fn in fnames]</p>
<p># Calculate the size of the output image, based on the<br />
#  photo thumb sizes, margins, and padding<br />
marw = marl+marr<br />
marh = mart+ marb</p>
<p>padw = (ncols-1)*padding<br />
padh = (nrows-1)*padding<br />
isize = (ncols*photow+marw+padw,nrows*photoh+marh+padh)</p>
<p># Create the new image. The background doesn&#8217;t have to be white<br />
white = (255,255,255)<br />
inew = Image.new(&#8216;RGB&#8217;,isize,white)</p>
<p># Insert each thumb:<br />
for irow in range(nrows):<br />
for icol in range(ncols):<br />
left = marl + icol*(photow+padding)<br />
right = left + photow<br />
upper = mart + irow*(photoh+padding)<br />
lower = upper + photoh<br />
bbox = (left,upper,right,lower)<br />
try:<br />
img = imgs.pop(0)<br />
except:<br />
break<br />
inew.paste(img,bbox)<br />
return inew</p></blockquote>
<p><strong>6. Finished</strong></p>
<p>You are finished! You should be able to produce and send images of your desktop to be viewed in your inbox!</p>
<p><a href="http://www.techontour.com/programming/2008/09/17/linux-windows-usage-surveillance-in-python">Part 1: Python Screen Capture</a><br />
<a href="http://www.techontour.com/programming/2008/09/17/part-2-python-emailer">Part 2: Python Emailer</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/programming/2008/09/17/part-3-setting-up-the-schedule/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Part 2: Python Emailer</title>
		<link>http://www.techontour.com/programming/2008/09/17/part-2-python-emailer/</link>
		<comments>http://www.techontour.com/programming/2008/09/17/part-2-python-emailer/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 17:20:28 +0000</pubDate>
		<dc:creator>Skilla Repok</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=274</guid>
		<description><![CDATA[Part 2: Python Emailer If you want to send emails using python&#8217;s smtplib, this is a good example. The method sendMail takes 8 arguments and is able to send attached emails to an address. Currently, this is only tested using my gmail account as the sender, but it should work elsewhere. #emailer.py import os.path import [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Part 2: Python Emailer</strong></p>
<p>If you want to send emails using python&#8217;s <strong>smtplib</strong>, this is a good example.<br />
The method sendMail takes 8 arguments and is able to send attached emails to an address.<br />
Currently, this is only tested using my <strong>gmail account</strong> as the sender, but it should work elsewhere.</p>
<blockquote><p>#emailer.py<br />
import os.path<br />
import sys, smtplib, MimeWriter, base64, StringIO<br />
import smtplib<br />
import mimetypes<br />
from email.Encoders import encode_base64<br />
from email.MIMEAudio import MIMEAudio<br />
from email.MIMEBase import MIMEBase<br />
from email.MIMEImage import MIMEImage<br />
from email.MIMEMultipart import MIMEMultipart<br />
from email.MIMEText import MIMEText</p>
<p>def getAttachment(path, filename):<br />
&#8220;&#8221;"Returns the attachment as a MIME formatted object&#8221;"&#8221;<br />
ctype, encoding = mimetypes.guess_type(path)<br />
if ctype is None or encoding is not None:<br />
ctype = &#8216;application/octet-stream&#8217;<br />
maintype, subtype = ctype.split(&#8216;/&#8217;, 1)<br />
fp = open(path, &#8216;rb&#8217;)<br />
if maintype == &#8216;text&#8217;:<br />
attach = MIMEText(fp.read(),_subtype=subtype)<br />
elif maintype == &#8216;message&#8217;:<br />
attach = email.message_from_file(fp)<br />
elif maintype == &#8216;image&#8217;:<br />
attach = MIMEImage(fp.read(),_subtype=subtype)<br />
elif maintype == &#8216;audio&#8217;:<br />
attach = MIMEAudio(fp.read(),_subtype=subtype)<br />
else:<br />
print maintype, subtype<br />
attach = MIMEBase(maintype, subtype)<br />
attach.set_payload(fp.read())<br />
encode_base64(attach)<br />
fp.close<br />
attach.add_header(&#8216;Content-Disposition&#8217;, &#8216;attachment&#8217;,<br />
filename=filename)<br />
return attach</p>
<p>def getTotalMessage(toAddr, fromAddr, subject, msg, attachmentFileNames):<br />
&#8220;&#8221;"given a to address, from address, subject, msg and any attachments, returns<br />
a message ready to be sent&#8221;"&#8221;<br />
mymsg = MIMEMultipart()<br />
mymsg['From'] = fromAddr<br />
mymsg['To'] = toAddr<br />
mymsg['Subject'] = subject<br />
mymsg.attach(MIMEText(msg))<br />
for path in attachmentFileNames:<br />
filename = path.split(&#8216;/&#8217;)[-1]<br />
print &#8216;getAttachment&#8217;, path, filename<br />
attach = getAttachment(path, filename)<br />
mymsg.attach(attach)<br />
return mymsg.as_string()</p>
<p>def sendEmail(toAddr, fromAddr, subject, msg, serverAddr,<br />
username, password, attachmentFileNames=[]):<br />
&#8220;&#8221;"This is the function to run when sending an email: Designed for gmail,<br />
may work elsewhere&#8221;"&#8221;<br />
msg = getTotalMessage(toAddr, fromAddr, subject, msg, attachmentFileNames)</p>
<p>server = smtplib.SMTP(serverAddr)<br />
server.ehlo(&#8221;)<br />
server.starttls()<br />
server.ehlo(&#8221;)<br />
server.login(username, password)<br />
server.sendmail(fromAddr, toAddr, msg)<br />
server.quit()</p></blockquote>
<p><a href="http://www.techontour.com/programming/2008/09/17/linux-windows-usage-surveillance-in-python">Part 1: Python Screen Capture</a><br />
<a href="http://www.techontour.com/programming/2008/09/17/part-3-setting-up-the-schedule/">Part 3: Setting up the schedule</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/programming/2008/09/17/part-2-python-emailer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux Windows Usage Surveillance in Python</title>
		<link>http://www.techontour.com/programming/2008/09/17/linux-windows-usage-surveillance-in-python/</link>
		<comments>http://www.techontour.com/programming/2008/09/17/linux-windows-usage-surveillance-in-python/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 17:20:14 +0000</pubDate>
		<dc:creator>Skilla Repok</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=272</guid>
		<description><![CDATA[Lets say you want to keep track of a computers usage, for remote working. It should deliver hourly shots of computer usage to an email address that you&#8217;ll give it. It will also deliver screen shots every 2 minutes, but you can choose whether it does that or not! Part 1: Python Screen Capture Part [...]]]></description>
			<content:encoded><![CDATA[<p>Lets say you want to keep track of a computers usage, for remote working. It should deliver hourly shots of computer usage to an email address that you&#8217;ll give it. It will also deliver screen shots every 2 minutes, but you can choose whether it does that or not!</p>
<p>Part 1: Python Screen Capture<br />
<a href="http://www.techontour.com/programming/2008/09/17/part-2-python-emailer">Part 2: Python Emailer</a><br />
<a href="http://www.techontour.com/programming/2008/09/17/part-3-setting-up-the-schedule/">Part 3: Setting up the schedule</a></p>
<p><strong>Part 1: Python Screen Capture</strong></p>
<p>Requirements:</p>
<ul>
<li>Python2.4 or greater</li>
<li>Windows or Linux based OS</li>
<li>On Windows, you&#8217;ll need to get Python Image Library</li>
<li>On Linux, you&#8217;ll need to have mogrify, which comes as part of ImageMagick.</li>
</ul>
<p>If you don&#8217;t have it use your package manager to get it.</p>
<blockquote><p>sudo apt-get install imagemagick</p></blockquote>
<p>The screen module:</p>
<blockquote><p>#screen.py<br />
import os<br />
import platform<br />
import shutil<br />
from config import launchCommand</p>
<p>def printScreen(filename):<br />
&#8220;&#8221;"prints the screen and saves it as the filename given&#8221;"&#8221;<br />
if platform.system()==&#8217;Windows&#8217; or platform.system()==&#8217;Microsoft&#8217;:<br />
import ImageGrab<br />
img = ImageGrab.grab()<br />
img.save(filename)<br />
else:<br />
launchCommand(&#8216;/usr/bin/xwd -display :0 -root -out %s&#8217;%filename)</p>
<p>def convertImage(filename, width=160, height=100):<br />
&#8220;&#8221;"Converts the image found in filename to one of the dimensions given. returns a gif filename&#8221;"&#8221;<br />
if platform.system()==&#8217;Windows&#8217; or platform.system()==&#8217;Microsoft&#8217;:<br />
import Image<br />
im1 = Image.open(filename)<br />
im2 = im1.resize((width, height), Image.NEAREST)<br />
im2.save(&#8216;%s.gif&#8217;%filename)<br />
else:<br />
#320&#215;200<br />
launchCommand(&#8216;/usr/bin/mogrify -format gif -resize %sx%s %s&#8217;%(width, height, filename))<br />
return &#8216;%s.gif&#8217;%filename</p>
<p>def removeImage(filename):<br />
&#8220;&#8221;"removes the imagename given&#8221;"&#8221;<br />
os.remove(filename)</p>
<p>def copyFile(source,destination):<br />
&#8220;&#8221;"copys a file from source to destination&#8221;"&#8221;<br />
shutil.copyfile(source, destination)</p>
<p>def grabScreen(filename, width=160, height=100):<br />
&#8220;&#8221;"given a filename, width and height, grabs a screen shot of the current desktop,<br />
scales it to the sizes passed in (default 160&#215;100) and saves it to the filename given&#8221;"&#8221;<br />
tmpName = &#8216;tmp_image&#8217;<br />
printScreen(tmpName)<br />
imageName = convertImage(tmpName)<br />
copyFile(imageName, filename)<br />
removeImage(tmpName)<br />
removeImage(imageName)</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/programming/2008/09/17/linux-windows-usage-surveillance-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Smultron vs Coda</title>
		<link>http://www.techontour.com/applications/2008/09/01/smultron-vs-coda/</link>
		<comments>http://www.techontour.com/applications/2008/09/01/smultron-vs-coda/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 23:48:51 +0000</pubDate>
		<dc:creator>nickv</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[coda]]></category>
		<category><![CDATA[cssedit]]></category>
		<category><![CDATA[cyberduck]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[mediatemple]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[panic]]></category>
		<category><![CDATA[sftp]]></category>
		<category><![CDATA[smultron]]></category>
		<category><![CDATA[textmate]]></category>
		<category><![CDATA[textwrangler]]></category>
		<category><![CDATA[web workflow]]></category>

		<guid isPermaLink="false">http://www.techontour.com/?p=240</guid>
		<description><![CDATA[Web Workflow All web developers seem to have a slightly different workflow. Last week I set out on a journey to increase my web development productivity. I&#8217;m currently using OS X Leopard 10.5.4 on a iMac 2.1GHz G5. Coda &#8216;Coda&#8216;, made by panic, is a ftp+text editor all in one. At first glance it appeared [...]]]></description>
			<content:encoded><![CDATA[<h2><span style="underline;">Web Workflow</span></h2>
<p>All web developers seem to have a slightly different workflow. Last week I set out on a journey to increase my web development productivity. I&#8217;m currently using OS X Leopard 10.5.4 on a iMac 2.1GHz G5.</p>
<h2><span style="underline;">Coda</span></h2>
<p><img style="5px;" src="http://www.panic.com/coda/img/screenshots/sites-screenshot_03.jpg" alt="Coda Screenshot" hspace="5" width="319" height="305" align="right" />&#8216;<a title="Coda by Panic" href="http://www.panic.com/coda/" target="_blank">Coda</a>&#8216;, made by panic, is a ftp+text editor all in one. At first glance it appeared to be everything that I needed. It includes a built ftp client, css editor, subversion, <a href="http://www.codingmonkeys.de/subethaengine/" target="_new">Subetha Engine</a> (which allows multiple people to edit a file collaboratively), and of course the editor. So I downloaded the 2 week trial and much to my surprise I was very impressed. The user interface is very nice and intuitive. New windows are opened up in tabs along the top (which I like but know others who hate that). Like most of these programs your remote/local file structure appears on the left side and the editor on the right. I got used to it very quickly. In fact my trial ran out 2 days ago and I have been struggling without it. The only downside is the $79 price tag, which is not a whole lot if this is what you do all day. I am a huge fan of open source, so I ventured off to find a free alternative. This is when I stumbled across the <a title="Smultron by Peter Borg" href="http://smultron.sourceforge.net/" target="_blank">Smultron</a> + <a title="Cyberduck" href="http://cyberduck.ch/" target="_self">Cyberduck</a> marriage.</p>
<p>Note: If you&#8217;ve been trying to use coda with a mediatemple server and having problems with files not saving, make sure you&#8217;re using sftp. I&#8217;m not sure why this makes a difference but it it did for me. Files should upload quickly once you switch it over.</p>
<h4>Coda Pros:</h4>
<ul>
<li>Well designed interface</li>
<li>Very intuitive</li>
<li>ftp built in</li>
<li>Collaborative editing of files</li>
</ul>
<h4>Coda Cons:</h4>
<ul>
<li>High price tag</li>
<li>Not as feature rich as something like &#8216;<a title="Textmate" href="http://macromates.com/" target="_blank">Textmate</a>&#8216; for in depth web development</li>
</ul>
<h2><span style="underline;">Smultron + Cyberduck</span></h2>
<p><img style="5px;" src="http://www.nickandsarajane.com/images/smultron.jpg" alt="Smultron Screenshot" hspace="5" width="320" height="327" align="left" /><a title="Smultron by Peter Borg" href="http://smultron.sourceforge.net/" target="_blank">Smultron</a>, made by Peter Borg, is a very simple but well designed text editor. It doesn&#8217;t have built in ftp so you will still need to use <a title="Cyberduck" href="http://cyberduck.ch/" target="_blank">Cyberduck</a>. I&#8217;m assuming most of you reading this will be well aware of Cyberduck, the free open source ftp client. Smultron fully integrates with Cyberduck allowing one click editing of any of your remote files from Cyberduck. Just use Cmd+s to save and your files are uploaded straight to your server. These two programs behave similar to Coda in this sense. The only downside being that you will have to use two programs to accomplish the same task. Smultron is a fairly basic editor and definitely doesn&#8217;t have some of the bells and whistles Coda has, but for the average coder it will do just fine. Remember this is the free solution so if your willing to  put up with this you can pocket that $79 and take your wife/girlfriend out for dinner.</p>
<h4>Smultron Cyberduck Pros:</h4>
<ul>
<li>Free</li>
<li>Open Source</li>
<li>Easy to use</li>
<li>Does what its supposed to best, edit text</li>
</ul>
<h4>Sumltron Cyberduck Cons:</h4>
<ul>
<li>File structure does not appear within Smultron</li>
<li>Cyberduck is prone to crashing (at least on my computer)</li>
</ul>
<h2><span style="underline;">Conclusion</span></h2>
<p>Well I&#8217;ve been fairly even with both sides at the moment. I&#8217;d have to say that if money wasn&#8217;t an issue I would definitely go with Coda. It&#8217;s ease of use and the fact that it&#8217;s an all in one package is very attractive. I like seeing my file structure along the left hand side, something that Smultron lacks (you have to go to Cyberduck to see this). Having said that I will continue to use my Smultron Cyberduck combo until I can convince my wife to skip a date night and put the money towards Coda.</p>
<p>What does your workflow look like? Let me know if you have better solutions. I would love to hear from people who have used <a title="Textmate" href="http://macromates.com/" target="_blank">Textmate</a>, <a title="CSSedit from MacRabbit" href="http://macrabbit.com/cssedit/" target="_blank">CSSedit</a>, <a title="TextWrangler" href="http://www.barebones.com/products/textwrangler/" target="_blank">TextWrangler</a>, or any other OS X friendly text editors or ftp clients.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/applications/2008/09/01/smultron-vs-coda/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>SugarCRM installation error &#8220;MySQL not available&#8221;</title>
		<link>http://www.techontour.com/os-servers/2008/04/22/sugarcrm-installation-error-mysql-not-available/</link>
		<comments>http://www.techontour.com/os-servers/2008/04/22/sugarcrm-installation-error-mysql-not-available/#comments</comments>
		<pubDate>Tue, 22 Apr 2008 21:58:25 +0000</pubDate>
		<dc:creator>Alex Costa</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[OS & Servers]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[quick & easy tips]]></category>

		<guid isPermaLink="false">http://www.techontour.com/os-servers/2008/04/22/sugarcrm-installation-error-mysql-not-available/</guid>
		<description><![CDATA[While moving a SugarCRM installation to a different server I found this problem &#8211; &#8220;MySQL not available&#8221;. Firstly I had a blank page and then decide to re-run the installation script. During the system check it listed MySQL as not available, so I checked for the status of the mysql server and it was running. [...]]]></description>
			<content:encoded><![CDATA[<p>While moving a <a href="http://sugarcrm.org" target="_blank"><strong>SugarCRM installation</strong></a> to a different server I found this problem &#8211; <strong>&#8220;MySQL not available&#8221;</strong>. Firstly I had a blank page and then decide to re-run the installation script. During the system check it listed MySQL as not available, so I checked for the status of the mysql server and it was running. (as root &#8211; <strong>/etc/init.d/mysql status</strong>)</p>
<p>This problem is caused by PHP not being able to talk to the MySQL server. Here are some simple steps that can help you resolve this.</p>
<p>1 &#8211; add the line <strong>extension=mysql.so</strong> to the end of your <strong>php.ini </strong>( found under <strong>/etc/php5/apache2</strong>)</p>
<p>2 -<strong> restart the apache server &#8211; /etc/init.d/apache2 restart<br />
</strong><br />
This should resolve your problem but if it does not, like in my case, the php-mysql extension is missing so you need to install it.</p>
<p>3 &#8211; in a Debian based distro (Like Ubuntu) just use <strong>apt-get install php-mysql</strong> to install it (as root or use sudo before the command)</p>
<p>4 &#8211; <strong>restart the apache server &#8211; /etc/init.d/apache2 restart</strong></p>
<p>This is it!  <img src='http://www.techontour.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Technorati Tags: <a href="http://technorati.com/tag/sugarcrm" class="performancingtags" rel="tag">SugarCRM</a>, <a href="http://technorati.com/tag/MySQL%20error" class="performancingtags" rel="tag">MySQL Error</a>, <a href="http://technorati.com/tag/php-mysql" class="performancingtags" rel="tag">php-mysql</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/os-servers/2008/04/22/sugarcrm-installation-error-mysql-not-available/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Internet Explorer 8 Beta</title>
		<link>http://www.techontour.com/applications/2008/03/16/internet-explorer-8-beta/</link>
		<comments>http://www.techontour.com/applications/2008/03/16/internet-explorer-8-beta/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 00:02:34 +0000</pubDate>
		<dc:creator>Alex Costa</dc:creator>
				<category><![CDATA[Applications]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Web Browsers]]></category>

		<guid isPermaLink="false">http://www.techontour.com/applications/2008/03/16/internet-explorer-8-beta/</guid>
		<description><![CDATA[IE8 Beta has been released specially for developers and web programmers. It comes with some interesting features: * IE7 Emulation * Developer Tools for debugging, with similar functionality to the Firefox Ad on  (mentioned just as a reference not as a comparison). *  IE8 activities - Providing quick access to external services from any webpage by sending information from the page to another application or fetching external information related [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a HREF="http://www.microsoft.com/windows/products/winfamily/ie/ie8/default.mspx" TARGET="_blank" TITLE="Download IE8">IE8 Beta</a></strong> has been released specially for developers and web programmers. It comes with some interesting features:</p>
<p>* IE7 Emulation</p>
<p>* Developer Tools for debugging, with similar functionality to the Firefox Ad on  (mentioned just as a reference not as a comparison).</p>
<p>*  <strong><a HREF="http://www.microsoft.com/windows/products/winfamily/ie/ie8/features.mspx">IE8 activities</a></strong> - Providing quick access to external services from any webpage by sending information from the page to another application or fetching external information related to data on the current page.</p>
<p>* <a HREF="http://www.microsoft.com/windows/products/winfamily/ie/ie8/webslices.mspx" TARGET="_blank"><strong>IE8 Webslices</strong></a> - you can slice a piece of a Webslices enable site to receive it&#8217;s updates, very much like you would subscribe to an rss feed. Partners already enabled are Facebook, eBay, MSN and StambleUpon</p>
<p>* CSS 2.1 compliant and HTML parsing improvement (claimed)</p>
<p>* Import &#8221;Favourites&#8221; from other browsers</p>
<p>* Improved Phishing Filtre</p>
<p>*<strong><a HREF="http://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=ie8whitepapers&amp;ReleaseId=582" TARGET="_blank" TITLE="ACR"> Automatic Crash Recovery (ACR)</a></strong> - recovers tabs and minimizes the interruption of sessions in the likely event of a browser crash.</p>
<p>* Faster startup</p>
<p>Unfortunately it still has the annoying &#8221;Navigation Blocked&#8221; page when there&#8217;s a question about a secure certificate on a URL, that can confuse a lot of people eg. http://google.com/adsense on IE will give you this page.</p>
<p>Technorati Tags: <a REL="tag" HREF="http://www.technorati.com/tag/internet explorer">internet explorer</a>, <a REL="tag" HREF="http://www.technorati.com/tag/browser">browser</a>, <a REL="tag" HREF="http://www.technorati.com/tag/microsoft">microsoft</a>, <a REL="tag" HREF="http://www.technorati.com/tag/web programming">web programming</a>, <a REL="tag" HREF="http://www.technorati.com/tag/beta software">beta software</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/applications/2008/03/16/internet-explorer-8-beta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress get_excerpt &#8211; show more words</title>
		<link>http://www.techontour.com/web-design/2008/01/03/wordpress-get_excerpt-show-more-words/</link>
		<comments>http://www.techontour.com/web-design/2008/01/03/wordpress-get_excerpt-show-more-words/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 15:07:41 +0000</pubDate>
		<dc:creator>Alex Costa</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[quick & easy tips]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://www.techontour.com/web-design/2008/01/03/wordpress-get_excerpt-show-more-words/</guid>
		<description><![CDATA[the get_excerpt function on WordPress shows the first 55 words of your post, striped out of any special formatting eg: links, bold, etc.  I wanted to change it for a blog I was developing so I traced it back to the function wp_trim_excerpt in the file \wp-includes\formatting.php. In this file you can change the value [...]]]></description>
			<content:encoded><![CDATA[<p>the <a href="http://www.google.com/custom?domains=techontour.com&amp;q=Wordpress+get_excerpt&amp;sa=Google+Search&amp;sitesearch=&amp;client=pub-8040660565830209" target="_blank"><strong>get_excerpt</strong></a> function on <a href="http://www.google.com/custom?hl=en&amp;safe=active&amp;q=Wordpress&amp;client=pub-8040660565830209"><strong>WordPress</strong></a> shows the first 55 words of your post, striped out of any special formatting eg: links, bold, etc.  I wanted to change it for a blog I was developing so I traced it back to the function <strong>wp_trim_excerpt</strong> in the file \wp-includes\formatting.php. In this file you can change the value from 55 to , in my case 100. Just change the line 786 which should look like this  <strong>$excerpt_length = 55</strong>;</p>
<p>Please remember that this will change the default value for all you excerpts.</p>
<p><span style="color: #ff0000;"><strong>UPDATED</strong></span>:  See <a title="Updated Content" href="http://www.techontour.com/web-design/2008/01/03/wordpress-get_excerpt-show-more-words/#comment-18658">Mike Schinkel&#8217;s comment</a> for updated information (Thank you)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techontour.com/web-design/2008/01/03/wordpress-get_excerpt-show-more-words/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

