Index: S3/Config.py
===================================================================
--- S3/Config.py	(revision 478)
+++ S3/Config.py	(working copy)
@@ -76,6 +76,8 @@
 	follow_symlinks = False
 	socket_timeout = 300
 	invalidate_on_cf = False
+	method = "GET"
+	ttl = 10
 
 	## Creating a singleton
 	def __new__(self, configfile = None):
Index: s3cmd
===================================================================
--- s3cmd	(revision 478)
+++ s3cmd	(working copy)
@@ -23,6 +23,7 @@
 import subprocess
 import htmlentitydefs
 import socket
+import urllib
 
 from copy import copy
 from optparse import OptionParser, Option, OptionValueError, IndentedHelpFormatter
@@ -522,6 +523,21 @@
 			else:
 				raise
 
+def cmd_url(args):
+	cfg = Config()
+	s3 = S3(cfg)
+	
+	while (len(args)):
+		uri_arg = args.pop(0)
+		uri = S3Uri(uri_arg)
+		if uri.type != "s3" or not uri.has_bucket():
+			raise ParameterError("Expecting S3 URI instead of '%s'" % uri_arg)
+		expires = int(time.time() + cfg.ttl)
+		string_to_sign = "%s\n\n\n%s\n/%s/%s" % (cfg.method, expires, uri._bucket, uri._object)
+		signature = urllib.quote(Utils.sign_string(string_to_sign))
+		url = "%s?AWSAccessKeyId=%s&Expires=%s&Signature=%s" % (uri.public_url(), cfg.access_key, expires, signature)
+		output(url)
+
 def cmd_sync_remote2remote(args):
 	s3 = S3(Config())
 
@@ -1316,6 +1332,7 @@
 	{"cmd":"sync", "label":"Synchronize a directory tree to S3", "param":"LOCAL_DIR s3://BUCKET[/PREFIX] or s3://BUCKET[/PREFIX] LOCAL_DIR", "func":cmd_sync, "argc":2},
 	{"cmd":"du", "label":"Disk usage by buckets", "param":"[s3://BUCKET[/PREFIX]]", "func":cmd_du, "argc":0},
 	{"cmd":"info", "label":"Get various information about Buckets or Files", "param":"s3://BUCKET[/OBJECT]", "func":cmd_info, "argc":1},
+	{"cmd":"url", "label":"Generate pre-signed URLs for File", "param":"s3://BUCKET/OBJECT", "func":cmd_url, "argc":1},
 	{"cmd":"cp", "label":"Copy object", "param":"s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]", "func":cmd_cp, "argc":2},
 	{"cmd":"mv", "label":"Move object", "param":"s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]", "func":cmd_mv, "argc":2},
 	{"cmd":"setacl", "label":"Modify Access control list for Bucket or Files", "param":"s3://BUCKET[/OBJECT]", "func":cmd_setacl, "argc":1},
@@ -1449,6 +1466,9 @@
 	optparser.add_option(      "--list-md5", dest="list_md5", action="store_true", help="Include MD5 sums in bucket listings (only for 'ls' command).")
 	optparser.add_option("-H", "--human-readable-sizes", dest="human_readable_sizes", action="store_true", help="Print sizes in human readable form (eg 1kB instead of 1234).")
 
+	optparser.add_option(      "--method", dest="method", action="store", help="Set HTTP method. Options are: GET (default), PUT (only for 'url' command).")
+	optparser.add_option(      "--ttl", dest="ttl", action="store", help="Set expires time TTL seconds in the future. Default: 10 (only for 'url' command).")
+
 	optparser.add_option(      "--progress", dest="progress_meter", action="store_true", help="Display progress meter (default on TTY).")
 	optparser.add_option(      "--no-progress", dest="progress_meter", action="store_false", help="Don't display progress meter (default on non-TTY).")
 	optparser.add_option(      "--enable", dest="enable", action="store_true", help="Enable given CloudFront distribution (only for [cfmodify] command)")
