~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/python -S
#
# Copyright 2009 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

import _pythonpath

import base64
import httplib
import os
import pwd
import sys
import urllib
import webbrowser
from optparse import OptionParser
from urlparse import urljoin
from cookielib import Cookie, CookieJar
from mechanize import HTTPRobotRulesProcessor

from zope.testbrowser.browser import Browser


# Should we be able to override any of these?
AUTH_FILE = '~/.lp_auth_cookie'
PRIVATE_PASTE_HOST = 'pastebin.canonical.com'
PUBLIC_PASTE_HOST = 'pastebin.ubuntu.com'
PASTE_PATH = ''
LP_AUTH_INSTRUCTIONS = """
%s doesn't contain a valid LP authentication cookie.

Please update this file, with the 'lp' cookie value your browser sends
when visiting https://launchpad.net (while being logged in). It should
look something like this:

    sd33JsfeJop3esf6joi8sldfjJoIj3dssD6isfsdweJDe6i9JIKEYK
""" % AUTH_FILE


def parse_arguments():
    parser = OptionParser(usage='%prog [options] [title] < stdin')
    parser.add_option('-b', '--browser',
                      default=False, action='store_true',
                      help='Open web browser to the pastebin.')
    parser.add_option('-p', '--private',
                      default=False, action='store_true',
                      help='Use a private pastebin (pastebin.canonical.com).')
    parser.add_option('-s', '--syntax',
                      default='text', type='string',
                      help='The syntax of the pastebin.')
    parser.add_option('-f', '--file',
                      type='string',
                      help='File to pastebin instead of stdin.')
    options, arguments = parser.parse_args()
    if len(arguments) == 0:
        parser.title = None
    elif len(arguments) == 1:
        parser.title = arguments[0]
    else:
        parser.error('Too many arguments')
        # Does not return
    parser.options = options
    parser.arguments = arguments
    return parser


def get_lp_auth_cookie(path):
    """Read the authentication file, and return a Cookie object."""
    path = os.path.expanduser(path)
    if not os.path.exists(path):
        return None
    f = open(path)
    try:
        cookie_value = f.readline().strip()
    finally:
        f.close()
    return Cookie(
        version=0, name='lp', value=cookie_value,
        port=None, port_specified=False,
        domain='login.launchpad.net', domain_specified=True,
        domain_initial_dot=False, path='', path_specified=None,
        secure=True, expires=None, discard=True,
        comment=None, comment_url=None, rest=None, rfc2109=False)


def authenticate(browser):
    """Go through the OpenID process and authenticate."""
    # First click on the page where it says we have to log in.
    browser.getControl('Continue').click()
    return True


def main():
    parser = parse_arguments()
    try:
        poster = os.environ['USER']
    except KeyError:
        poster = pwd.getpwuid(os.getuid()).pw_name

    if parser.title is None:
        title = "The loser %s didn't even add a title" % poster
    else:
        title = parser.title

    if parser.options.file:
        f = open(parser.options.file)
        try:
            content = f.read()
        finally:
            f.close()
    else:
        content = sys.stdin.read()

    form = (
        ('poster', poster),
        ('syntax', [parser.options.syntax]),
        ('content', content),
        )

    browser = Browser()
    paste_host = PUBLIC_PASTE_HOST
    if parser.options.private:
        paste_host = PRIVATE_PASTE_HOST
        # Figure out the authentication.
        lp_cookie = get_lp_auth_cookie(AUTH_FILE)
        if lp_cookie is None:
            print LP_AUTH_INSTRUCTIONS
            return
        cookiejar = CookieJar()
        cookiejar.set_cookie(lp_cookie)
        browser.mech_browser.set_cookiejar(cookiejar)

    # Remove the the check for robots.txt, since the one on
    # pastebin.ubuntu.com doesn't allow us to open the page. We're not
    # really a robot.
    browser.mech_browser.handlers = [
        handler for handler in browser.mech_browser.handlers
        if not isinstance(handler, HTTPRobotRulesProcessor)]
    browser.open(urljoin('https://' + paste_host, PASTE_PATH))

    if parser.options.private:
        # We need to authenticate before pasting.
        oid_form = browser.getForm(id='openid_message')
        if oid_form is not None:
            authenticated = authenticate(browser)
            if not authenticated:
                print LP_AUTH_INSTRUCTIONS
                return
    for name, value in form:
        browser.getControl(name=name).value = value
    browser.getControl('Paste!').click()
    print browser.url
    if parser.options.browser:
        webbrowser.open(browser.url)


if __name__ == '__main__':
    main()