diff --git a/webdav_upload/upload.py b/webdav_upload/upload.py
index 96751acdf8e7e99dcc5fcb36530bc7b6f60673f0..b42dd30992ea073a634753e4094968abd30aedb4 100644
--- a/webdav_upload/upload.py
+++ b/webdav_upload/upload.py
@@ -1,8 +1,61 @@
 import argparse
 import logging
 import os
+import time
 from urllib.parse import urlparse
-from webdav3.client import Client
+from webdav3.client import Client, Urn, RemoteResourceNotFound
+
+TIME_FMT = '%a, %d %b %Y %H:%M:%S %Z'
+
+
+def upload(client, local_path, remote_path, do_force, do_delete):
+    if os.path.isdir(local_path):
+        upload_directory(client, local_path, remote_path, do_force, do_delete)
+    else:
+        upload_file(client, local_path, remote_path, do_force)
+
+
+def upload_directory(client, local_path, remote_path, do_force, do_delete):
+    client.mkdir(remote_path)
+
+    remote_files = set(x.rstrip('/') for x in client.list(remote_path))
+    
+    urn = Urn(remote_path, directory=True)
+    for resource_name in os.listdir(local_path):
+        _remote_path = "{parent}{name}".format(parent=urn.path(), name=resource_name).replace('\\', '')
+        _local_path = os.path.join(local_path, resource_name)
+        upload(client, _local_path, _remote_path, do_force, do_delete)
+        remote_files.discard(resource_name)
+
+    if remote_files:
+        for f in remote_files:
+            _remote_path = "{parent}{name}".format(parent=urn.path(), name=f).replace('\\', '')
+            logging.info('deleting %s' % _remote_path)
+            client.clean(_remote_path)
+
+
+def upload_file(client, local_path, remote_path, do_force):
+    if not do_force:
+        # Stat remote path and compare size and mtime.
+        local_stat = os.stat(local_path)
+        try:
+            remote_stat = client.info(remote_path)
+            local_mtime = time.mktime(time.gmtime(local_stat.st_mtime))
+            remote_mtime = time.mktime(time.strptime(remote_stat['modified'], TIME_FMT))
+            if int(remote_stat['size']) != local_stat.st_size:
+                logging.info('%s has changed (size differs)', remote_path)
+            elif remote_mtime <= local_mtime:
+                logging.info('%s has changed (local file is newer)', remote_path)
+            else:
+                logging.info('%s is unchanged, skipping...', remote_path)
+                return
+        except RemoteResourceNotFound:
+            pass
+
+    logging.info('uploading %s to %s', local_path, remote_path)
+    urn = Urn(remote_path)
+    with open(local_path, 'rb') as fd:
+        client.execute_request(action='upload', path=urn.quote(), data=fd)
 
 
 def main():
@@ -24,7 +77,10 @@ def main():
         'like "https://www.autistici.org/dav/myuser/")')
     parser.add_argument(
         '--force', action='store_true',
-        help='always overwrite remote files')
+        help='always upload files even if they seem to not have changed')
+    parser.add_argument(
+        '--delete', action='store_true',
+        help='delete remote files that do not exist locally')
     parser.add_argument(
         '--verbose', action='store_true',
         help='enable WebDAV logging')
@@ -39,7 +95,7 @@ def main():
 
     parsed_url = urlparse(args.url)
 
-    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.ERROR)
+    logging.basicConfig(level=logging.INFO if args.verbose else logging.ERROR)
     logging.getLogger('urllib3.connectionpool').setLevel(logging.ERROR)
 
     client = Client({
@@ -49,12 +105,8 @@ def main():
         'webdav_root': parsed_url.path,
         'webdav_verbose': True,
     })
-    if args.force:
-        client.upload_sync(args.dstdir, args.srcdir)
-    else:
-        client.push(
-            remote_directory=args.dstdir,
-            local_directory=args.srcdir)
+
+    upload(client, args.srcdir, args.dstdir, args.force, args.delete)
 
 
 if __name__ == '__main__':