calcurse-caldav: Add a debug mode
Dump all communication with the server to stdout if --debug is specified. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
448d470b61
commit
badbd71275
@ -80,14 +80,35 @@ def get_auth_headers():
|
|||||||
headers = { 'Authorization' : 'Basic %s' % user_password }
|
headers = { 'Authorization' : 'Basic %s' % user_password }
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
def get_headers():
|
def remote_query(cmd, path, additional_headers, body):
|
||||||
headers = get_auth_headers()
|
headers = get_auth_headers()
|
||||||
headers['Content-Type'] = 'Content-Type: text/calendar; charset=utf-8'
|
headers['Content-Type'] = 'Content-Type: text/calendar; charset=utf-8'
|
||||||
return headers
|
headers.update(additional_headers)
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print("> " + repr(headers))
|
||||||
|
if body:
|
||||||
|
for line in body.splitlines():
|
||||||
|
print("> " + line)
|
||||||
|
|
||||||
|
conn.request(cmd, path, headers=headers, body=body)
|
||||||
|
|
||||||
|
resp = conn.getresponse()
|
||||||
|
|
||||||
|
if not resp:
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
headers = resp.getheaders()
|
||||||
|
body = resp.read().decode('utf-8')
|
||||||
|
|
||||||
|
if debug:
|
||||||
|
print("< " + repr(headers))
|
||||||
|
for line in body.splitlines():
|
||||||
|
print("< " + line)
|
||||||
|
|
||||||
|
return (headers, body)
|
||||||
|
|
||||||
def get_hrefmap(conn, uid=None):
|
def get_hrefmap(conn, uid=None):
|
||||||
headers = get_headers()
|
|
||||||
|
|
||||||
if uid:
|
if uid:
|
||||||
propfilter = '<c:prop-filter name="UID">' +\
|
propfilter = '<c:prop-filter name="UID">' +\
|
||||||
'<c:text-match collation="i;octet" >%s</c:text-match>' +\
|
'<c:text-match collation="i;octet" >%s</c:text-match>' +\
|
||||||
@ -99,16 +120,10 @@ def get_hrefmap(conn, uid=None):
|
|||||||
'<d:prop><d:getetag /></d:prop><c:filter>' +\
|
'<d:prop><d:getetag /></d:prop><c:filter>' +\
|
||||||
'<c:comp-filter name="VCALENDAR">' + propfilter + '</c:comp-filter>' +\
|
'<c:comp-filter name="VCALENDAR">' + propfilter + '</c:comp-filter>' +\
|
||||||
'</c:filter></c:calendar-query>'
|
'</c:filter></c:calendar-query>'
|
||||||
|
headers, body = remote_query("REPORT", path, {}, body)
|
||||||
conn.request("REPORT", path, body=body, headers=headers)
|
if not headers:
|
||||||
|
|
||||||
resp = conn.getresponse()
|
|
||||||
resp = resp.read().decode('utf-8')
|
|
||||||
|
|
||||||
if not resp:
|
|
||||||
return {}
|
return {}
|
||||||
|
root = etree.fromstring(body)
|
||||||
root = etree.fromstring(resp)
|
|
||||||
|
|
||||||
hrefmap = {}
|
hrefmap = {}
|
||||||
for node in root.findall(".//D:response", namespaces=nsmap):
|
for node in root.findall(".//D:response", namespaces=nsmap):
|
||||||
@ -132,12 +147,7 @@ def remote_wipe(conn):
|
|||||||
if dry_run:
|
if dry_run:
|
||||||
return
|
return
|
||||||
|
|
||||||
headers = get_headers()
|
remote_query("DELETE", path, headers, None)
|
||||||
conn.request("DELETE", path, headers=headers)
|
|
||||||
|
|
||||||
resp = conn.getresponse()
|
|
||||||
if resp:
|
|
||||||
resp.read()
|
|
||||||
|
|
||||||
def get_syncdb(fn):
|
def get_syncdb(fn):
|
||||||
if not os.path.exists(fn):
|
if not os.path.exists(fn):
|
||||||
@ -165,18 +175,13 @@ def save_syncdb(fn, syncdb):
|
|||||||
print("%s %s" % (etag, objhash), file=f)
|
print("%s %s" % (etag, objhash), file=f)
|
||||||
|
|
||||||
def push_object(conn, objhash):
|
def push_object(conn, objhash):
|
||||||
href = path + objhash + ".ics"
|
|
||||||
|
|
||||||
headers = get_headers()
|
|
||||||
body = calcurse_export(objhash)
|
body = calcurse_export(objhash)
|
||||||
conn.request("PUT", href, body=body, headers=headers)
|
headers, body = remote_query("PUT", path + objhash + ".ics", {}, body)
|
||||||
|
|
||||||
resp = conn.getresponse()
|
if not 'ETag' in headers:
|
||||||
if not resp:
|
|
||||||
return None
|
return None
|
||||||
resp.read()
|
|
||||||
|
|
||||||
etag = resp.getheader('ETag')
|
etag = headers['ETag']
|
||||||
while not etag:
|
while not etag:
|
||||||
hrefmap = get_hrefmap(conn, objhash)
|
hrefmap = get_hrefmap(conn, objhash)
|
||||||
if len(hrefmap.keys()) > 0:
|
if len(hrefmap.keys()) > 0:
|
||||||
@ -186,13 +191,8 @@ def push_object(conn, objhash):
|
|||||||
return etag
|
return etag
|
||||||
|
|
||||||
def remove_remote_object(conn, etag, href):
|
def remove_remote_object(conn, etag, href):
|
||||||
headers = get_headers()
|
headers = { 'If-Match' : '"' + etag + '"' }
|
||||||
headers['If-Match'] = '"' + etag + '"'
|
remote_query("DELETE", href, headers, None)
|
||||||
conn.request("DELETE", href, headers=headers)
|
|
||||||
|
|
||||||
resp = conn.getresponse()
|
|
||||||
if resp:
|
|
||||||
resp.read()
|
|
||||||
|
|
||||||
def push_objects(conn, syncdb, hrefmap):
|
def push_objects(conn, syncdb, hrefmap):
|
||||||
objhashes = calcurse_hashset()
|
objhashes = calcurse_hashset()
|
||||||
@ -240,19 +240,14 @@ def pull_objects(conn, syncdb, hrefmap):
|
|||||||
orphan = set(syncdb.keys()) - set(hrefmap.keys())
|
orphan = set(syncdb.keys()) - set(hrefmap.keys())
|
||||||
|
|
||||||
# Download and import new objects from the server.
|
# Download and import new objects from the server.
|
||||||
headers = get_headers()
|
|
||||||
body = '<c:calendar-multiget xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">' +\
|
body = '<c:calendar-multiget xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">' +\
|
||||||
'<d:prop><d:getetag /><c:calendar-data /></d:prop>'
|
'<d:prop><d:getetag /><c:calendar-data /></d:prop>'
|
||||||
for etag in missing:
|
for etag in missing:
|
||||||
body += '<d:href>%s</d:href>' % (hrefmap[etag])
|
body += '<d:href>%s</d:href>' % (hrefmap[etag])
|
||||||
body += '</c:calendar-multiget>'
|
body += '</c:calendar-multiget>'
|
||||||
conn.request("REPORT", path, body=body, headers=headers)
|
headers, body = remote_query("REPORT", path, {}, body)
|
||||||
|
|
||||||
resp = conn.getresponse()
|
root = etree.fromstring(body)
|
||||||
if not resp:
|
|
||||||
return
|
|
||||||
resp = resp.read().decode('utf-8')
|
|
||||||
root = etree.fromstring(resp)
|
|
||||||
|
|
||||||
added = deleted = 0
|
added = deleted = 0
|
||||||
|
|
||||||
@ -316,6 +311,8 @@ parser.add_argument('--syncdb', action='store', dest='syncdbfn',
|
|||||||
parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
|
parser.add_argument('-v', '--verbose', action='store_true', dest='verbose',
|
||||||
default=False,
|
default=False,
|
||||||
help='print status messages to stdout')
|
help='print status messages to stdout')
|
||||||
|
parser.add_argument('--debug', action='store_true', dest='debug',
|
||||||
|
default=False, help='print debug messages to stdout')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
init = args.init is not None
|
init = args.init is not None
|
||||||
@ -323,6 +320,7 @@ configfn = args.configfn
|
|||||||
lockfn = args.lockfn
|
lockfn = args.lockfn
|
||||||
syncdbfn = args.syncdbfn
|
syncdbfn = args.syncdbfn
|
||||||
verbose = args.verbose
|
verbose = args.verbose
|
||||||
|
debug = args.debug
|
||||||
|
|
||||||
# Read configuration.
|
# Read configuration.
|
||||||
config = configparser.RawConfigParser()
|
config = configparser.RawConfigParser()
|
||||||
@ -354,6 +352,9 @@ else:
|
|||||||
if not verbose and config.has_option('General', 'Verbose'):
|
if not verbose and config.has_option('General', 'Verbose'):
|
||||||
verbose = config.getboolean('General', 'Verbose')
|
verbose = config.getboolean('General', 'Verbose')
|
||||||
|
|
||||||
|
if not debug and config.has_option('General', 'Debug'):
|
||||||
|
debug = config.getboolean('General', 'Debug')
|
||||||
|
|
||||||
if config.has_option('Auth', 'UserName'):
|
if config.has_option('Auth', 'UserName'):
|
||||||
username = config.get('Auth', 'UserName')
|
username = config.get('Auth', 'UserName')
|
||||||
else:
|
else:
|
||||||
@ -388,6 +389,8 @@ open(lockfn, 'w')
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Connect to the server via HTTPs.
|
# Connect to the server via HTTPs.
|
||||||
|
if verbose:
|
||||||
|
print('Connecting to ' + hostname + '...')
|
||||||
if insecure_ssl:
|
if insecure_ssl:
|
||||||
try:
|
try:
|
||||||
context = ssl._create_unverified_context()
|
context = ssl._create_unverified_context()
|
||||||
@ -400,8 +403,6 @@ try:
|
|||||||
conn = http.client.HTTPSConnection(hostname)
|
conn = http.client.HTTPSConnection(hostname)
|
||||||
else:
|
else:
|
||||||
conn = http.client.HTTPSConnection(hostname)
|
conn = http.client.HTTPSConnection(hostname)
|
||||||
if verbose:
|
|
||||||
print('Connecting to ' + hostname + '...')
|
|
||||||
|
|
||||||
if init:
|
if init:
|
||||||
# In initialization mode, start with an empty synchronization database.
|
# In initialization mode, start with an empty synchronization database.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user