<?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>Messy Mind &#187; Python</title>
	<atom:link href="http://www.messy-mind.net/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.messy-mind.net</link>
	<description>Welcome to the tangle in my head.</description>
	<lastBuildDate>Sun, 14 Feb 2010 12:06:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Python FTP Uploader in right click menu</title>
		<link>http://www.messy-mind.net/2007/python-ftp-uploader-in-right-click-menu/</link>
		<comments>http://www.messy-mind.net/2007/python-ftp-uploader-in-right-click-menu/#comments</comments>
		<pubDate>Sun, 07 Oct 2007 10:17:39 +0000</pubDate>
		<dc:creator>GearGOD</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[snippets]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://gear.64digits.com/blog/uncategorized/python-ftp-uploader-in-right-click-menu/</guid>
		<description><![CDATA[This tutorial will show you an example of how I&#8217;ve been using Python to make my life easier and make my computer do what I want. Here we&#8217;re going to add an option to the right click menu to upload a file to your FTP storage. Like so:

I&#8217;ve been using Python for a while now [...]]]></description>
			<content:encoded><![CDATA[<p>This tutorial will show you an example of how I&#8217;ve been using Python to make my life easier and make my computer do what I want. Here we&#8217;re going to add an option to the right click menu to upload a file to your FTP storage. Like so:<br />
<img SRC="http://messy-mind.net/blog/wp-content/uploads/2007/10/rightclick.jpg" /><br />
I&#8217;ve been using Python for a while now and have come to love it. The language is very intuitive, and most of the time I  know exactly how to do things which I&#8217;ve never done before; because they&#8217;re done in the most intuitive way. It&#8217;s very good when it comes to doing little tasks quickly. For example I have scripts that watch the household internet usage, or fetch a live proxy server list for me, or crawl image boards to make slideshows. I think this upload function is the most handy thing I made thusfar, so I thought it&#8217;ll be nice to share. I think everyone who regularily puts pictures on their site to show to others knows how annoying it is to be whipping out the ftp client just for that.</p>
<p>This is probably going to be my first actual tutorial. Ever. Lets see how I go!</p>
<p><span id="more-76"></span></p>
<div class = "nowrap">
First thing&#8217;s first. If you don&#8217;t have Python,  <a HREF="http://www.python.org/download/"  TITLE="Python">grab yourself a copy here</a>.  It comes with a whole lot of wonderful stuff built in  including FTP, so our life is going to be very easy. Start up Idle and make a new file. Save it as something that ends  with .py, this bit is important because otherwise you lose syntax highlighting.</p>
<p>For the actual upload, we want it to be quiet and unobtrusive because this isn&#8217;t a full blown app, its a little script  that&#8217;ll sit in your right click menu. Python&#8217;s FTPLib has great documentation <a  HREF="http://docs.python.org/lib/module-ftplib.html">here</a> but it&#8217;s so straightforward that we don&#8217;t even really  need it beyond the example. Lets try to get a connection to our server going.<br />
[python]<br />
from ftplib import FTP<br />
import os, sys, webbrowser</p>
<p>server = &#8216;ftp.blah.com&#8217;<br />
username = &#8216;joe&#8217;<br />
password = &#8216;password&#8217;</p>
<p>ftp = FTP(server)<br />
ftp.login(username, password)<br />
ftp.retrlines(&#8216;LIST&#8217;)<br />
ftp.close()<br />
[/python]<br />
Replace the details with your own and hit F5. Assuming the connection goes through, you&#8217;ll get a printout of your ftp  root folder. If not, an exception will be thrown, most likley saying that the authentication failed. That means your  details are wrong.</p>
<p>Anyway, now we have our basic connection, lets move on to the actual script to upload a file. Since this is a script  and not a gui app, it&#8217;ll receive the name of the file to upload as a program parameter. In python we have sys.argv for  that.<br />
[python]<br />
import sys</p>
<p>print &#8220;Params: &#8220;+str(len(sys.argv)) #the number of params<br />
print sys.argv #the entire list of params<br />
print sys.argv[0] #the first param (path to this prog)<br />
print &#8220;Press enter&#8221;<br />
raw_input(&#8220;&#8221;) #inputs a string, but here just acts as a &#8216;wait for enter&#8217;</p>
<p>[/python]<br />
You can try make a new script for that. Save it somwhere and hop over to it in explorer. If you run&gt;cmd and drag the  script into the command promt, you can now give it parameters by appending things after its filename.</p>
<p><highslide image="http://messy-mind.net/blog/wp-content/uploads/2007/10/command.jpg"  thumbnail="http://messy-mind.net/blog/wp-content/uploads/2007/10/command.thumbnail.jpg" altdesc=""  captiontext="Passing params to python" /></p>
<p>Nifty, isn&#8217;t it. Now lets put it all together into one big upload script. Here&#8217;s mine.<br />
[python]<br />
from ftplib import FTP<br />
import os, sys, webbrowser</p>
<p>website_url = &#8220;http://messy-mind.net/&#8221;<br />
server = &#8216;ftp.messy-mind.net&#8217;<br />
username = &#8216;lalala&#8217;<br />
password = &#8216;tralala&#8217;</p>
<p>#if we have two arguments (the second being the file to upload)<br />
if len(sys.argv) == 2:</p>
<p>    remote_folder = &#8220;temporary&#8221; #this is the folder I want to put my files on the server</p>
<p>    fname = sys.argv[1] #this is the second param, the file to upload<br />
    name = os.path.basename(fname) #fetch the filename alone for the remote name<br />
    name = name.replace(&#8221; &#8220;,&#8221;-&#8221;) #take out spaces from the name to make it nice for the web</p>
<p>    #Connect to server<br />
    ftp = FTP(server)<br />
    ftp.login(username, password)<br />
    ftp.cwd(&#8216;public_html/&#8217;+remote_folder) #hop to remote_folder<br />
    ftp.retrlines(&#8216;LIST&#8217;) #print out a dir listing for good measure</p>
<p>    #Upload the file to the server<br />
    print &#8220;Uploading&#8230;&#8221;,<br />
    ftp.storbinary(&#8220;STOR &#8220;+name, open(fname,&#8221;rb&#8221;))<br />
    ftp.close()<br />
    print &#8220;Done!&#8221;</p>
<p>    #Show the file in the default browser<br />
    webbrowser.open(website_url+remote_folder+&#8221;/&#8221;+name)</p>
<p>else:<br />
    print &#8220;No filename given&#8221;<br />
[/python]<br />
That&#8217;s it! The comments should be enough to make sense of it all. Drop it into cmd and pass on a file. You should get  something like this and then your browser should pop up showing what you just uploaded.<br />
<highslide image="http://messy-mind.net/blog/wp-content/uploads/2007/10/command2.jpg"  thumbnail="http://messy-mind.net/blog/wp-content/uploads/2007/10/command2.thumbnail.jpg" altdesc="python upload"  captiontext="Uploader in action" /></p>
<p>Now for the second part; getting this into the right click menu.  We&#8217;ll be messing around with registry so I&#8217;m just  going to give you the functions I wrote up with no intermediate steps so there&#8217;s no room for you to screw up and kill  your windows install or something.<br />
The idea is that windows registry has a place where you can put your own right click function and associate it with a  program. The only problem I ran into is that windows doesn&#8217;t allow you to associate with .py scripts and stubbornly  demands exe. So I wrote a little program called runner which simply executes a given script and passes params on to it.  Here is the framework to allow a script to register itself as a right click item<br />
[python]<br />
import sys, os<br />
from _winreg import *</p>
<p>def register(command_name,association=sys.argv[0],runner=&#8221;runner.exe&#8221;):<br />
    association = os.path.realpath(association)<br />
    runner = os.path.realpath(runner)</p>
<p>    if not os.path.isfile(runner):<br />
        print &#8220;Runder does not exist at &#8220;+runner<br />
        return 0</p>
<p>    try:<br />
        reg = CreateKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name+&#8221;\\Command&#8221;)<br />
        runner_path = runner.replace(&#8220;\\&#8221;,&#8221;\\\\&#8221;)<br />
        association_path = association.replace(&#8220;\\&#8221;,&#8221;\\\\&#8221;)</p>
<p>        key = runner_path + &#8221; &#8221; +association_path + &#8221; %1&#8243;<br />
        print command_name+&#8221; :: &#8220;+key<br />
        SetValue(reg, &#8220;&#8221;, REG_SZ, key)<br />
        CloseKey(reg)<br />
    except:<br />
        print &#8220;Failed to set registry&#8221;</p>
<p>def unregister(command_name):<br />
    try:<br />
        if command_name==&#8221;":<br />
            return 0 #don&#8217;t allow everything under shell to be deleted<br />
        DeleteKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name+&#8221;\\Command&#8221;)<br />
        DeleteKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name)<br />
        print (&#8220;Deleted HKEY_CLASSES_ROOT\\&#8221;+&#8221;*\\Shell\\&#8221;+command_name)<br />
    except:<br />
        print &#8220;Command &#8220;+command_name+&#8221; was not registered&#8221;</p>
<p>command_name = &#8220;Test&#8221;<br />
if len(sys.argv)==1:<br />
    register(command_name)</p>
<p>if len(sys.argv)==2:<br />
    if sys.argv[1] == &#8220;-unreg&#8221;:<br />
        unregister(command_name)<br />
        raw_input(&#8220;&#8221;)<br />
        sys.exit()</p>
<p>    print sys.argv<br />
    raw_input(&#8220;&#8221;)<br />
[/python]</p>
<p>If you download the <a TITLE="Python script runner"  HREF="http://messy-mind.net/blog/wp-content/uploads/2007/10/runner.zip">Python script runner </a>and throw it into  the same folder as that script, running the script will result in &#8216;Test&#8217; being added to the right click menu on any  file. Running the script and passing -unreg as a parameter will take that back off. You can use this framework to add  any option that does anything.</p>
<p>Putting it all together.<br />
Now we know how to upload and how to stick things into the right click menu. It&#8217;s just a matter of taking the context menu framework and extending it with the upload function. Here&#8217;s mine.<br />
[python]<br />
import sys, os<br />
from _winreg import *</p>
<p>from ftplib import FTP<br />
import webbrowser</p>
<p>website_url = &#8220;http://gear.64digits.com/&#8221;<br />
server = &#8216;ftp.gear.64digits.com&#8217;<br />
username = &#8216;lalala&#8217;<br />
password = &#8216;tralala&#8217;</p>
<p>def upload(fname):<br />
    remote_folder = &#8220;temporary&#8221; #this if the folder I want to put my files on the server</p>
<p>    name = os.path.basename(fname) #fetch the filename alone for the remote name<br />
    name = name.replace(&#8221; &#8220;,&#8221;-&#8221;) #take out spaces from the name to make it nice for the web</p>
<p>    #Connect to server<br />
    ftp = FTP(server)<br />
    ftp.login(username, password)<br />
    ftp.cwd(&#8216;public_html/&#8217;+remote_folder) #hop to remote_folder<br />
    ftp.retrlines(&#8216;LIST&#8217;) #print out a dir listing for good measure</p>
<p>    #Upload the file to the server<br />
    print &#8220;Uploading&#8230;&#8221;,<br />
    ftp.storbinary(&#8220;STOR &#8220;+name, open(fname,&#8221;rb&#8221;))<br />
    ftp.close()<br />
    print &#8220;Done!&#8221;</p>
<p>    #Show the file in the default browser<br />
    webbrowser.open(website_url+remote_folder+&#8221;/&#8221;+name)</p>
<p>def register(command_name,association=sys.argv[0],runner=&#8221;runner.exe&#8221;):<br />
    #The params are:<br />
    #name to register as, this shows in in the right click menu for all files<br />
    #the script to associate it with (defaults to this script)<br />
    #the location of the runner (defaults to runner.exe in same place as script)</p>
<p>    association = os.path.realpath(association)<br />
    runner = os.path.realpath(runner)</p>
<p>    if not os.path.isfile(runner):<br />
        print &#8220;Runder does not exist at &#8220;+runner<br />
        return 0</p>
<p>    try:<br />
        reg = CreateKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name+&#8221;\\Command&#8221;)<br />
        runner_path = runner.replace(&#8220;\\&#8221;,&#8221;\\\\&#8221;)<br />
        association_path = association.replace(&#8220;\\&#8221;,&#8221;\\\\&#8221;)</p>
<p>        key = runner_path + &#8221; &#8221; +association_path + &#8221; %1&#8243;<br />
        print command_name+&#8221; :: &#8220;+key<br />
        SetValue(reg, &#8220;&#8221;, REG_SZ, key)<br />
        CloseKey(reg)<br />
    except:<br />
        print &#8220;Failed to set registry&#8221;</p>
<p>def unregister(command_name):<br />
    #the param is the name of the command<br />
    try:<br />
        if command_name==&#8221;":<br />
            return 0 #don&#8217;t allow everything under shell to be deleted<br />
        DeleteKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name+&#8221;\\Command&#8221;)<br />
        DeleteKey(HKEY_CLASSES_ROOT,&#8221;*\\Shell\\&#8221;+command_name)<br />
        print (&#8220;Deleted HKEY_CLASSES_ROOT\\&#8221;+&#8221;*\\Shell\\&#8221;+command_name)<br />
    except:<br />
        print &#8220;Command &#8220;+command_name+&#8221; was not registered&#8221;</p>
<p>command_name = &#8220;Upload&#8221;</p>
<p>#If no arguments are given, register ourselves<br />
if len(sys.argv)==1:<br />
    register(command_name)</p>
<p>#Otherwise unregister if the command is -unreg, or otherwise do whatever we want<br />
if len(sys.argv)==2:<br />
    if sys.argv[1] == &#8220;-unreg&#8221;:<br />
        unregister(command_name)<br />
        sys.exit()</p>
<p>    #At this point we can call functions to operate on the param given<br />
    #which is the name of the file that was right clicked<br />
    upload(sys.argv[1])<br />
[/python]<br />
We&#8217;re done! Stick that script somwhere, make sure runner.exe resides in the same folder, and run the script to have it  register itself under Upload. Last but not least, after you&#8217;re done with a script and want to use it, you&#8217;ll want to  prevent it from opening up the dos prompt window. To do that, just rename it from .py into .pyw which is the format for  gui apps, only we&#8217;re not using any gui functionality. Of course you&#8217;ll then want to run the .pyw to have it register itself in the menu, overwriting the previous .py reference.</p>
<p>Well, that&#8217;s all. I hope that wasn&#8217;t too terrible. You can use the framework here to do anything you want with a file  through right click. Personally for me the upload function is wonderful. No waiting for stupid imageshack, no whipping  out ftp client. Just click and a few seconds later its already in your browser! You might want to look into things like  adding a system tray icon to display the progress, and perhaps support for uploading entire folders. One thing I wanted  to do was to put the uploaded url into clipboard, but I haven&#8217;t been able to find a Python library that claims to do  this and actually works.<br />
<a HREF="http://gear.64digits.com/blog/wp-content/uploads/2007/10/uploader.zip" TITLE="Python uploader">Here is the  finished product.</a><br />
Just unzip to a premanent location, open it in notepad to put in your FTP details, and run the .pyw script so the Upload option will appear in right click menu. If you  need to get rid of it, run uploader.pyw -unreg<br />
And I&#8217;m in no way responsible for any damage you might do to your computer while messing around with this. The registry  functions are pretty safe but editing them can result in big damage.
</div>
<img src="http://www.messy-mind.net/?ak_action=api_record_view&id=76&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.messy-mind.net/2007/python-ftp-uploader-in-right-click-menu/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
