def testDefaultRepository(self):
     """Get the default repository by calling the repo's service URL"""
     cmisClient = CmisClient(self.url,
                             self.user,
                             self.pwd,
                             binding=self.binding,
                             **self.ext_args)
     repo = cmisClient.getDefaultRepository()
     assert repo is not None
     assert repo.getRepositoryId() is not None
Example #2
0
def cmis_connect(url, username = '', password = ''):
    print
    print "** Connecting to %s" % url
    print "Environment variables: CMIS_URL, CMIS_USERNAME, CMIS_PASSWORD"

    client = CmisClient(url, username, password)

    print '** Connected to repository %s' % (client.getDefaultRepository().getRepositoryName())
    print
    return client
 def testTypeDefinition(self):
     """Get the cmis:document type and test a few props of the type."""
     cmisClient = CmisClient(self.url,
                             self.user,
                             self.pwd,
                             binding=self.binding,
                             **self.ext_args)
     repo = cmisClient.getDefaultRepository()
     docTypeDef = repo.getTypeDefinition('cmis:document')
     assert 'cmis:document' == docTypeDef.getTypeId()
     assert docTypeDef.baseId
    def cmis_connect(self, cr, uid):
        """Connect to the CMIS Server and returns the document repository"""
        user = self.pool.get('res.users').browse(cr, uid, uid)
        server_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'document_cmis.server_url')

        if not server_url:
            raise osv.except_osv(_('Error!'),_("Cannot connect to the CMIS Server: No CMIS Server URL system property found"))

        client = CmisClient(server_url, user.login, user.password)
        repo = client.getDefaultRepository()

        return repo
 def testGetRepository(self):
     """Get a repository by repository ID"""
     cmisClient = CmisClient(self.url,
                             self.user,
                             self.pwd,
                             binding=self.binding,
                             **self.ext_args)
     repo = cmisClient.getDefaultRepository()
     defaultRepoId = repo.getRepositoryId()
     defaultRepoName = repo.getRepositoryName()
     repo = cmisClient.getRepository(defaultRepoId)
     assert defaultRepoId == repo.getRepositoryId()
     assert defaultRepoName == repo.getRepositoryName()
 def testTypeProperties(self):
     """Get the properties for a type."""
     cmisClient = CmisClient(self.url,
                             self.user,
                             self.pwd,
                             binding=self.binding,
                             **self.ext_args)
     repo = cmisClient.getDefaultRepository()
     docTypeDef = repo.getTypeDefinition('cmis:document')
     assert 'cmis:document' == docTypeDef.getTypeId()
     props = docTypeDef.getProperties().values()
     assert len(props) > 0
     for prop in props:
         if prop.queryable:
             assert prop.queryName
         assert prop.propertyType
    def testTypeDescendants(self):
        """Get the descendant types of the repository."""

        cmisClient = CmisClient(self.url,
                                self.user,
                                self.pwd,
                                binding=self.binding,
                                **self.ext_args)
        repo = cmisClient.getDefaultRepository()
        typeDefs = repo.getTypeDescendants()
        folderDef = None
        for typeDef in typeDefs:
            if typeDef.getTypeId() == 'cmis:folder':
                folderDef = typeDef
                break
        assert folderDef
        assert folderDef.baseId
    def testTypeChildren(self):
        """Get the child types for this repository and make sure cmis:folder
        is in the list."""

        # This test would be more interesting if there was a standard way to
        # deploy a custom model. Then we could look for custom types.

        cmisClient = CmisClient(self.url,
                                self.user,
                                self.pwd,
                                binding=self.binding,
                                **self.ext_args)
        repo = cmisClient.getDefaultRepository()
        typeDefs = repo.getTypeChildren()
        folderDef = None
        for typeDef in typeDefs:
            if typeDef.getTypeId() == 'cmis:folder':
                folderDef = typeDef
                break
        assert folderDef
        assert folderDef.baseId
