summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG4
-rw-r--r--client/pkg/requirements.pip2
-rw-r--r--client/src/leap/soledad/client/__init__.py290
-rw-r--r--client/src/leap/soledad/client/auth.py24
-rw-r--r--client/src/leap/soledad/client/crypto.py62
-rw-r--r--client/src/leap/soledad/client/shared_db.py58
-rw-r--r--client/src/leap/soledad/client/sqlcipher.py290
-rw-r--r--client/src/leap/soledad/client/target.py132
8 files changed, 452 insertions, 410 deletions
diff --git a/CHANGELOG b/CHANGELOG
index d400fc52..a7254c40 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+0.4.1 Oct 4:
+Client:
+ o Save only UTF8 strings. Related to #3660.
+
0.4.0 Sep 20:
Client:
o Remove redundant logging when creating data dirs.
diff --git a/client/pkg/requirements.pip b/client/pkg/requirements.pip
index df6ddb94..8733f320 100644
--- a/client/pkg/requirements.pip
+++ b/client/pkg/requirements.pip
@@ -20,3 +20,5 @@ oauth
# pysqlite should not be a dep, see #2945
pysqlite
+
+cchardet \ No newline at end of file
diff --git a/client/src/leap/soledad/client/__init__.py b/client/src/leap/soledad/client/__init__.py
index 4c6a41fc..13a3b68f 100644
--- a/client/src/leap/soledad/client/__init__.py
+++ b/client/src/leap/soledad/client/__init__.py
@@ -32,6 +32,8 @@ import socket
import ssl
import urlparse
+import cchardet
+
from hashlib import sha256
from u1db.remote import http_client
@@ -226,25 +228,26 @@ class Soledad(object):
"""
Initialize configuration, cryptographic keys and dbs.
- @param uuid: User's uuid.
- @type uuid: str
- @param passphrase: The passphrase for locking and unlocking encryption
- secrets for local and remote storage.
- @type passphrase: str
- @param secrets_path: Path for storing encrypted key used for
- symmetric encryption.
- @type secrets_path: str
- @param local_db_path: Path for local encrypted storage db.
- @type local_db_path: str
- @param server_url: URL for Soledad server. This is used either to sync
+ :param uuid: User's uuid.
+ :type uuid: str
+ :param passphrase: The passphrase for locking and unlocking encryption
+ secrets for local and remote storage.
+ :type passphrase: str
+ :param secrets_path: Path for storing encrypted key used for
+ symmetric encryption.
+ :type secrets_path: str
+ :param local_db_path: Path for local encrypted storage db.
+ :type local_db_path: str
+ :param server_url: URL for Soledad server. This is used either to sync
with the user's remote db and to interact with the shared recovery
database.
- @type server_url: str
- @param cert_file: Path to the SSL certificate to use in the
- connection to the server_url.
- @type cert_file: str
- @param auth_token: Authorization token for accessing remote databases.
- @type auth_token: str
+ :type server_url: str
+ :param cert_file: Path to the certificate of the ca used
+ to validate the SSL certificate used by the remote
+ soledad server.
+ :type cert_file: str
+ :param auth_token: Authorization token for accessing remote databases.
+ :type auth_token: str
"""
# get config params
self._uuid = uuid
@@ -339,7 +342,7 @@ class Soledad(object):
"""
Create work directories.
- @raise OSError: in case file exists and is not a dir.
+ :raise OSError: in case file exists and is not a dir.
"""
paths = map(
lambda x: os.path.dirname(x),
@@ -418,8 +421,8 @@ class Soledad(object):
Storage secret is encrypted before being stored. This method decrypts
and returns the stored secret.
- @return: The storage secret.
- @rtype: str
+ :return: The storage secret.
+ :rtype: str
"""
# calculate the encryption key
key = scrypt.hash(
@@ -478,8 +481,8 @@ class Soledad(object):
"""
Return whether there is a storage secret available for use or not.
- @return: Whether there's a storage secret for symmetric encryption.
- @rtype: bool
+ :return: Whether there's a storage secret for symmetric encryption.
+ :rtype: bool
"""
if self._secret_id is None or self._secret_id not in self._secrets:
try:
@@ -515,8 +518,8 @@ class Soledad(object):
}
}
- @return: The id of the generated secret.
- @rtype: str
+ :return: The id of the generated secret.
+ :rtype: str
"""
signal(SOLEDAD_CREATING_KEYS, self._uuid)
# generate random secret
@@ -571,10 +574,10 @@ class Soledad(object):
"""
Change the passphrase that encrypts the storage secret.
- @param new_passphrase: The new passphrase.
- @type new_passphrase: str
+ :param new_passphrase: The new passphrase.
+ :type new_passphrase: str
- @raise NoStorageSecret: Raised if there's no storage secret available.
+ :raise NoStorageSecret: Raised if there's no storage secret available.
"""
# maybe we want to add more checks to guarantee passphrase is
# reasonable?
@@ -616,8 +619,8 @@ class Soledad(object):
Calculate a hash for storing/retrieving key material on shared
database, based on user's uuid.
- @return: the hash
- @rtype: str
+ :return: the hash
+ :rtype: str
"""
return sha256(
'%s%s' % (
@@ -639,8 +642,8 @@ class Soledad(object):
Retrieve the document with encrypted key material from the shared
database.
- @return: a document with encrypted key material in its contents
- @rtype: SoledadDocument
+ :return: a document with encrypted key material in its contents
+ :rtype: SoledadDocument
"""
signal(SOLEDAD_DOWNLOADING_KEYS, self._uuid)
db = self._shared_db()
@@ -687,11 +690,11 @@ class Soledad(object):
"""
Update a document in the local encrypted database.
- @param doc: the document to update
- @type doc: SoledadDocument
+ :param doc: the document to update
+ :type doc: SoledadDocument
- @return: the new revision identifier for the document
- @rtype: str
+ :return: the new revision identifier for the document
+ :rtype: str
"""
return self._db.put_doc(doc)
@@ -699,11 +702,11 @@ class Soledad(object):
"""
Delete a document from the local encrypted database.
- @param doc: the document to delete
- @type doc: SoledadDocument
+ :param doc: the document to delete
+ :type doc: SoledadDocument
- @return: the new revision identifier for the document
- @rtype: str
+ :return: the new revision identifier for the document
+ :rtype: str
"""
return self._db.delete_doc(doc)
@@ -711,15 +714,15 @@ class Soledad(object):
"""
Retrieve a document from the local encrypted database.
- @param doc_id: the unique document identifier
- @type doc_id: str
- @param include_deleted: if True, deleted documents will be
- returned with empty content; otherwise asking for a deleted
- document will return None
- @type include_deleted: bool
+ :param doc_id: the unique document identifier
+ :type doc_id: str
+ :param include_deleted: if True, deleted documents will be
+ returned with empty content; otherwise asking
+ for a deleted document will return None
+ :type include_deleted: bool
- @return: the document object or None
- @rtype: SoledadDocument
+ :return: the document object or None
+ :rtype: SoledadDocument
"""
return self._db.get_doc(doc_id, include_deleted=include_deleted)
@@ -728,15 +731,15 @@ class Soledad(object):
"""
Get the content for many documents.
- @param doc_ids: a list of document identifiers
- @type doc_ids: list
- @param check_for_conflicts: if set False, then the conflict check will
+ :param doc_ids: a list of document identifiers
+ :type doc_ids: list
+ :param check_for_conflicts: if set False, then the conflict check will
be skipped, and 'None' will be returned instead of True/False
- @type check_for_conflicts: bool
+ :type check_for_conflicts: bool
- @return: iterable giving the Document object for each document id
+ :return: iterable giving the Document object for each document id
in matching doc_ids order.
- @rtype: generator
+ :rtype: generator
"""
return self._db.get_docs(doc_ids,
check_for_conflicts=check_for_conflicts,
@@ -745,28 +748,59 @@ class Soledad(object):
def get_all_docs(self, include_deleted=False):
"""Get the JSON content for all documents in the database.
- @param include_deleted: If set to True, deleted documents will be
- returned with empty content. Otherwise deleted documents will not
- be included in the results.
- @return: (generation, [Document])
- The current generation of the database, followed by a list of all
- the documents in the database.
+ :param include_deleted: If set to True, deleted documents will be
+ returned with empty content. Otherwise deleted
+ documents will not be included in the results.
+ :return: (generation, [Document])
+ The current generation of the database, followed by a list of
+ all the documents in the database.
"""
return self._db.get_all_docs(include_deleted)
+ def _convert_to_utf8(self, content):
+ """
+ Converts content to utf8 (or all the strings in content)
+
+ NOTE: Even though this method supports any type, it will
+ currently ignore contents of lists, tuple or any other
+ iterable than dict. We don't need support for these at the
+ moment
+
+ :param content: content to convert
+ :type content: object
+
+ :rtype: object
+ """
+
+ if isinstance(content, unicode):
+ return content
+ elif isinstance(content, str):
+ try:
+ result = cchardet.detect(content)
+ content = content.decode(result["encoding"]).encode("utf-8")\
+ .decode("utf-8")
+ except UnicodeError:
+ pass
+ return content
+ else:
+ if isinstance(content, dict):
+ for key in content.keys():
+ content[key] = self._convert_to_utf8(content[key])
+ return content
+
def create_doc(self, content, doc_id=None):
"""
Create a new document in the local encrypted database.
- @param content: the contents of the new document
- @type content: dict
- @param doc_id: an optional identifier specifying the document id
- @type doc_id: str
+ :param content: the contents of the new document
+ :type content: dict
+ :param doc_id: an optional identifier specifying the document id
+ :type doc_id: str
- @return: the new document
- @rtype: SoledadDocument
+ :return: the new document
+ :rtype: SoledadDocument
"""
- return self._db.create_doc(content, doc_id=doc_id)
+ return self._db.create_doc(self._convert_to_utf8(content), doc_id=doc_id)
def create_doc_from_json(self, json, doc_id=None):
"""
@@ -778,12 +812,12 @@ class Soledad(object):
If the database specifies a maximum document size and the document
exceeds it, create will fail and raise a DocumentTooBig exception.
- @param json: The JSON document string
- @type json: str
- @param doc_id: An optional identifier specifying the document id.
- @type doc_id:
- @return: The new cocument
- @rtype: SoledadDocument
+ :param json: The JSON document string
+ :type json: str
+ :param doc_id: An optional identifier specifying the document id.
+ :type doc_id:
+ :return: The new cocument
+ :rtype: SoledadDocument
"""
return self._db.create_doc_from_json(json, doc_id=doc_id)
@@ -796,11 +830,11 @@ class Soledad(object):
Creating an index will block until the expressions have been evaluated
and the index generated.
- @param index_name: A unique name which can be used as a key prefix
- @type index_name: str
- @param index_expressions: index expressions defining the index
- information.
- @type index_expressions: dict
+ :param index_name: A unique name which can be used as a key prefix
+ :type index_name: str
+ :param index_expressions: index expressions defining the index
+ information.
+ :type index_expressions: dict
Examples:
@@ -816,8 +850,8 @@ class Soledad(object):
"""
Remove a named index.
- @param index_name: The name of the index we are removing
- @type index_name: str
+ :param index_name: The name of the index we are removing
+ :type index_name: str
"""
if self._db:
return self._db.delete_index(index_name)
@@ -826,8 +860,8 @@ class Soledad(object):
"""
List the definitions of all known indexes.
- @return: A list of [('index-name', ['field', 'field2'])] definitions.
- @rtype: list
+ :return: A list of [('index-name', ['field', 'field2'])] definitions.
+ :rtype: list
"""
if self._db:
return self._db.list_indexes()
@@ -843,14 +877,14 @@ class Soledad(object):
It is also possible to append a '*' to the last supplied value (eg
'val*', '*', '*' or 'val', 'val*', '*', but not 'val*', 'val', '*')
- @param index_name: The index to query
- @type index_name: str
- @param key_values: values to match. eg, if you have
- an index with 3 fields then you would have:
- get_from_index(index_name, val1, val2, val3)
- @type key_values: tuple
- @return: List of [Document]
- @rtype: list
+ :param index_name: The index to query
+ :type index_name: str
+ :param key_values: values to match. eg, if you have
+ an index with 3 fields then you would have:
+ get_from_index(index_name, val1, val2, val3)
+ :type key_values: tuple
+ :return: List of [Document]
+ :rtype: list
"""
if self._db:
return self._db.get_from_index(index_name, *key_values)
@@ -869,18 +903,18 @@ class Soledad(object):
possible to append a '*' to the last supplied value (eg 'val*', '*',
'*' or 'val', 'val*', '*', but not 'val*', 'val', '*')
- @param index_name: The index to query
- @type index_name: str
- @param start_values: tuples of values that define the lower bound of
+ :param index_name: The index to query
+ :type index_name: str
+ :param start_values: tuples of values that define the lower bound of
the range. eg, if you have an index with 3 fields then you would
have: (val1, val2, val3)
- @type start_values: tuple
- @param end_values: tuples of values that define the upper bound of the
+ :type start_values: tuple
+ :param end_values: tuples of values that define the upper bound of the
range. eg, if you have an index with 3 fields then you would have:
(val1, val2, val3)
- @type end_values: tuple
- @return: List of [Document]
- @rtype: list
+ :type end_values: tuple
+ :return: List of [Document]
+ :rtype: list
"""
if self._db:
return self._db.get_range_from_index(
@@ -890,10 +924,10 @@ class Soledad(object):
"""
Return all keys under which documents are indexed in this index.
- @param index_name: The index to query
- @type index_name: str
- @return: [] A list of tuples of indexed keys.
- @rtype: list
+ :param index_name: The index to query
+ :type index_name: str
+ :return: [] A list of tuples of indexed keys.
+ :rtype: list
"""
if self._db:
return self._db.get_index_keys(index_name)
@@ -902,11 +936,11 @@ class Soledad(object):
"""
Get the list of conflicts for the given document.
- @param doc_id: the document id
- @type doc_id: str
+ :param doc_id: the document id
+ :type doc_id: str
- @return: a list of the document entries that are conflicted
- @rtype: list
+ :return: a list of the document entries that are conflicted
+ :rtype: list
"""
if self._db:
return self._db.get_doc_conflicts(doc_id)
@@ -915,11 +949,11 @@ class Soledad(object):
"""
Mark a document as no longer conflicted.
- @param doc: a document with the new content to be inserted.
- @type doc: SoledadDocument
- @param conflicted_doc_revs: a list of revisions that the new content
- supersedes.
- @type conflicted_doc_revs: list
+ :param doc: a document with the new content to be inserted.
+ :type doc: SoledadDocument
+ :param conflicted_doc_revs: a list of revisions that the new content
+ supersedes.
+ :type conflicted_doc_revs: list
"""
if self._db:
return self._db.resolve_doc(doc, conflicted_doc_revs)
@@ -928,12 +962,12 @@ class Soledad(object):
"""
Synchronize the local encrypted replica with a remote replica.
- @param url: the url of the target replica to sync with
- @type url: str
+ :param url: the url of the target replica to sync with
+ :type url: str
- @return: the local generation before the synchronisation was
+ :return: the local generation before the synchronisation was
performed.
- @rtype: str
+ :rtype: str
"""
if self._db:
local_gen = self._db.sync(
@@ -946,11 +980,11 @@ class Soledad(object):
"""
Return if local db replica differs from remote url's replica.
- @param url: The remote replica to compare with local replica.
- @type url: str
+ :param url: The remote replica to compare with local replica.
+ :type url: str
- @return: Whether remote replica and local replica differ.
- @rtype: bool
+ :return: Whether remote replica and local replica differ.
+ :rtype: bool
"""
target = SoledadSyncTarget(url, creds=self._creds, crypto=self._crypto)
info = target.get_sync_info(self._db._get_replica_uid())
@@ -972,8 +1006,8 @@ class Soledad(object):
'token': '<token>'
}
- @param token: The authentication token.
- @type token: str
+ :param token: The authentication token.
+ :type token: str
"""
self._creds = {
'token': {
@@ -1004,11 +1038,11 @@ class Soledad(object):
self.UUID_KEY: '<uuid>', # (optional)
}
- @param include_uuid: Should the uuid be included?
- @type include_uuid: bool
+ :param include_uuid: Should the uuid be included?
+ :type include_uuid: bool
- @return: The recovery document.
- @rtype: dict
+ :return: The recovery document.
+ :rtype: dict
"""
data = {self.STORAGE_SECRETS_KEY: self._secrets}
if include_uuid:
@@ -1027,8 +1061,8 @@ class Soledad(object):
self.UUID_KEY: '<uuid>', # (optional)
}
- @param data: The recovery document.
- @type data: dict
+ :param data: The recovery document.
+ :type data: dict
"""
# include new secrets in our secret pool.
for secret_id, secret_data in data[self.STORAGE_SECRETS_KEY].items():
@@ -1101,7 +1135,9 @@ SOLEDAD_TIMEOUT = 10
class VerifiedHTTPSConnection(httplib.HTTPSConnection):
- """HTTPSConnection verifying server side certificates."""
+ """
+ HTTPSConnection verifying server side certificates.
+ """
# derived from httplib.py
def connect(self):
diff --git a/client/src/leap/soledad/client/auth.py b/client/src/leap/soledad/client/auth.py
index 3cd6dabe..d85e3ba6 100644
--- a/client/src/leap/soledad/client/auth.py
+++ b/client/src/leap/soledad/client/auth.py
@@ -37,10 +37,10 @@ class TokenBasedAuth(object):
"""
Store given credentials so we can sign the request later.
- @param uuid: The user's uuid.
- @type uuid: str
- @param token: The authentication token.
- @type token: str
+ :param uuid: The user's uuid.
+ :type uuid: str
+ :param token: The authentication token.
+ :type token: str
"""
self._creds = {'token': (uuid, token)}
@@ -51,15 +51,15 @@ class TokenBasedAuth(object):
[('Authorization', 'Token <base64 encoded creds')]
- @param method: The HTTP method.
- @type method: str
- @param url_query: The URL query string.
- @type url_query: str
- @param params: A list with encoded query parameters.
- @type param: list
+ :param method: The HTTP method.
+ :type method: str
+ :param url_query: The URL query string.
+ :type url_query: str
+ :param params: A list with encoded query parameters.
+ :type param: list
- @return: The Authorization header.
- @rtype: list of tuple
+ :return: The Authorization header.
+ :rtype: list of tuple
"""
if 'token' in self._creds:
uuid, token = self._creds['token']
diff --git a/client/src/leap/soledad/client/crypto.py b/client/src/leap/soledad/client/crypto.py
index 9fcff8e9..a6372107 100644
--- a/client/src/leap/soledad/client/crypto.py
+++ b/client/src/leap/soledad/client/crypto.py
@@ -70,8 +70,8 @@ class SoledadCrypto(object):
"""
Initialize the crypto object.
- @param soledad: A Soledad instance for key lookup.
- @type soledad: leap.soledad.Soledad
+ :param soledad: A Soledad instance for key lookup.
+ :type soledad: leap.soledad.Soledad
"""
self._soledad = soledad
@@ -82,15 +82,15 @@ class SoledadCrypto(object):
Currently, the only encryption method supported is AES-256 CTR mode.
- @param data: The data to be encrypted.
- @type data: str
- @param key: The key used to encrypt C{data} (must be 256 bits long).
- @type key: str
- @param method: The encryption method to use.
- @type method: str
+ :param data: The data to be encrypted.
+ :type data: str
+ :param key: The key used to encrypt C{data} (must be 256 bits long).
+ :type key: str
+ :param method: The encryption method to use.
+ :type method: str
- @return: A tuple with the initial value and the encrypted data.
- @rtype: (long, str)
+ :return: A tuple with the initial value and the encrypted data.
+ :rtype: (long, str)
"""
soledad_assert_type(key, str)
@@ -119,17 +119,17 @@ class SoledadCrypto(object):
Currently, the only encryption method supported is AES-256 CTR mode.
- @param data: The data to be decrypted.
- @type data: str
- @param key: The key used to decrypt C{data} (must be 256 bits long).
- @type key: str
- @param method: The encryption method to use.
- @type method: str
- @param kwargs: Other parameters specific to each encryption method.
- @type kwargs: dict
-
- @return: The decrypted data.
- @rtype: str
+ :param data: The data to be decrypted.
+ :type data: str
+ :param key: The key used to decrypt C{data} (must be 256 bits long).
+ :type key: str
+ :param method: The encryption method to use.
+ :type method: str
+ :param kwargs: Other parameters specific to each encryption method.
+ :type kwargs: dict
+
+ :return: The decrypted data.
+ :rtype: str
"""
soledad_assert_type(key, str)
# assert params
@@ -160,14 +160,14 @@ class SoledadCrypto(object):
secret stripped from the first MAC_KEY_LENGTH characters. The HMAC
message is C{doc_id}.
- @param doc_id: The id of the document that will be encrypted using
+ :param doc_id: The id of the document that will be encrypted using
this passphrase.
- @type doc_id: str
+ :type doc_id: str
- @return: The passphrase.
- @rtype: str
+ :return: The passphrase.
+ :rtype: str
- @raise NoSymmetricSecret: if no symmetric secret was supplied.
+ :raise NoSymmetricSecret: if no symmetric secret was supplied.
"""
if self.secret is None:
raise NoSymmetricSecret()
@@ -187,13 +187,13 @@ class SoledadCrypto(object):
function. The key used for HMAC is the first MAC_KEY_LENGTH characters
of Soledad's storage secret. The HMAC message is C{doc_id}.
- @param doc_id: The id of the document.
- @type doc_id: str
+ :param doc_id: The id of the document.
+ :type doc_id: str
- @return: The key.
- @rtype: str
+ :return: The key.
+ :rtype: str
- @raise NoSymmetricSecret: if no symmetric secret was supplied.
+ :raise NoSymmetricSecret: if no symmetric secret was supplied.
"""
if self.secret is None:
raise NoSymmetricSecret()
diff --git a/client/src/leap/soledad/client/shared_db.py b/client/src/leap/soledad/client/shared_db.py
index a6ca504d..adcde4e2 100644
--- a/client/src/leap/soledad/client/shared_db.py
+++ b/client/src/leap/soledad/client/shared_db.py
@@ -61,10 +61,10 @@ class SoledadSharedDatabase(http_database.HTTPDatabase, TokenBasedAuth):
"""
Store given credentials so we can sign the request later.
- @param uuid: The user's uuid.
- @type uuid: str
- @param token: The authentication token.
- @type token: str
+ :param uuid: The user's uuid.
+ :type uuid: str
+ :param token: The authentication token.
+ :type token: str
"""
TokenBasedAuth.set_token_credentials(self, uuid, token)
@@ -72,15 +72,15 @@ class SoledadSharedDatabase(http_database.HTTPDatabase, TokenBasedAuth):
"""
Return an authorization header to be included in the HTTP request.
- @param method: The HTTP method.
- @type method: str
- @param url_query: The URL query string.
- @type url_query: str
- @param params: A list with encoded query parameters.
- @type param: list
+ :param method: The HTTP method.
+ :type method: str
+ :param url_query: The URL query string.
+ :type url_query: str
+ :param params: A list with encoded query parameters.
+ :type param: list
- @return: The Authorization header.
- @rtype: list of tuple
+ :return: The Authorization header.
+ :rtype: list of tuple
"""
return TokenBasedAuth._sign_request(self, method, url_query, params)
@@ -95,16 +95,16 @@ class SoledadSharedDatabase(http_database.HTTPDatabase, TokenBasedAuth):
"""
Open a Soledad shared database.
- @param url: URL of the remote database.
- @type url: str
- @param create: Should the database be created if it does not already
+ :param url: URL of the remote database.
+ :type url: str
+ :param create: Should the database be created if it does not already
exist?
- @type create: bool
- @param token: An authentication token for accessing the shared db.
- @type token: str
+ :type create: bool
+ :param token: An authentication token for accessing the shared db.
+ :type token: str
- @return: The shared database in the given url.
- @rtype: SoledadSharedDatabase
+ :return: The shared database in the given url.
+ :rtype: SoledadSharedDatabase
"""
db = SoledadSharedDatabase(url, creds=creds)
db.open(create)
@@ -115,10 +115,10 @@ class SoledadSharedDatabase(http_database.HTTPDatabase, TokenBasedAuth):
"""
Dummy method that prevents from deleting shared database.
- @raise: This will always raise an Unauthorized exception.
+ :raise: This will always raise an Unauthorized exception.
- @param url: The database URL.
- @type url: str
+ :param url: The database URL.
+ :type url: str
"""
raise Unauthorized("Can't delete shared database.")
@@ -126,13 +126,13 @@ class SoledadSharedDatabase(http_database.HTTPDatabase, TokenBasedAuth):
"""
Initialize database with auth token and encryption powers.
- @param url: URL of the remote database.
- @type url: str
- @param document_factory: A factory for U1BD documents.
- @type document_factory: u1db.Document
- @param creds: A tuple containing the authentication method and
+ :param url: URL of the remote database.
+ :type url: str
+ :param document_factory: A factory for U1BD documents.
+ :type document_factory: u1db.Document
+ :param creds: A tuple containing the authentication method and
credentials.
- @type creds: tuple
+ :type creds: tuple
"""
http_database.HTTPDatabase.__init__(self, url, document_factory,
creds)
diff --git a/client/src/leap/soledad/client/sqlcipher.py b/client/src/leap/soledad/client/sqlcipher.py
index c605c28c..3e01a4fb 100644
--- a/client/src/leap/soledad/client/sqlcipher.py
+++ b/client/src/leap/soledad/client/sqlcipher.py
@@ -79,29 +79,29 @@ def open(path, password, create=True, document_factory=None, crypto=None,
Will raise u1db.errors.DatabaseDoesNotExist if create=False and the
database does not already exist.
- @param path: The filesystem path for the database to open.
- @param type: str
- @param create: True/False, should the database be created if it doesn't
+ :param path: The filesystem path for the database to open.
+ :param type: str
+ :param create: True/False, should the database be created if it doesn't
already exist?
- @param type: bool
- @param document_factory: A function that will be called with the same
+ :param type: bool
+ :param document_factory: A function that will be called with the same
parameters as Document.__init__.
- @type document_factory: callable
- @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
+ :type document_factory: callable
+ :param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type crypto: soledad.crypto.SoledadCrypto
- @param raw_key: Whether C{password} is a raw 64-char hex string or a
+ :type crypto: soledad.crypto.SoledadCrypto
+ :param raw_key: Whether C{password} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
- @param cipher: The cipher and mode to use.
- @type cipher: str
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
-
- @return: An instance of Database.
- @rtype SQLCipherDatabase
+ :type raw_key: bool
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
+
+ :return: An instance of Database.
+ :rtype SQLCipherDatabase
"""
return SQLCipherDatabase.open_database(
path, password, create=create, document_factory=document_factory,
@@ -143,25 +143,25 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Create a new sqlcipher file.
- @param sqlcipher_file: The path for the SQLCipher file.
- @type sqlcipher_file: str
- @param password: The password that protects the SQLCipher db.
- @type password: str
- @param document_factory: A function that will be called with the same
+ :param sqlcipher_file: The path for the SQLCipher file.
+ :type sqlcipher_file: str
+ :param password: The password that protects the SQLCipher db.
+ :type password: str
+ :param document_factory: A function that will be called with the same
parameters as Document.__init__.
- @type document_factory: callable
- @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
+ :type document_factory: callable
+ :param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type crypto: soledad.crypto.SoledadCrypto
- @param raw_key: Whether C{password} is a raw 64-char hex string or a
+ :type crypto: soledad.crypto.SoledadCrypto
+ :param raw_key: Whether C{password} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
- @param cipher: The cipher and mode to use.
- @type cipher: str
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
+ :type raw_key: bool
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
"""
# ensure the db is encrypted if the file already exists
if os.path.exists(sqlcipher_file):
@@ -195,28 +195,28 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Open a SQLCipher database.
- @param sqlcipher_file: The path for the SQLCipher file.
- @type sqlcipher_file: str
- @param password: The password that protects the SQLCipher db.
- @type password: str
- @param document_factory: A function that will be called with the same
+ :param sqlcipher_file: The path for the SQLCipher file.
+ :type sqlcipher_file: str
+ :param password: The password that protects the SQLCipher db.
+ :type password: str
+ :param document_factory: A function that will be called with the same
parameters as Document.__init__.
- @type document_factory: callable
- @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
+ :type document_factory: callable
+ :param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type crypto: soledad.crypto.SoledadCrypto
- @param raw_key: Whether C{password} is a raw 64-char hex string or a
+ :type crypto: soledad.crypto.SoledadCrypto
+ :param raw_key: Whether C{password} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
- @param cipher: The cipher and mode to use.
- @type cipher: str
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
+ :type raw_key: bool
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
- @return: The database object.
- @rtype: SQLCipherDatabase
+ :return: The database object.
+ :rtype: SQLCipherDatabase
"""
if not os.path.isfile(sqlcipher_file):
raise u1db_errors.DatabaseDoesNotExist()
@@ -267,33 +267,33 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Open a SQLCipher database.
- @param sqlcipher_file: The path for the SQLCipher file.
- @type sqlcipher_file: str
- @param password: The password that protects the SQLCipher db.
- @type password: str
- @param create: Should the datbase be created if it does not already
+ :param sqlcipher_file: The path for the SQLCipher file.
+ :type sqlcipher_file: str
+ :param password: The password that protects the SQLCipher db.
+ :type password: str
+ :param create: Should the datbase be created if it does not already
exist?
- @type: bool
- @param backend_cls: A class to use as backend.
- @type backend_cls: type
- @param document_factory: A function that will be called with the same
+ :type: bool
+ :param backend_cls: A class to use as backend.
+ :type backend_cls: type
+ :param document_factory: A function that will be called with the same
parameters as Document.__init__.
- @type document_factory: callable
- @param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
+ :type document_factory: callable
+ :param crypto: An instance of SoledadCrypto so we can encrypt/decrypt
document contents when syncing.
- @type crypto: soledad.crypto.SoledadCrypto
- @param raw_key: Whether C{password} is a raw 64-char hex string or a
+ :type crypto: soledad.crypto.SoledadCrypto
+ :param raw_key: Whether C{password} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
- @param cipher: The cipher and mode to use.
- @type cipher: str
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
+ :type raw_key: bool
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
- @return: The database object.
- @rtype: SQLCipherDatabase
+ :return: The database object.
+ :rtype: SQLCipherDatabase
"""
try:
return cls._open_database(
@@ -316,16 +316,16 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Synchronize documents with remote replica exposed at url.
- @param url: The url of the target replica to sync with.
- @type url: str
- @param creds: optional dictionary giving credentials.
+ :param url: The url of the target replica to sync with.
+ :type url: str
+ :param creds: optional dictionary giving credentials.
to authorize the operation with the server.
- @type creds: dict
- @param autocreate: Ask the target to create the db if non-existent.
- @type autocreate: bool
+ :type creds: dict
+ :param autocreate: Ask the target to create the db if non-existent.
+ :type autocreate: bool
- @return: The local generation before the synchronisation was performed.
- @rtype: int
+ :return: The local generation before the synchronisation was performed.
+ :rtype: int
"""
from u1db.sync import Synchronizer
from leap.soledad.client.target import SoledadSyncTarget
@@ -343,8 +343,8 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
method, which is executed when the database schema is created. Here,
we use it to include the "syncable" property for LeapDocuments.
- @param c: The cursor for querying the database.
- @type c: dbapi2.cursor
+ :param c: The cursor for querying the database.
+ :type c: dbapi2.cursor
"""
c.execute(
'ALTER TABLE document '
@@ -354,10 +354,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Update a document and all indexes related to it.
- @param old_doc: The old version of the document.
- @type old_doc: u1db.Document
- @param doc: The new version of the document.
- @type doc: u1db.Document
+ :param old_doc: The old version of the document.
+ :type old_doc: u1db.Document
+ :param doc: The new version of the document.
+ :type doc: u1db.Document
"""
sqlite_backend.SQLitePartialExpandDatabase._put_and_update_indexes(
self, old_doc, doc)
@@ -370,15 +370,15 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
"""
Get just the document content, without fancy handling.
- @param doc_id: The unique document identifier
- @type doc_id: str
- @param include_deleted: If set to True, deleted documents will be
+ :param doc_id: The unique document identifier
+ :type doc_id: str
+ :param include_deleted: If set to True, deleted documents will be
returned with empty content. Otherwise asking for a deleted
document will return None.
- @type include_deleted: bool
+ :type include_deleted: bool
- @return: a Document object.
- @type: u1db.Document
+ :return: a Document object.
+ :type: u1db.Document
"""
doc = sqlite_backend.SQLitePartialExpandDatabase._get_doc(
self, doc_id, check_for_conflicts)
@@ -411,19 +411,19 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
which will attempt to read the first page of the database and will
parse the schema.
- @param sqlcipher_file: The path for the SQLCipher file.
- @type sqlcipher_file: str
- @param key: The key that protects the SQLCipher db.
- @type key: str
- @param raw_key: Whether C{key} is a raw 64-char hex string or a
+ :param sqlcipher_file: The path for the SQLCipher file.
+ :type sqlcipher_file: str
+ :param key: The key that protects the SQLCipher db.
+ :type key: str
+ :param raw_key: Whether C{key} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
- @param cipher: The cipher and mode to use.
- @type cipher: str
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
+ :type raw_key: bool
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
"""
try:
# try to open an encrypted database with the regular u1db
@@ -473,11 +473,11 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
* PRAGMA key should generally be called as the first operation on a
database.
- @param key: The key for use with the database.
- @type key: str
- @param raw_key: Whether C{key} is a raw 64-char hex string or a
+ :param key: The key for use with the database.
+ :type key: str
+ :param raw_key: Whether C{key} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
+ :type raw_key: bool
"""
if raw_key:
cls._pragma_key_raw(db_handle, key)
@@ -495,10 +495,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
if you want to do so you should use a raw key instead and derive the
key using your own KDF.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param passphrase: The passphrase used to derive the encryption key.
- @type passphrase: str
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param passphrase: The passphrase used to derive the encryption key.
+ :type passphrase: str
"""
db_handle.cursor().execute("PRAGMA key = '%s'" % passphrase)
@@ -512,10 +512,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
ensure that the data provided is a 64 character hex string, which will
be converted directly to 32 bytes (256 bits) of key data.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param key: A 64 character hex string.
- @type key: str
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param key: A 64 character hex string.
+ :type key: str
"""
if not all(c in string.hexdigits for c in key):
raise NotAnHexString(key)
@@ -546,10 +546,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
widely available and peer-reviewed OpenSSL libcrypto for all
cryptographic functions.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param cipher: The cipher and mode to use.
- @type cipher: str
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param cipher: The cipher and mode to use.
+ :type cipher: str
"""
db_handle.cursor().execute("PRAGMA cipher = '%s'" % cipher)
@@ -575,10 +575,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
* It is not recommended to reduce the number of iterations if a
passphrase is in use.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param kdf_iter: The number of iterations to use.
- @type kdf_iter: int
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param kdf_iter: The number of iterations to use.
+ :type kdf_iter: int
"""
db_handle.cursor().execute("PRAGMA kdf_iter = '%d'" % kdf_iter)
@@ -608,10 +608,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
* If a non-default value is used PRAGMA cipher_page_size to create a
database, it must also be called every time that database is opened.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param cipher_page_size: The page size.
- @type cipher_page_size: int
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param cipher_page_size: The page size.
+ :type cipher_page_size: int
"""
db_handle.cursor().execute(
"PRAGMA cipher_page_size = '%d'" % cipher_page_size)
@@ -637,13 +637,13 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
code>PRAGMA rekey_kdf_iter. These are deprecated and should not be
used. Instead, use sqlcipher_export().
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param new_key: The new key.
- @type new_key: str
- @param raw_key: Whether C{password} is a raw 64-char hex string or a
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param new_key: The new key.
+ :type new_key: str
+ :param raw_key: Whether C{password} is a raw 64-char hex string or a
passphrase that should be hashed to obtain the encyrption key.
- @type raw_key: bool
+ :type raw_key: bool
"""
if raw_key:
cls._pragma_rekey_raw(db_handle, key)
@@ -659,10 +659,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
PBKDF2 key derivation. The result is used as the encryption key for
the database.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param passphrase: The passphrase used to derive the encryption key.
- @type passphrase: str
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param passphrase: The passphrase used to derive the encryption key.
+ :type passphrase: str
"""
db_handle.cursor().execute("PRAGMA rekey = '%s'" % passphrase)
@@ -676,10 +676,10 @@ class SQLCipherDatabase(sqlite_backend.SQLitePartialExpandDatabase):
ensure that the data provided is a 64 character hex string, which will
be converted directly to 32 bytes (256 bits) of key data.
- @param db_handle: A handle to the SQLCipher database.
- @type db_handle: pysqlcipher.Connection
- @param key: A 64 character hex string.
- @type key: str
+ :param db_handle: A handle to the SQLCipher database.
+ :type db_handle: pysqlcipher.Connection
+ :param key: A 64 character hex string.
+ :type key: str
"""
if not all(c in string.hexdigits for c in key):
raise NotAnHexString(key)
diff --git a/client/src/leap/soledad/client/target.py b/client/src/leap/soledad/client/target.py
index d0bc3706..65639887 100644
--- a/client/src/leap/soledad/client/target.py
+++ b/client/src/leap/soledad/client/target.py
@@ -98,19 +98,19 @@ def mac_doc(crypto, doc_id, doc_rev, ciphertext, mac_method):
* msg: doc_id + doc_rev + ciphertext
* digestmod: sha256
- @param crypto: A SoledadCryto instance used to perform the encryption.
- @type crypto: leap.soledad.crypto.SoledadCrypto
- @param doc_id: The id of the document.
- @type doc_id: str
- @param doc_rev: The revision of the document.
- @type doc_rev: str
- @param ciphertext: The content of the document.
- @type ciphertext: str
- @param mac_method: The MAC method to use.
- @type mac_method: str
-
- @return: The calculated MAC.
- @rtype: str
+ :param crypto: A SoledadCryto instance used to perform the encryption.
+ :type crypto: leap.soledad.crypto.SoledadCrypto
+ :param doc_id: The id of the document.
+ :type doc_id: str
+ :param doc_rev: The revision of the document.
+ :type doc_rev: str
+ :param ciphertext: The content of the document.
+ :type ciphertext: str
+ :param mac_method: The MAC method to use.
+ :type mac_method: str
+
+ :return: The calculated MAC.
+ :rtype: str
"""
if mac_method == MacMethods.HMAC:
return hmac.new(
@@ -137,14 +137,14 @@ def encrypt_doc(crypto, doc):
MAC_METHOD_KEY: 'hmac'
}
- @param crypto: A SoledadCryto instance used to perform the encryption.
- @type crypto: leap.soledad.crypto.SoledadCrypto
- @param doc: The document with contents to be encrypted.
- @type doc: SoledadDocument
+ :param crypto: A SoledadCryto instance used to perform the encryption.
+ :type crypto: leap.soledad.crypto.SoledadCrypto
+ :param doc: The document with contents to be encrypted.
+ :type doc: SoledadDocument
- @return: The JSON serialization of the dict representing the encrypted
+ :return: The JSON serialization of the dict representing the encrypted
content.
- @rtype: str
+ :rtype: str
"""
soledad_assert(doc.is_tombstone() is False)
# encrypt content using AES-256 CTR mode
@@ -191,13 +191,13 @@ def decrypt_doc(crypto, doc):
EncryptionSchemes.SYMKEY and C{enc_method} is
EncryptionMethods.AES_256_CTR.
- @param crypto: A SoledadCryto instance to perform the encryption.
- @type crypto: leap.soledad.crypto.SoledadCrypto
- @param doc: The document to be decrypted.
- @type doc: SoledadDocument
+ :param crypto: A SoledadCryto instance to perform the encryption.
+ :type crypto: leap.soledad.crypto.SoledadCrypto
+ :param doc: The document to be decrypted.
+ :type doc: SoledadDocument
- @return: The JSON serialization of the decrypted content.
- @rtype: str
+ :return: The JSON serialization of the decrypted content.
+ :rtype: str
"""
soledad_assert(doc.is_tombstone() is False)
soledad_assert(ENC_JSON_KEY in doc.content)
@@ -258,10 +258,10 @@ class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
"""
Store given credentials so we can sign the request later.
- @param uuid: The user's uuid.
- @type uuid: str
- @param token: The authentication token.
- @type token: str
+ :param uuid: The user's uuid.
+ :type uuid: str
+ :param token: The authentication token.
+ :type token: str
"""
TokenBasedAuth.set_token_credentials(self, uuid, token)
@@ -269,15 +269,15 @@ class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
"""
Return an authorization header to be included in the HTTP request.
- @param method: The HTTP method.
- @type method: str
- @param url_query: The URL query string.
- @type url_query: str
- @param params: A list with encoded query parameters.
- @type param: list
+ :param method: The HTTP method.
+ :type method: str
+ :param url_query: The URL query string.
+ :type url_query: str
+ :param params: A list with encoded query parameters.
+ :type param: list
- @return: The Authorization header.
- @rtype: list of tuple
+ :return: The Authorization header.
+ :rtype: list of tuple
"""
return TokenBasedAuth._sign_request(self, method, url_query, params)
@@ -293,14 +293,14 @@ class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
"""
Initialize the SoledadSyncTarget.
- @param url: The url of the target replica to sync with.
- @type url: str
- @param creds: optional dictionary giving credentials.
+ :param url: The url of the target replica to sync with.
+ :type url: str
+ :param creds: optional dictionary giving credentials.
to authorize the operation with the server.
- @type creds: dict
- @param soledad: An instance of Soledad so we can encrypt/decrypt
+ :type creds: dict
+ :param soledad: An instance of Soledad so we can encrypt/decrypt
document contents when syncing.
- @type soledad: soledad.Soledad
+ :type soledad: soledad.Soledad
"""
HTTPSyncTarget.__init__(self, url, creds)
self._crypto = crypto
@@ -314,19 +314,19 @@ class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
EncryptionSchemes.SYMKEY, then this method will decrypt it with
Soledad's symmetric key.
- @param data: The body of the HTTP response.
- @type data: str
- @param return_doc_cb: A callback to insert docs from target.
- @type return_doc_cb: function
- @param ensure_callback: A callback to ensure we have the correct
+ :param data: The body of the HTTP response.
+ :type data: str
+ :param return_doc_cb: A callback to insert docs from target.
+ :type return_doc_cb: function
+ :param ensure_callback: A callback to ensure we have the correct
target_replica_uid, if it was just created.
- @type ensure_callback: function
+ :type ensure_callback: function
- @raise BrokenSyncStream: If C{data} is malformed.
+ :raise BrokenSyncStream: If C{data} is malformed.
- @return: A dictionary representing the first line of the response got
+ :return: A dictionary representing the first line of the response got
from remote replica.
- @rtype: list of str
+ :rtype: list of str
"""
parts = data.splitlines() # one at a time
if not parts or parts[0] != '[':
@@ -381,25 +381,25 @@ class SoledadSyncTarget(HTTPSyncTarget, TokenBasedAuth):
This does the same as the parent's method but encrypts content before
syncing.
- @param docs_by_generations: A list of (doc_id, generation, trans_id)
+ :param docs_by_generations: A list of (doc_id, generation, trans_id)
of local documents that were changed since the last local
generation the remote replica knows about.
- @type docs_by_generations: list of tuples
- @param source_replica_uid: The uid of the source replica.
- @type source_replica_uid: str
- @param last_known_generation: Target's last known generation.
- @type last_known_generation: int
- @param last_known_trans_id: Target's last known transaction id.
- @type last_known_trans_id: str
- @param return_doc_cb: A callback for inserting received documents from
+ :type docs_by_generations: list of tuples
+ :param source_replica_uid: The uid of the source replica.
+ :type source_replica_uid: str
+ :param last_known_generation: Target's last known generation.
+ :type last_known_generation: int
+ :param last_known_trans_id: Target's last known transaction id.
+ :type last_known_trans_id: str
+ :param return_doc_cb: A callback for inserting received documents from
target.
- @type return_doc_cb: function
- @param ensure_callback: A callback that ensures we know the target
+ :type return_doc_cb: function
+ :param ensure_callback: A callback that ensures we know the target
replica uid if the target replica was just created.
- @type ensure_callback: function
+ :type ensure_callback: function
- @return: The new generation and transaction id of the target replica.
- @rtype: tuple
+ :return: The new generation and transaction id of the target replica.
+ :rtype: tuple
"""
self._ensure_connection()
if self._trace_hook: # for tests