aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/caldav
diff options
context:
space:
mode:
authorRandy Ramos <rramos1295@gmail.com>2017-09-06 17:46:19 -0400
committerLukas Fleischer <lfleischer@calcurse.org>2017-09-08 22:35:36 +0200
commit1e1d61585ded01891de74f01b88fc03c8ab89bb2 (patch)
tree638551a4818f773fcc16b8df142d9121d7c4b96f /contrib/caldav
parent2d1e6e394d14b21525d981546108bb8f0ba44f98 (diff)
downloadcalcurse-1e1d61585ded01891de74f01b88fc03c8ab89bb2.tar.gz
calcurse-1e1d61585ded01891de74f01b88fc03c8ab89bb2.zip
Refactor calcurse-caldav to use httplib2
This will allow much more flexibility and less code duplication when adding OAuth2 support. OAuth2 support will require this library as it is a dependency of oauth2client. The documentation was updated to reflect the new dependency. Signed-off-by: Randy Ramos <rramos1295@gmail.com> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
Diffstat (limited to 'contrib/caldav')
-rw-r--r--contrib/caldav/README4
-rwxr-xr-xcontrib/caldav/calcurse-caldav.py42
2 files changed, 17 insertions, 29 deletions
diff --git a/contrib/caldav/README b/contrib/caldav/README
index 008b3fe..93baf37 100644
--- a/contrib/caldav/README
+++ b/contrib/caldav/README
@@ -18,7 +18,9 @@ Usage
calcurse-caldav requires an up-to-date version of calcurse and a configuration
file located at ~/.calcurse/caldav/config. An example configuration file can be
-found under contrib/caldav/config.sample in the calcurse source tree.
+found under contrib/caldav/config.sample in the calcurse source tree. You will
+also need to install *httplib2* for Python 3 using *pip* (e.g. `pip3 install
+--user httplib2`) or your distribution's package manager.
If you run calcurse-caldav for the first time, you need to provide the --init
argument. You can choose between the following initialization modes:
diff --git a/contrib/caldav/calcurse-caldav.py b/contrib/caldav/calcurse-caldav.py
index f98ee9d..3725068 100755
--- a/contrib/caldav/calcurse-caldav.py
+++ b/contrib/caldav/calcurse-caldav.py
@@ -3,10 +3,9 @@
import argparse
import base64
import configparser
-import http.client
+import httplib2
import os
import re
-import ssl
import subprocess
import sys
import textwrap
@@ -113,18 +112,14 @@ def remote_query(conn, cmd, path, additional_headers, body):
if isinstance(body, str):
body = body.encode('utf-8')
- conn.request(cmd, path, headers=headers, body=body)
-
- resp = conn.getresponse()
+ resp, body = conn.request(path, cmd, body=body, headers=headers)
+ body = body.decode('utf-8')
if not resp:
return (None, None)
- headers = resp.getheaders()
- body = resp.read().decode('utf-8')
-
if debug:
- print("< Headers: " + repr(headers))
+ print("< Headers: " + repr(resp))
for line in body.splitlines():
print("< " + line)
print()
@@ -134,7 +129,7 @@ def remote_query(conn, cmd, path, additional_headers, body):
"while trying to access {}.").format(hostname, resp.status,
resp.reason, path))
- return (headers, body)
+ return (resp, body)
def get_etags(conn, hrefs=[]):
@@ -155,7 +150,7 @@ def get_etags(conn, hrefs=[]):
'<D:prop><D:getetag /></D:prop>'
'<C:filter><C:comp-filter name="VCALENDAR" /></C:filter>'
'</C:calendar-query>')
- headers, body = remote_query(conn, "REPORT", path, headers, body)
+ headers, body = remote_query(conn, "REPORT", absolute_uri, headers, body)
if not headers:
return {}
root = etree.fromstring(body)
@@ -230,13 +225,13 @@ def save_syncdb(fn, syncdb):
def push_object(conn, objhash):
href = path + objhash + ".ics"
body = calcurse_export(objhash)
- headers, body = remote_query(conn, "PUT", href, {}, body)
+ headers, body = remote_query(conn, "PUT", hostname_uri + href, {}, body)
if not headers:
return None
etag = None
- headerdict = dict((key.lower(), value) for key, value in headers)
+ headerdict = dict(headers)
if 'etag' in headerdict:
etag = headerdict['etag']
while not etag:
@@ -266,7 +261,7 @@ def push_objects(objhashes, conn, syncdb, etagdict):
def remove_remote_object(conn, etag, href):
headers = {'If-Match': '"' + etag + '"'}
- remote_query(conn, "DELETE", href, headers, None)
+ remote_query(conn, "DELETE", hostname_uri + href, headers, None)
def remove_remote_objects(objhashes, conn, syncdb, etagdict):
@@ -313,7 +308,7 @@ def pull_objects(hrefs_missing, hrefs_modified, conn, syncdb, etagdict):
for href in (hrefs_missing | hrefs_modified):
body += '<D:href>{}</D:href>'.format(href)
body += '</C:calendar-multiget>'
- headers, body = remote_query(conn, "REPORT", path, {}, body)
+ headers, body = remote_query(conn, "REPORT", absolute_uri, {}, body)
root = etree.fromstring(body)
@@ -433,6 +428,8 @@ except FileNotFoundError as e:
hostname = config.get('General', 'HostName')
path = '/' + config.get('General', 'Path').strip('/') + '/'
+hostname_uri = 'https://' + hostname
+absolute_uri = hostname_uri + path
if config.has_option('General', 'InsecureSSL'):
insecure_ssl = config.getboolean('General', 'InsecureSSL')
@@ -499,18 +496,9 @@ try:
# Connect to the server via HTTPs.
if verbose:
print('Connecting to ' + hostname + '...')
+ conn = httplib2.Http()
if insecure_ssl:
- try:
- context = ssl._create_unverified_context()
- conn = http.client.HTTPSConnection(hostname, context=context)
- except AttributeError:
- # Python versions prior to 3.4.3 do not support
- # ssl._create_unverified_context(). However, these versions do not
- # seem to verify certificates by default so we can simply fall back
- # to http.client.HTTPSConnection().
- conn = http.client.HTTPSConnection(hostname)
- else:
- conn = http.client.HTTPSConnection(hostname)
+ conn.disable_ssl_certificate_validation = True
if init:
# In initialization mode, start with an empty synchronization database.
@@ -563,8 +551,6 @@ try:
# Write the synchronization database.
save_syncdb(syncdbfn, syncdb)
- # Close the HTTPs connection.
- conn.close()
finally:
# Remove lock file.
os.remove(lockfn)