Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/jarabe/journal/webdavmanager.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/jarabe/journal/webdavmanager.py')
-rw-r--r--src/jarabe/journal/webdavmanager.py256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/jarabe/journal/webdavmanager.py b/src/jarabe/journal/webdavmanager.py
new file mode 100644
index 0000000..6cd0713
--- /dev/null
+++ b/src/jarabe/journal/webdavmanager.py
@@ -0,0 +1,256 @@
+from gettext import gettext as _
+
+import os
+import sys
+
+import gobject
+import simplejson
+import shutil
+
+from webdav.Connection import AuthorizationError, WebdavError
+from webdav.WebdavClient import CollectionStorer
+
+def get_key_from_resource(resource):
+ return resource.path
+
+def ensure_correct_remote_webdav_hierarchy(remote_webdav_share_resources,
+ remote_webdav_share_collections):
+ pass
+ #assert len(remote_webdav_share_collections.keys()) == 1
+
+class WebDavUrlManager(gobject.GObject):
+ """
+ This class holds all data, relevant to a WebDavUrl.
+
+ One thing must be noted, that a valid WebDavUrl is the one which
+ may contain zero or more resources (files), or zero or more
+ collections (directories).
+
+ Thus, following are valid WebDavUrls ::
+
+ dav://1.2.3.4/webdav
+ dav://1.2.3.4/webdav/dir_1
+ dav://1.2.3.4/webdav/dir_1/dir_2
+
+ but following are not ::
+
+ dav://1.2.3.4/webdav/a.txt
+ dav://1.2.3.4/webdav/dir_1/b.jpg
+ dav://1.2.3.4/webdab/dir_1/dir_2/c.avi
+ """
+
+ def __init__(self, WebDavUrl, username, password):
+ self._WebDavUrl = WebDavUrl
+ self._username = username
+ self._password = password
+
+ def _get_key_from_resource(self, resource):
+ return resource.path.encode(sys.getfilesystemencoding())
+
+ def _get_number_of_collections(self):
+ return len(self._remote_webdav_share_collections)
+
+ def _get_resources_dict(self):
+ return self._remote_webdav_share_resources
+
+ def _get_collections_dict(self):
+ return self._remote_webdav_share_collections
+
+ def _get_resource_by_key(self, key):
+ return self._remote_webdav_share_resources[key]['resource']
+
+ def _get_metadata_list(self):
+ metadata_list = []
+ for key in self._remote_webdav_share_resources.keys():
+ metadata_list.append(self._remote_webdav_share_resources[key]['metadata'])
+ return metadata_list
+
+ def _get_live_properties(self, resource_key):
+ resource_container = self._remote_webdav_share_resources[resource_key]
+ return resource_container['webdav-properties']
+
+ def _set_metadata_for_resource(self, key, metadata):
+ self._remote_webdav_share_resources[key]['metadata'] = metadata
+
+ def _fetch_resources_and_collections(self):
+ webdavConnection = CollectionStorer(self._WebDavUrl, validateResourceNames=False)
+
+ authFailures = 0
+ while authFailures < 2:
+ try:
+ self._remote_webdav_share_resources = {}
+ self._remote_webdav_share_collections = {}
+
+ try:
+ self._collection_contents = webdavConnection.getCollectionContents()
+ for resource, properties in self._collection_contents:
+ try:
+ key = self._get_key_from_resource(resource)
+ selected_dict = None
+
+ if properties.getResourceType() == 'resource':
+ selected_dict = self._remote_webdav_share_resources
+ else:
+ selected_dict = self._remote_webdav_share_collections
+
+ selected_dict[key] = {}
+ selected_dict[key]['resource'] = resource
+ selected_dict[key]['webdav-properties'] = properties
+ except UnicodeEncodeError:
+ print("Cannot encode resource path or properties.")
+
+ return True
+
+ except WebdavError, e:
+ # Note that, we need to deal with all errors,
+ # except "AuthorizationError", as that is not
+ # really an error from our perspective.
+ if not type(e) == AuthorizationError:
+ from jarabe.journal.journalactivity import get_journal
+
+ error_message = e
+ get_journal()._volume_error_cb(None, error_message,_('Error'))
+
+ # Simply return, in case of connection-not-available.
+ return False
+
+ else:
+ # If this indeed is an Authorization Error,
+ # re-raise it, so that it is caught by the outer
+ # "except" block.
+ raise e
+
+
+ except AuthorizationError, e:
+ if self._username is None or self._password is None:
+ raise Exception("WebDav username or password is None. Please specify appropriate values.")
+
+ if e.authType == "Basic":
+ webdavConnection.connection.addBasicAuthorization(self._username, self._password)
+ elif e.authType == "Digest":
+ info = parseDigestAuthInfo(e.authInfo)
+ webdavConnection.connection.addDigestAuthorization(self._username, self._password, realm=info["realm"], qop=info["qop"], nonce=info["nonce"])
+ else:
+ raise
+ authFailures += 1
+
+ return False
+
+webdav_manager = {}
+
+
+def get_resource_by_ip_address_and_resource_key(ip_address, key):
+ global webdav_manager
+
+ if ip_address in webdav_manager.keys():
+ root_webdav = webdav_manager[ip_address]
+ resources_dict = root_webdav._get_resources_dict()
+ resource_dict = resources_dict[key]
+ resource = resource_dict['resource']
+
+ return resource
+
+
+def get_remote_webdav_share_metadata(ip_address):
+ protocol = 'dav://'
+
+ root_webdav_url = '/webdav'
+
+ complete_root_url = protocol + ip_address + root_webdav_url
+
+ root_webdav = WebDavUrlManager(complete_root_url, 'test', 'olpc')
+ if root_webdav._fetch_resources_and_collections() is False:
+ # Return empty metadata list.
+ return []
+
+ # Keep reference to the "WebDavUrlManager", keyed by IP-Address.
+ global webdav_manager
+ webdav_manager[ip_address] = root_webdav
+
+
+ # Assert that the number of collections is only one at this url
+ # (i.e. only ".Sugar-Metadata" is present).
+ assert root_webdav._get_number_of_collections() == 1
+
+ root_sugar_metadata_url = root_webdav_url + '/.Sugar-Metadata'
+
+ complete_root_sugar_metadata_url = protocol + ip_address + root_sugar_metadata_url
+ root_webdav_sugar_metadata = WebDavUrlManager(complete_root_sugar_metadata_url, 'test', 'olpc')
+ if root_webdav_sugar_metadata._fetch_resources_and_collections() is False:
+ # Return empty metadata list.
+ return []
+
+ # assert that the number of collections is zero at this url.
+ assert root_webdav_sugar_metadata._get_number_of_collections() == 0
+
+ # Now. associate sugar-metadata with each of the "root-webdav"
+ # resource.
+ root_webdav_resources = root_webdav._get_resources_dict()
+ root_webdav_sugar_metadata_resources = root_webdav_sugar_metadata._get_resources_dict()
+
+ # Prepare the metadata-download folder.
+ downloaded_data_root_dir = '/tmp/' + ip_address
+ downloaded_metadata_file_dir = downloaded_data_root_dir + '/.Sugar-Metadata'
+ if os.path.isdir(downloaded_data_root_dir):
+ shutil.rmtree(downloaded_data_root_dir)
+ os.makedirs(downloaded_metadata_file_dir)
+
+ for root_webdav_resource_name in root_webdav_resources.keys():
+ """
+ root_webdav_resource_name is of the type ::
+
+ /webdav/a.txt
+ """
+ split_tokens_array = root_webdav_resource_name.split('/')
+
+ # This will provide us with "a.txt"
+ basename = split_tokens_array[len(split_tokens_array) - 1]
+
+ # This will provide us with "a.txt.metadata"
+ sugar_metadata_basename = basename + '.metadata'
+
+ # Thus will provide us with "/webdav/.Sugar-Metadata/a.txt.metadata"
+ sugar_metadata_url = root_sugar_metadata_url + '/' + sugar_metadata_basename
+
+ # Ensure that "sugar_metadata_url" is present as one of the
+ # keys in "root_webdav_sugar_metadata_resources"
+ assert sugar_metadata_url in root_webdav_sugar_metadata_resources.keys()
+
+ # Now download the metadata file, read its contents, and store
+ # the metadata in memory.
+ # It is assumed that the metadata-file is small enough to be
+ # read in one call to "read".
+
+ downloaded_metadata_file_path = downloaded_metadata_file_dir + '/' + sugar_metadata_basename
+ metadata_resource = root_webdav_sugar_metadata._get_resource_by_key(sugar_metadata_url)
+ metadata_resource.downloadFile(downloaded_metadata_file_path)
+
+ file_pointer = open(downloaded_metadata_file_path)
+ metadata = eval(file_pointer.read())
+ file_pointer.close()
+
+ # Very critical.
+ # 1. CRITICAL ONE:
+ # Fill in the uid.
+ # Note that the file is not physically present.
+ metadata['uid'] = downloaded_data_root_dir + '/' + basename
+
+ # 2. CRITICAL TWO:
+ # Fill in the properties, that can only be done by reading
+ # in the webdav-properties.
+ live_properties = root_webdav._get_live_properties(root_webdav_resource_name)
+ metadata['filesize'] = live_properties.getContentLength()
+ metadata['timestamp'] = live_properties.getLastModified()
+ metadata['creation_time'] = live_properties.getCreationDate()
+
+ # Now, write this to the metadata-file, so that
+ # webdav-properties get gelled into sugar-metadata.
+
+ file_pointer = open(downloaded_metadata_file_path, 'w')
+ file_pointer.write(simplejson.dumps(metadata))
+ file_pointer.close()
+
+ root_webdav._set_metadata_for_resource(root_webdav_resource_name,
+ metadata)
+
+ return root_webdav._get_metadata_list()