Example #9
0
class RemoteClient(Client):
    """CMIS Client"""

    def __init__(self, repository_url, username, password, base_folder):
        self.repository_url = repository_url
        self.username = username
        self.password = password
        self.base_folder = base_folder

        self.client = CmisClient(repository_url, username, password)
        self.repo = self.client.getDefaultRepository()

    def get_descendants(self, path=""):
        result = []

        remote_path = self.get_remote_path(path)
        object = self.repo.getObjectByPath(remote_path)

        children = object.getChildren()
        for child in children:
            properties = child.properties
            # Hack around some Nuxeo quirks
            child_name = properties['cmis:name']
            if properties.has_key('cmis:path'):
                child_name = properties['cmis:path'].split('/')[-1]
            if child_name.startswith('.'):
                continue
            if path == "":
                child_path = child_name
            else:
                child_path = path + "/" + child_name

            state = self.make_state(child_path, properties)
            if state.type == 'folder':
                result += [state] + self.get_descendants(child_path)
            else:
                result += [state]

        return result

    def get_state(self, path):
        remote_path = self.get_remote_path(path)
        try:
            object = self.repo.getObjectByPath(remote_path)
            properties = object.properties
            return self.make_state(path, properties)
        except ObjectNotFoundException:
            return None

    def get_content(self, path):
        remote_path = self.get_remote_path(path)
        object = self.repo.getObjectByPath(remote_path)
        try:
            return object.getContentStream().read()
        except AssertionError:
            # No attached stream: bug in Nuxeo?
            return ""

    # Modifiers
    def mkdir(self, path):
        remote_path = self.get_remote_path(path)
        parent_path, name = os.path.split(remote_path)
        parent_folder = self.repo.getObjectByPath(parent_path)
        parent_folder.createFolder(name)

    def mkfile(self, path, content=None):
        remote_path = self.get_remote_path(path)
        parent_path, name = os.path.split(remote_path)
        parent_folder = self.repo.getObjectByPath(parent_path)
        content_file = StringIO(content)
        content_file.name = path.rsplit('/', 1)[-1]
        parent_folder.createDocument(name, contentFile=content_file)

    def update(self, path, content):
        remote_path = self.get_remote_path(path)
        object = self.repo.getObjectByPath(remote_path)
        content_file = StringIO(content)
        content_file.name = path.rsplit('/', 1)[-1]
        return object.setContentStream(content_file)
        # TODO: manage also mime type

    def delete(self, path):
        remote_path = self.get_remote_path(path)
        try:
            object = self.repo.getObjectByPath(remote_path)
            # XXX: hack, fix later
            try:
                object.delete()
            except:
                object.deleteTree()
        except ObjectNotFoundException:
            # nothing to delete
            pass

    #
    # Utilities
    #
    def get_remote_path(self, path):
        if path != "":
            return self.base_folder + "/" + path
        else:
            return self.base_folder

    def make_state(self, path, properties):
        if properties['cmis:baseTypeId'] == 'cmis:folder':
            type = 'folder'
        else:
            type = 'file'
        uid = properties['cmis:objectId']
        mtime = properties['cmis:lastModificationDate']
        return Info(path, uid, type, mtime)
Example #10
0
class CMISStorage(Storage):
    """
    Storage engine to upload and fetch files from a CMIS-enabled content management system, like Alfresco
    """

    def __init__(self, base_folder=None):
        self.options = settings.CMIS_STORAGE_OPTIONS

        if 'baseFolder' not in self.options:
            self.options['baseFolder'] = '/'

        if base_folder:
            self.options['baseFolder'] = base_folder

        self.client = CmisClient(**self.options)
        self.repo = self.client.getDefaultRepository()

    def _open(self, name, mode='rb'):
        return File(self.open_stream(name), name=name)

    def open_stream(self, name):

        # Build the full path of the file
        full_path = os.path.join(self.options['baseFolder'], name.strip('./'))

        # Get the object from the CMS
        obj = self.repo.getObjectByPath(full_path)  # type: cmislib.model.Document

        # Return the stream
        return obj.getContentStream()

    def _save(self, name, content):
        logger.debug("Saving file {}".format(name))

        # Build the full path of the file
        full_path = os.path.join(self.options['baseFolder'], name.strip('.'))

        logger.debug("Full path at {}".format(full_path))

        # Split the path
        dirname, filename = os.path.split(full_path)

        # Get the folder
        folder = self.repo.getObjectByPath(dirname)

        # Create the document
        newfile = folder.createDocument(filename, contentFile=content)

        # Get the new path for the file
        newfile_path = newfile.getPaths()[0]

        logger.debug("New path: {}".format(newfile_path))

        return newfile_path

    def delete(self, name):
        logger.debug("Deleting file '{}'".format(name))

        # Build the full path of the file
        full_path = os.path.join(self.options['baseFolder'], name.strip('./'))

        try:
            obj = self.repo.getObjectByPath(full_path)
            obj.delete()
        except cmislib.exceptions.ObjectNotFoundException:
            pass

    def exists(self, name):
        logger.debug("Checking if file exists '{}'".format(name))

        # Build the full path of the file
        full_path = os.path.join(self.options['baseFolder'], name.strip('./'))

        try:
            self.repo.getObjectByPath(full_path)
        except cmislib.exceptions.ObjectNotFoundException:
            return False

        return True

    def path(self, name):
        return name

    def _props(self, name):
        # Build the full path of the file
        full_path = os.path.join(self.options['baseFolder'], name.strip('./'))

        # Get the object from the CMS
        obj = self.repo.getObjectByPath(full_path)  # type: cmislib.model.Document

        return obj.getProperties()

    def modified_time(self, name):
        """
        Returns the last modification date for the specified file
        """
        return self._props(name).get('cmis:lastModificationDate', None)

    def accessed_time(self, name):
        return None

    def created_time(self, name):
        return self._props(name).get('cmis:creationDate', None)

    def size(self, name):
        return self._props(name).get('cmis:contentStreamLength', 0)

    def listdir(self, path):
        try:
            folder = self.repo.getObjectByPath(path)

            if not isinstance(folder, cmislib.models.Folder):
                return []

            return [x.getName() for x in folder.getChildren()]

        except ObjectNotFoundException as e:
            return []

    def url(self, name):
        return reverse('cmis_storage_get_file', kwargs={'path': name})
