diff --git a/geeknote/oauth.py b/geeknote/oauth.py index 3c44a01..dd173fb 100644 --- a/geeknote/oauth.py +++ b/geeknote/oauth.py @@ -5,7 +5,8 @@ import Cookie import uuid import re -from urllib import urlencode, unquote +import base64 +from urllib import urlencode, unquote, getproxies, proxy_bypass from urlparse import urlparse import out @@ -58,6 +59,26 @@ class GeekNoteAuth(object): incorrectCode = 0 code = None + def __init__(self): + try: + proxy = getproxies()['https'] + except KeyError: + proxy = None + if proxy is None: + self._proxy = None + else: + # This assumes that the proxy is given in URL form. + # A little simpler as _parse_proxy in urllib2.py + self._proxy = urlparse(proxy) + + if proxy is None or not self._proxy.username: + self._proxy_auth = None + else: + user_pass = "%s:%s" % (urlparse.unquote(self._proxy.username), + urlparse.unquote(self._proxy.password)) + self._proxy_auth = { "Proxy-Authorization": + "Basic " + base64.b64encode(user_pass).strip() } + def getTokenRequestData(self, **kwargs): params = { 'oauth_consumer_key': self.consumerKey, @@ -77,9 +98,11 @@ def loadPage(self, url, uri=None, method="GET", params=""): logging.error("Request URL undefined") tools.exitErr() + if not url.startswith("http"): + url = "https://" + url + urlData = urlparse(url) if not uri: - urlData = urlparse(url) - url = urlData.netloc + url = "%s://%s" (urlData.scheme, urlData.netloc) uri = urlData.path + '?' + urlData.query # prepare params, append to uri @@ -97,11 +120,27 @@ def loadPage(self, url, uri=None, method="GET", params=""): if method == "POST": headers["Content-type"] = "application/x-www-form-urlencoded" - logging.debug("Request URL: %s:/%s > %s # %s", url, + if self._proxy is None or proxy_bypass(urlData.hostname): + host = urlData.hostname + port = urlData.port + real_host = real_port = None + else: + host = self._proxy.hostname + port = self._proxy.port + real_host = urlData.hostname + real_port = urlData.port + + logging.debug("Request URL: %s%s > %s # %s", url, uri, unquote(params), headers["Cookie"]) - conn = httplib.HTTPSConnection(url) - conn.request(method, uri, params, headers) + conn = httplib.HTTPSConnection(host, port) + + if real_host is not None: + conn.set_tunnel(real_host, real_port, headers=self._proxy_auth) + if config.DEBUG: + conn.set_debuglevel(1) + + conn.request(method, url + uri, params, headers) response = conn.getresponse() data = response.read() conn.close() diff --git a/geeknote/out.py b/geeknote/out.py index 6c3e27b..222eb6c 100644 --- a/geeknote/out.py +++ b/geeknote/out.py @@ -275,18 +275,11 @@ def rawInput(message, isPass=False): def printDate(timestamp): - # Author @ash-2000 https://github.com/ash-2000 - # Check for crashing when timestamp is 13 digits on python2.7 - # pull request #260 - - if len(str(timestamp)) == 13: - timestamp = int(str(timestamp)[0:-3]) - - # --- - return datetime.date.strftime(datetime.date.fromtimestamp(timestamp / 1000), "%d.%m.%Y") -def printLine(line, endLine="\n", out=sys.stdout): +def printLine(line, endLine="\n", out=None): + if out is None: + out = sys.stdout message = line + endLine message = tools.stdoutEncode(message) try: diff --git a/proxy_support.md b/proxy_support.md new file mode 100644 index 0000000..ba292e4 --- /dev/null +++ b/proxy_support.md @@ -0,0 +1,45 @@ +HTTP proxy support for geeknote +=============================== + +I recommend to make this work with virtualenv, to avoid overwriting system files. +The important part is to install in the order **thrift, then evernote, then geeknote**. This will make sure that path search order is correct for thrift. + +``` +# Download thrift and geeknote +git clone https://github.com/apache/thrift.git +git clone https://github.com/mwilck/geeknote.git + +# create and enter a virtual environment +virtualenv /var/tmp/geeknote +. /var/tmp/geeknote/bin/activate + +# Apply proxy-support patches for thrift +cd thrift + +## If the patches don't apply, you may need to check out the state that I wrote the patches for: +## git checkout -b proxy e363a34e63 +curl https://issues.apache.org/jira/secure/attachment/12801233/0001-python-THttpClient-Add-support-for-system-proxy-sett.patch | git am +curl https://issues.apache.org/jira/secure/attachment/12801234/0002-Python-THttpClient-Support-proxy-authorization.patch | git am + +# Install thrift from the patched tree +(cd lib/py; python setup.py install) +cd .. + +# Install evernote +pip install evernote + +# Install geeknote +cd geeknote +python setup.py install +``` + +Now `geeknote login`, `geeknote find`, etc. should work behind a proxy if the `http_proxy` environment variable is correctly set. You can now generate a script to activate the virtual environment: + +``` +cat >~/bin/geeknote <<\EOF +#! /bin/bash +. /var/tmp/geeknote/bin/activate +exec geeknote "$@" +EOF +chmod a+x ~/bin/geeknote +``` \ No newline at end of file diff --git a/tests/editorTest.py b/tests/editorTest.py index 92e54dc..3e0fa8c 100644 --- a/tests/editorTest.py +++ b/tests/editorTest.py @@ -16,7 +16,6 @@ def setUp(self): _Line 2_ **Line 3** - """ self.HTML_TEXT = "

