7bf5fab1fa2fa07cc012c0570781aea23343ae05bcca862eaaeeb4e5a739a9107f8ae073ef6a37b3
 
 
1
#!/usr/bin/env python
 
 
2
 
 
 
3
# The contents of this file are subject to the Common Public Attribution
 
 
4
# License Version 1.0. (the "License"); you may not use this file except in
 
 
5
# compliance with the License. You may obtain a copy of the License at
 
 
6
# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
 
 
7
# License Version 1.1, but Sections 14 and 15 have been added to cover use of
 
 
8
# software over a computer network and provide for limited attribution for the
 
 
9
# Original Developer. In addition, Exhibit A has been modified to be consistent
 
 
10
# with Exhibit B.
 
 
11
# 
 
 
12
# Software distributed under the License is distributed on an "AS IS" basis,
 
 
13
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 
 
14
# the specific language governing rights and limitations under the License.
 
 
15
# 
 
 
16
# The Original Code is Reddit.
 
 
17
# 
 
 
18
# The Original Developer is the Initial Developer.  The Initial Developer of the
 
 
19
# Original Code is CondeNet, Inc.
 
 
20
# 
 
 
21
# All portions of the code written by CondeNet are Copyright (c) 2006-2008
 
 
22
# CondeNet, Inc. All Rights Reserved.
 
 
23
################################################################################
 
 
24
 
 
 
25
import base64, hmac, sha, os, sys, getopt
 
 
26
from datetime import datetime
 
 
27
from pylons import g,config
 
 
28
 
 
 
29
KEY_ID = g.S3KEY_ID
 
 
30
SECRET_KEY = g.S3SECRET_KEY
 
 
31
 
 
 
32
class S3Exception(Exception): pass
 
 
33
 
 
 
34
def make_header(verb, date, amz_headers, resource, content_type):
 
 
35
    content_md5 = ''
 
 
36
 
 
 
37
    #amazon headers
 
 
38
    lower_head = dict((key.lower(), val)
 
 
39
                      for key, val in amz_headers.iteritems())
 
 
40
    keys = lower_head.keys()
 
 
41
    keys.sort()
 
 
42
    amz_lst = ['%s:%s' % (key, lower_head[key]) for key in keys]
 
 
43
    amz_str = '\n'.join(amz_lst)
 
 
44
 
 
 
45
    s = '\n'.join((verb,
 
 
46
                   content_md5,
 
 
47
                   content_type,
 
 
48
                   date,
 
 
49
                   amz_str,
 
 
50
                   resource))
 
 
51
 
 
 
52
    h = hmac.new(SECRET_KEY, s, sha)
 
 
53
    return base64.encodestring(h.digest()).strip()
 
 
54
 
 
 
55
def send_file(filename, resource, content_type, acl, rate, meter):
 
 
56
    date = datetime.utcnow().strftime("%a, %d %b %Y %X GMT")
 
 
57
    amz_headers = {'x-amz-acl': acl}
 
 
58
 
 
 
59
    auth_header = make_header('PUT', date, amz_headers, resource, content_type)
 
 
60
 
 
 
61
    params = ['-T', filename,
 
 
62
              '-H', 'x-amz-acl: %s' % amz_headers['x-amz-acl'],
 
 
63
              '-H', 'Authorization: AWS %s:%s' % (KEY_ID, auth_header),
 
 
64
              '-H', 'Date: %s' % date]
 
 
65
 
 
 
66
    if content_type:
 
 
67
        params.append('-H')
 
 
68
        params.append('Content-Type: %s' % content_type)
 
 
69
 
 
 
70
    if rate:
 
 
71
        params.append('--limit-rate')
 
 
72
        params.append(rate)
 
 
73
 
 
 
74
    if meter:
 
 
75
        params.append('-o')
 
 
76
        params.append('s3cp.output')
 
 
77
    else:
 
 
78
        params.append('-s')
 
 
79
 
 
 
80
    params.append('https://s3.amazonaws.com%s' % resource)
 
 
81
 
 
 
82
    exit_code = os.spawnlp(os.P_WAIT, 'curl', 'curl', *params)
 
 
83
    if exit_code:
 
 
84
        raise S3Exception(exit_code)
 
 
85
 
 
 
86
 
 
 
87
if __name__ == '__main__':
 
 
88
    options = "a:c:l:m"
 
 
89
    try:
 
 
90
        opts, args = getopt.getopt(sys.argv[1:], options)
 
 
91
    except:
 
 
92
        sys.exit(2)
 
 
93
 
 
 
94
    opts = dict(opts)
 
 
95
 
 
 
96
    send_file(args[0], args[1],
 
 
97
              opts.get('-c', ''),
 
 
98
              opts.get('-a', 'private'),
 
 
99
              opts.get('-l'),
 
 
100
              opts.has_key('-m'))