Example #11
0
class CmisTracPlugin(Component):
    implements(INavigationContributor, IRequestHandler, ITemplateProvider, IPermissionRequestor)

    def __init__(self):
        Component.__init__(self)
        self.url_api = None
        self.user = None
        self.password = None
        self.base_path = None
        self.max_size = None
        self.cmis_client = None
        self.repository = None
        self.root_cmis_object = None

    # INavigationContributor methods

    def get_active_navigation_item(self, req):
        return 'documents'

    def get_navigation_items(self, req):
        if req.perm.has_permission('REPOSITORY_BROWSER'):
            yield ('mainnav', 'documents', tag.a('Documents', href=req.href.documents()))

    # IRequestHandler methods

    def match_request(self, req):
        '''Check if applicable to this plugin'''
        match = re.match('^(/documents)(/)?(workspace://SpacesStore/)?([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})?(/)?(newfolder|removefolder|renamefolder|upload|download|removedocument)?$', req.path_info)
        self._print("cmistracplugin: Check req.path_info: [" + req.path_info + "] match: [" + ("true" if match else "false") + "]")
        if match:
            if match.group(4) != None:
                req.args['objectId'] = match.group(4)
            if match.group(6) != None:
                req.args['op'] = match.group(6)
            return True
        else:
            return False

    def process_request(self, req):
        '''Processes the request. Input validation and call the corresponding method'''
        req.perm.assert_permission('REPOSITORY_BROWSER')
        self.load_config()
        xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest'
        add_script(req, 'common/js/expand_dir.js')
        add_stylesheet(req, 'common/css/browser.css')
        add_stylesheet(req, 'hw/cmistracplugin.css')

        if xhr:
            return 'folder-entries.html', self._render_cmis_object(req, xhr), None

        elif 'op' in req.args and req.args['op'] == 'newfolder':
            if 'objectId' in req.args:
                return 'new-folder.html', self._prepare_newfolder_form(req), None
            else:
                self._process_newfolder_form(req)
                req.redirect(req.href.documents(req.args['objectId']))

        elif 'op' in req.args and req.args['op'] == 'removefolder':
            if 'objectId' in req.args:
                self._process_removefolder(req)
                req.redirect(req.href.documents(req.args['objectId']))

        elif 'op' in req.args and req.args['op'] == 'renamefolder':
            if 'objectId' in req.args:
                if req.method == 'GET':
                    return 'rename-folder.html', self._prepare_renamefolder_form(req), None
                else:
                    self._process_renamefolder_form(req)
                    if req.args['parentId']:
                        req.redirect(req.href.documents(req.args['parentId']))
                    else:
                        req.redirect(req.href.documents(req.args['objectId']))

        elif 'op' in req.args and req.args['op'] == 'upload':
            if 'objectId' in req.args:
                return 'upload-document.html', self._prepare_upload_form(req), None
            elif 'cancel' in req.args:
                req.redirect(req.href.documents(req.args['parentId']))
            else:
                self._process_upload_form(req)
                req.redirect(req.href.documents(req.args['objectId']))

        elif 'op' in req.args and req.args['op'] == 'download':
            if 'objectId' in req.args:
                self._process_download(req)

        elif 'op' in req.args and req.args['op'] == 'removedocument':
            if 'objectId' in req.args:
                self._process_removedocument(req)
                if req.session['lastCmisFolderIdVisited']:
                    req.redirect(req.href.documents(req.session['lastCmisFolderIdVisited']))
                else:
                    req.redirect(req.href.documents())
        else:
            self._print("cmistracplugin: go to 'repository-browser.html'")
            return 'repository-browser.html', self._render_cmis_object(req), None

    # ITemplateProvider methods

    def get_templates_dirs(self):
        return [pkg_resources.resource_filename(__name__, 'templates')]

    def get_htdocs_dirs(self):
        return [('hw', pkg_resources.resource_filename(__name__, 'htdocs'))]

    # IPermissionRequestor methods

    def get_permission_actions(self):
        return ['REPOSITORY_BROWSER', 'REPOSITORY_UPLOAD', 'REPOSITORY_DOWNLOAD', 'REPOSITORY_CREATE_FOLDER', 'REPOSITORY_REMOVE_FOLDER', 'REPOSITORY_RENAME_FOLDER', 'REPOSITORY_REMOVE_DOCUMENT']

    def load_config(self):
        '''Read available configurations options from trac.ini'''

        self.url_api = self.env.config.get('cmis', 'url_api')
        self.user = self.env.config.get('cmis', 'user')
        self.password = self.env.config.get('cmis', 'password')
        self.base_path = self.env.config.get('cmis', 'base_path')
        self.max_size = self.env.config.getint('cmis', 'max_size')
        self.log.info('Plugin Configuration loaded')
        try:
            self.cmis_client = CmisClient(self.url_api, self.user, self.password)
            self.repository = self.cmis_client.getDefaultRepository()
            self.root_cmis_object = self.repository.getObjectByPath(self.base_path)
        except:
            raise TracError('Unable to connect to the repository. Check the configuration')

    def _render_cmis_object(self, req, xhr = None):
        if 'objectId' in req.args:
            selt._print("cmis: get object: [" + str(req.args['objectId']) + "]")
            cmis_object = self.repository.getObject(req.args['objectId'])
        else:
            cmis_object = self.root_cmis_object

        data = {}
        data['rootFolder'] = self.root_cmis_object

        self._print("p1: cmistracplugin: cmis:objectTypeId: " + cmis_object.getProperties()['cmis:objectTypeId'])

        if cmis_object.getProperties()['cmis:objectTypeId'] in ['cmis:folder', 'Folder', 'Section', 'Workspace']:
        #if cmis_object.getProperties()['cmis:objectTypeId'] == 'cmis:folder' || cmis_object.getProperties()['cmis:objectTypeId'] == 'cmis:Section':
            cmis_objects = cmis_object.getChildren().getResults()
            data['breadcrumb'] = render_breadcrumb(self.cmis_client, self.repository, self.root_cmis_object, cmis_object)
            if cmis_object.getObjectId() != self.root_cmis_object.getObjectId():
                data['parentId'] = cmis_object.getProperties()['cmis:parentId']
            data['cmis_objectTypeId'] = 'cmis:folder'

            self._print("cmistracplugin: len(cmis_object.getChildren().getResults()): " + str(len(cmis_objects)))
            for idx in range(len(cmis_objects)):
                self._printCmisObjetc(cmis_objects[idx])

            data['cmis_objects'] = cmis_objects
            add_ctxtnav(req, tag.a('New folder', href=req.href.documents(cmis_object.getProperties()['cmis:objectId'], 'newfolder')))
            add_ctxtnav(req, tag.a('Remove folder', href=req.href.documents(cmis_object.getProperties()['cmis:objectId'], 'removefolder')))
            add_ctxtnav(req, tag.a('Rename folder', href=req.href.documents(cmis_object.getProperties()['cmis:objectId'], 'renamefolder')))
            add_ctxtnav(req, tag.a('Upload document', href=req.href.documents(cmis_object.getProperties()['cmis:objectId'], 'upload')))
        elif cmis_object.getProperties()['cmis:objectTypeId'] == 'cmis:document':
            data['breadcrumb'] = render_breadcrumb(self.cmis_client, self.repository, self.root_cmis_object, cmis_object)
            data['cmis_objectTypeId'] = 'cmis:document'
            data['cmis_object'] = cmis_object
        else:
            self._print("cmistracplugin: Unknow cmis:objectTypeId: " + cmis_object.getProperties()['cmis:objectTypeId'])
            self._printCmisObjetc(cmis_object)

        if cmis_object.getProperties()['cmis:objectTypeId'] == 'cmis:folder' and xhr == None:
            req.session['lastCmisFolderIdVisited'] = cmis_object.getObjectId()
        return data

    def _prepare_newfolder_form(self, req):
        req.perm.require('REPOSITORY_CREATE_FOLDER')
        data = {
            'parentId': req.args['objectId']
        }
        return data

    def _process_newfolder_form(self, req):
        '''Processes the request to create a new directory'''
        req.perm.require('REPOSITORY_CREATE_FOLDER')
        if req.method == 'POST' and 'name' in req.args and 'parentId' in req.args:
            if 'name' in req.args and req.args['name'] != '':
                parent_folder = self.repository.getObject(req.args['parentId'])
                parent_folder.createFolder(req.args['name'].encode('utf-8'))
                req.args['objectId'] = req.args['parentId']
                del req.args['parentId']
            else:
                raise TracError('The folder name can not be empty')
        self.log.info('A new folder has been created')

    def _process_removefolder(self, req):
        '''Processes the request to remove a folder'''
        req.perm.require('REPOSITORY_REMOVE_FOLDER')
        if 'objectId' in req.args:
            cmis_object = self.repository.getObject(req.args['objectId'])
            if cmis_object.getObjectId() == self.root_cmis_object.getObjectId():
                raise TracError('Can\'t remove root folder')
            parent_folder = self.repository.getObject(cmis_object.getProperties()['cmis:parentId'])
            cmis_object.deleteTree()
            req.args['objectId'] = parent_folder.getObjectId()
        self.log.info('A folder has been removed')

    def _prepare_upload_form(self, req):
        req.perm.require('REPOSITORY_UPLOAD')
        data = {
            'parentId': req.args['objectId'],
            'max_size': self.max_size
        }
        return data

    def _process_upload_form(self, req):
        req.perm.require('REPOSITORY_UPLOAD')
        upload = req.args['document']

        if not hasattr(upload, 'filename') or not upload.filename:
            raise TracError('No file uploaded')

        if hasattr(upload.file, 'fileno'):
            size = os.fstat(upload.file.fileno())[6]
        else:
            upload.file.seek(0, 2) # seek to end of file
            size = upload.file.tell()
            upload.file.seek(0)

        if size == 0:
            raise TracError('Can\'t upload empty document')

        if size > self.max_size:
            raise TracError('Maximum document size: %s KB' % self.max_size)

        # We try to normalize the filename to unicode NFC if we can.
        # Files uploaded from OS X might be in NFD.
        filename = unicodedata.normalize('NFC', unicode(upload.filename, 'utf-8'))
        filename = filename.replace('\\', '/').replace(':', '/')
        filename = os.path.basename(filename)
        if not filename:
            raise TracError('No file uploaded')

        if 'parentId' in req.args:
            cmis_object = self.repository.getObject(req.args['parentId'])
            if cmis_object.getProperties()['cmis:objectTypeId'] == 'cmis:folder':
                cmis_object.createDocument(filename.encode('utf-8'), contentFile = upload.file, contentType = upload.type)

        req.args['objectId'] = req.args['parentId']
        del req.args['parentId']
        self.log.info('A document has been saved')

    def _process_download(self, req):
        req.perm.require('REPOSITORY_DOWNLOAD')
        cmis_object = self.repository.getObject(req.args['objectId'])
        # Validar que es un objecto de tipo documento
        content = cmis_object.getContentStream()
        req.send_response(200)
        req.send_header('Content-Type', cmis_object.getProperties()['cmis:contentStreamMimeType'])
        req.send_header('Content-Length', cmis_object.getProperties()['cmis:contentStreamLength'])
        req.send_header('Last-Modified', cmis_object.getProperties()['cmis:lastModificationDate'])
        req.send_header('Content-Disposition', 'attachment; filename="%s"' % cmis_object.getName())
        req.end_headers()
        chunk = content.read(CHUNK_SIZE)
        while 1:
            if not chunk:
                raise RequestDone
            req.write(chunk)
            chunk = content.read(CHUNK_SIZE)
        self.log.info('A document has been downloaded')

    def _prepare_renamefolder_form(self, req):
        req.perm.require('REPOSITORY_RENAME_FOLDER')
        cmis_object = self.repository.getObject(req.args['objectId'])
        data = {
            'cmis_object': cmis_object
        }
        return data

    def _process_renamefolder_form(self, req):
        req.perm.require('REPOSITORY_RENAME_FOLDER')
        folder = self.repository.getObject(req.args['objectId'])
        parent_folder = folder.getParent()
        props = {
            'cmis:name': req.args['name'].encode('utf-8')
        }
        folder.updateProperties(props)
        if parent_folder:
            req.args['parentId'] = parent_folder.getObjectId()
        self.log.info('A folder has been renamed')

    def _process_removedocument(self, req):
        req.perm.require('REPOSITORY_REMOVE_DOCUMENT')
        if 'objectId' in req.args:
            cmis_object = self.repository.getObject(req.args['objectId'])
            cmis_object.delete()
        self.log.info('A document has been removed')

    def _printCmisObjetc(self, cmis_object):
        self._print("-- cmis:objectTypeId :: [" + cmis_object.getProperties()['cmis:objectTypeId'] + "] -- cmis:objectId :: [" + cmis_object.getProperties()['cmis:objectId'] + "]")
        _props = cmis_object.getProperties()
        for _key in _props:
            self._print("---  cmis_object.getProperties()['" + _key + "'] :: " + str(_props[_key]))

    def _print(self, _str):
        print _str
        self.log.debug(_str)