Header 1

Header 2

Line 1

"\ "Line 2

Line 3

" diff --git a/tests/geeknoteTest.py b/tests/geeknoteTest.py index 209c3a2..4b116b8 100644 --- a/tests/geeknoteTest.py +++ b/tests/geeknoteTest.py @@ -88,6 +88,5 @@ def test_createSearchRequest2(self): self.assertEqual(testRequest, response) def testError_createSearchRequest1(self): - testRequest = self.notes._createSearchRequest(search="test text", - date="12.31.1999") - self.assertEqual(testRequest, 'exit') + self.assertRaises(SystemExit, self.notes._createSearchRequest, + search="test text", date="12.31.1999") diff --git a/tests/outTest.py b/tests/outTest.py index 778333f..a2a4ee4 100644 --- a/tests/outTest.py +++ b/tests/outTest.py @@ -22,6 +22,9 @@ class UserStub(object): accounting = AccountingStub() +class NoteAttributesStub(object): + pass + class NoteStub(object): title = 'testnote' created = 10000 @@ -29,7 +32,7 @@ class NoteStub(object): content = '##note content' tagNames = ['tag1', 'tag2', 'tag3'] guid = 12345 - + attributes = NoteAttributesStub() class outTestsWithHackedStdout(unittest.TestCase): @@ -73,9 +76,13 @@ def test_separator_empty_args_success(self): self.assertEquals(sys.stdout.read(), '\n\n') def test_failure_message_success(self): + sav = sys.stderr + buf = StringIO() + sys.stderr = buf failureMessage('fail') - sys.stdout.seek(0) - self.assertEquals(sys.stdout.read(), 'fail\n') + sys.stderr = sav + buf.seek(0) + self.assertEquals(buf.read(), 'fail\n') def test_success_message_success(self): successMessage('success') @@ -106,18 +113,19 @@ def test_show_note_success(self): note = '''################## TITLE ################## testnote =================== META ================== -Created: 01.01.1970 Updated:01.01.1970 \n'''\ -'''----------------- CONTENT ----------------- +Created: 01.01.1970 +Updated: 01.01.1970 +----------------- CONTENT ----------------- Tags: tag1, tag2, tag3 -##note content\n\n\n''' +##note content\n\n''' showNote(NoteStub()) sys.stdout.seek(0) self.assertEquals(sys.stdout.read(), note) def test_print_list_without_title_success(self): notes_list = '''Total found: 2 - 1 : 01.01.1970 testnote - 2 : 01.01.1970 testnote\n''' + 1 : 01.01.1970 testnote + 2 : 01.01.1970 testnote\n''' printList([NoteStub() for _ in xrange(2)]) sys.stdout.seek(0) self.assertEquals(sys.stdout.read(), notes_list) @@ -125,8 +133,8 @@ def test_print_list_without_title_success(self): def test_print_list_with_title_success(self): notes_list = '''=================== test ================== Total found: 2 - 1 : 01.01.1970 testnote - 2 : 01.01.1970 testnote\n''' + 1 : 01.01.1970 testnote + 2 : 01.01.1970 testnote\n''' printList([NoteStub() for _ in xrange(2)], title='test') sys.stdout.seek(0) self.assertEquals(sys.stdout.read(), notes_list) @@ -134,8 +142,8 @@ def test_print_list_with_title_success(self): def test_print_list_with_urls_success(self): notes_list = '''=================== test ================== Total found: 2 - 1 : 01.01.1970 testnote >>> https://www.evernote.com/Home.action?#n=12345 - 2 : 01.01.1970 testnote >>> https://www.evernote.com/Home.action?#n=12345 + 1 : 01.01.1970 testnote >>> https://www.evernote.com/Home.action?#n=12345 + 2 : 01.01.1970 testnote >>> https://www.evernote.com/Home.action?#n=12345 ''' printList([NoteStub() for _ in xrange(2)], title='test', showUrl=True) sys.stdout.seek(0) @@ -145,8 +153,8 @@ def test_print_list_with_selector_success(self): out.rawInput = lambda x: 2 notes_list = '''=================== test ================== Total found: 2 - 1 : 01.01.1970 testnote - 2 : 01.01.1970 testnote + 1 : 01.01.1970 testnote + 2 : 01.01.1970 testnote 0 : -Cancel-\n''' out.printList([NoteStub() for _ in xrange(2)], title='test', showSelector=True) sys.stdout.seek(0) @@ -155,11 +163,11 @@ def test_print_list_with_selector_success(self): def test_search_result_success(self): result = '''Search request: test Total found: 2 - 1 : 01.01.1970 testnote - 2 : 01.01.1970 testnote\n''' + 1 : 01.01.1970 testnote + 2 : 01.01.1970 testnote\n''' SearchResult([NoteStub() for _ in xrange(2)], 'test') sys.stdout.seek(0) self.assertEquals(sys.stdout.read(), result) def test_print_date(self): - self.assertEquals(printDate(1000000), '12.01.1970') + self.assertEquals(printDate(1000000000L), '12.01.1970')