import time
import base64
import xmlrpclib
from cmislib.model import CmisClient, Repository

server = "localhost"
dbname = "natuurpunt"
uid = 1
pwd = "n2aevl8w"

# replace localhost wity the address of the server
sock = xmlrpclib.ServerProxy("http://%s:8069/xmlrpc/object" % (server))

"""Connect to the CMIS Server and returns the document repository"""
client = CmisClient("http://192.168.1.225:8080/alfresco/s/cmis", "admin", "a2aevl8w")
repo = client.getDefaultRepository()


def process(cmis_naam, cmis_object_id):
    print "***** Start processing {} *****".format(cmis_naam)
    process_cmis_dir(repo.getObject(cmis_object_id))
    print "***** End processing {} *****".format(cmis_naam)


def process_cmis_dir(cmisDir):
    query = (
        """ 
            select cmis:objectId, cmis:name
            from cmis:folder
            where in_folder('%s')
            order by cmis:lastModificationDate desc
Example #13
0
def main():
    """Main method (split it if you want cleaner code.

    Creates a folder called "TEST", then stuffs if with the content of the local
    folder specified in config.py.
    """

    client = CmisClient(REPOSITORY_URL, USERNAME, PASSWORD)
    repo = client.getDefaultRepository()
    root_folder = repo.getObjectByPath(REMOTE_PATH)

    # Removes the TEST folder if it already exists
    try:
        object = repo.getObjectByPath(REMOTE_PATH + "/TEST")
        object.deleteTree()
    except:
        pass

    root_folder.createFolder("TEST")

    start_time = time.time()

    for root, dirs, files in os.walk(LOCAL_PATH):
        root_rel = root[len(LOCAL_PATH) :]
        remote_parent = repo.getObjectByPath(REMOTE_PATH + "/TEST" + root_rel)
        for dir in dirs:
            # FIXME later: skip non-ascii file names
            if dir.encode("ascii", errors="replace") != dir:
                continue

            print "----"
            print ("creating dir: %s" % dir).encode("ascii", errors="replace")
            remote_parent.createFolder(dir)

        for file in files:
            # FIXME later: skip non-ascii file names
            if file.encode("ascii", errors="replace") != file:
                continue

            print "----"
            if os.stat(os.path.join(root, file)).st_size > 1e6:
                print ("File %s too big, skipping" % file).encode("ascii", errors="replace")
                continue

            print ("Creating file: %s" % file).encode("ascii", errors="replace"),
            try:
                local_fd = open(os.path.join(root, file))
                created = remote_parent.createDocument(file, contentFile=local_fd)
                local_fd.close()
                print "OK"
            except AssertionError, e:
                print "KO: exception raised"
                print e
            except CmisException, e:
                print "KO: exception raised"
                print e
            print "nNote: remote name is:", created.properties["cmis:name"].encode("ascii", errors="replace")

            print ("Verifying file: %s" % file).encode("ascii", errors="replace"),
            try:
                path = REMOTE_PATH + "/TEST" + root_rel + "/" + file
                object = repo.getObjectByPath(path)
                remote_fd = object.getContentStream()
                local_fd = open(os.path.join(root, file))
                if compare(local_fd, remote_fd):
                    print "OK"
                else:
                    print "KO: Content differs"
            except AssertionError, e:
                print "KO: exception raised"
                print e