def _result_sync(self, view, iq, sync, args): try: view.refresh(None, None, False) if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId: raise RepositoryMismatchError, args['toRepoId'] repoId = UUID(args['fromRepoId']) uuid = UUID(args['uuid']) version = int(args['version']) collection = view.find(uuid) if collection is None: collection = pim.SmartCollection(itsView=view, _uuid=uuid, displayName=args['name']) schema.ns("osaf.app", view).sidebarCollection.add(collection) # for now, grant READ to everyone acl = ACL() acl.append( ACE(schema.ns('p2p', view).all.itsUUID, Permissions.READ)) collection.setACL(acl, 'p2p') isNew = True else: isNew = False share = self.findShare(view, collection, repoId, iq['from']) format = share.format if isNew: share.localVersion = view.itsVersion + 1 else: changes = self.computeChanges(view, share.localVersion, collection, share) if not changes: share.localVersion = view.itsVersion + 1 if sync.attributes.get('compressed') == 'true': dom = formats.ElementTreeDOM() input = StringIO(decompress(b64decode(sync.children[0]))) data = ElementTree(file=input).getroot() input.close() else: dom = DomishDOM() data = sync.firstChildElement() share.remoteVersion = version view.deferDelete() for itemElement in dom.iterElements(data): attributes = dom.getAttributes(itemElement) status = attributes.get('status') if status == 'deleted': item = view.findUUID(attributes['uuid']) if item is not None: item.delete() else: child = dom.getFirstChildElement(itemElement) if child is not None: item = format.importProcess(dom, child) else: item = view.findUUID(attributes['uuid']) if status == 'member': collection.inclusions.add(item) # Kludge until masterEvents filter patch on bug 6970 is checked in for item in collection.inclusions: if pim.has_stamp(item, pim.EventStamp): event = pim.EventStamp(item) if event.rruleset is not None: event.getMaster().getFirstOccurrence() except: view.cancel() raise share.established = True view.commit() self.client.output("'%s' synchronized" % (collection.displayName)) to = iq['from'] iq = client.IQ(self.client.xmlstream, 'result') iq.addElement(('jabber:x:chandler', 'query')) receipt = iq.query.addElement('receipt') receipt['fromRepoId'] = self._repoId.str64() receipt['toRepoId'] = repoId.str64() receipt['uuid'] = collection.itsUUID.str64() receipt['version'] = str(share.localVersion) reactor.callFromThread(iq.send, to)
def _get_sync(self, view, iq, args): try: if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId: raise RepositoryMismatchError, args['toRepoId'] view.refresh(None, None, False) repoId = UUID(args['fromRepoId']) name = args['name'] version = int(args.get('version', '0')) uuid = args.get('uuid') if uuid is not None: uuid = UUID(uuid) collection, name, uuid = self.findCollection(view, name, uuid) share = self.findShare(view, collection, repoId, iq['from']) iq = client.IQ(self.client.xmlstream, "result") query = iq.addElement(("jabber:x:chandler", "query")) sync = query.addElement('sync') sync['name'] = name changes = self.computeChanges(view, version, collection, share) keys = set() compressed = len(changes) > 16 if compressed: builder = TreeBuilder() dom = formats.ElementTreeDOM() data = dom.openElement(builder, 'data') else: dom = DomishDOM() data = dom.openElement(sync, 'data') for key, (_changes, status) in changes.iteritems(): if key not in keys: if status & CItem.DELETED: dom.openElement(data, 'item', uuid=key.str64(), status='deleted') else: attrs = {'uuid': key.str64()} if key in collection: attrs['status'] = 'member' item = dom.openElement(data, 'item', **attrs) share.format.exportProcess(dom, key, item, changes, keys) dom.closeElement(data, 'item') elif key in collection: dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(data, 'data') sync['fromRepoId'] = self._repoId.str64() sync['toRepoId'] = repoId.str64() sync['version'] = str(view.itsVersion) sync['uuid'] = collection.itsUUID.str64() if compressed: sync['compressed'] = 'true' out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') sync.children.append(b64encode(compress(out.getvalue()))) out.close() except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return iq
def _result_sync(self, view, uid, message, fromAddress): try: view.refresh(None, None, False) repoId = UUID(message['X-chandler-p2p-from']) uuid, version = message['X-chandler-p2p-item'].split('-') uuid = UUID(uuid) version = int(version) name = message['X-chandler-p2p-name'] self.client.output("processing '%s'" %(name)) collection = view.find(uuid) if collection is None: collection = pim.SmartCollection(itsView=view, _uuid=uuid, displayName=name) schema.ns("osaf.app", view).sidebarCollection.add(collection) # for now, grant READ to everyone acl = ACL() acl.append(ACE(schema.ns('p2p', view).all.itsUUID, Permissions.READ)) collection.setACL(acl, 'p2p') isNew = True else: isNew = False share = self.findShare(view, collection, repoId, fromAddress) format = share.format if isNew: share.localVersion = view.itsVersion + 1 else: changes = self.computeChanges(view, share.localVersion, collection, share) if not changes: share.localVersion = view.itsVersion + 1 payload = message.get_payload(1).get_payload() dom = ElementTreeDOM() input = StringIO(decompress(b64decode(payload))) data = ElementTree(file=input).getroot() input.close() share.remoteVersion = version view.deferDelete() for itemElement in dom.iterElements(data): attributes = dom.getAttributes(itemElement) status = attributes.get('status') if status == 'deleted': item = view.findUUID(attributes['uuid']) if item is not None: item.delete() else: child = dom.getFirstChildElement(itemElement) if child is not None: item = format.importProcess(dom, child) else: item = view.findUUID(attributes['uuid']) if status == 'member': collection.inclusions.add(item) # Kludge until masterEvents filter patch on bug 6970 is checked in for item in collection.inclusions: if pim.has_stamp(item, pim.EventStamp): event = pim.EventStamp(item) if event.rruleset is not None: event.getMaster().getFirstOccurrence() except: view.cancel() raise share.established = True view.commit() self.client.output("'%s' synchronized" %(collection.displayName)) replyTo = view[self.client.account].imap.replyToAddress.emailAddress receipt = MIMEText('Chandler sent a receipt for "%s"' %(name)) receipt['From'] = replyTo receipt['Reply-To'] = replyTo receipt['To'] = message.get('replyTo') or fromAddress receipt['Subject'] = "Chandler sent a receipt" receipt['X-chandler'] = 'p2p' receipt['X-chandler-p2p-name'] = name receipt['X-chandler-p2p-from'] = self._repoId.str64() receipt['X-chandler-p2p-to'] = repoId.str64() receipt['X-chandler-p2p-item'] = "%s-%d" %(uuid.str64(), share.localVersion) receipt['X-chandler-p2p-op'] = 'receipt' return receipt
def _result_sync(self, view, uid, message, fromAddress): try: view.refresh(None, None, False) repoId = UUID(message['X-chandler-p2p-from']) uuid, version = message['X-chandler-p2p-item'].split('-') uuid = UUID(uuid) version = int(version) name = message['X-chandler-p2p-name'] self.client.output("processing '%s'" % (name)) collection = view.find(uuid) if collection is None: collection = pim.SmartCollection(itsView=view, _uuid=uuid, displayName=name) schema.ns("osaf.app", view).sidebarCollection.add(collection) # for now, grant READ to everyone acl = ACL() acl.append( ACE(schema.ns('p2p', view).all.itsUUID, Permissions.READ)) collection.setACL(acl, 'p2p') isNew = True else: isNew = False share = self.findShare(view, collection, repoId, fromAddress) format = share.format if isNew: share.localVersion = view.itsVersion + 1 else: changes = self.computeChanges(view, share.localVersion, collection, share) if not changes: share.localVersion = view.itsVersion + 1 payload = message.get_payload(1).get_payload() dom = ElementTreeDOM() input = StringIO(decompress(b64decode(payload))) data = ElementTree(file=input).getroot() input.close() share.remoteVersion = version view.deferDelete() for itemElement in dom.iterElements(data): attributes = dom.getAttributes(itemElement) status = attributes.get('status') if status == 'deleted': item = view.findUUID(attributes['uuid']) if item is not None: item.delete() else: child = dom.getFirstChildElement(itemElement) if child is not None: item = format.importProcess(dom, child) else: item = view.findUUID(attributes['uuid']) if status == 'member': collection.inclusions.add(item) # Kludge until masterEvents filter patch on bug 6970 is checked in for item in collection.inclusions: if pim.has_stamp(item, pim.EventStamp): event = pim.EventStamp(item) if event.rruleset is not None: event.getMaster().getFirstOccurrence() except: view.cancel() raise share.established = True view.commit() self.client.output("'%s' synchronized" % (collection.displayName)) replyTo = view[self.client.account].imap.replyToAddress.emailAddress receipt = MIMEText('Chandler sent a receipt for "%s"' % (name)) receipt['From'] = replyTo receipt['Reply-To'] = replyTo receipt['To'] = message.get('replyTo') or fromAddress receipt['Subject'] = "Chandler sent a receipt" receipt['X-chandler'] = 'p2p' receipt['X-chandler-p2p-name'] = name receipt['X-chandler-p2p-from'] = self._repoId.str64() receipt['X-chandler-p2p-to'] = repoId.str64() receipt['X-chandler-p2p-item'] = "%s-%d" % (uuid.str64(), share.localVersion) receipt['X-chandler-p2p-op'] = 'receipt' return receipt
def _result_sync(self, view, iq, sync, args): try: view.refresh(None, None, False) if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId: raise RepositoryMismatchError, args['toRepoId'] repoId = UUID(args['fromRepoId']) uuid = UUID(args['uuid']) version = int(args['version']) collection = view.find(uuid) if collection is None: collection = pim.SmartCollection(itsView=view, _uuid=uuid, displayName=args['name']) schema.ns("osaf.app", view).sidebarCollection.add(collection) # for now, grant READ to everyone acl = ACL() acl.append(ACE(schema.ns('p2p', view).all.itsUUID, Permissions.READ)) collection.setACL(acl, 'p2p') isNew = True else: isNew = False share = self.findShare(view, collection, repoId, iq['from']) format = share.format if isNew: share.localVersion = view.itsVersion + 1 else: changes = self.computeChanges(view, share.localVersion, collection, share) if not changes: share.localVersion = view.itsVersion + 1 if sync.attributes.get('compressed') == 'true': dom = formats.ElementTreeDOM() input = StringIO(decompress(b64decode(sync.children[0]))) data = ElementTree(file=input).getroot() input.close() else: dom = DomishDOM() data = sync.firstChildElement() share.remoteVersion = version view.deferDelete() for itemElement in dom.iterElements(data): attributes = dom.getAttributes(itemElement) status = attributes.get('status') if status == 'deleted': item = view.findUUID(attributes['uuid']) if item is not None: item.delete() else: child = dom.getFirstChildElement(itemElement) if child is not None: item = format.importProcess(dom, child) else: item = view.findUUID(attributes['uuid']) if status == 'member': collection.inclusions.add(item) # Kludge until masterEvents filter patch on bug 6970 is checked in for item in collection.inclusions: if pim.has_stamp(item, pim.EventStamp): event = pim.EventStamp(item) if event.rruleset is not None: event.getMaster().getFirstOccurrence() except: view.cancel() raise share.established = True view.commit() self.client.output("'%s' synchronized" %(collection.displayName)) to = iq['from'] iq = client.IQ(self.client.xmlstream, 'result') iq.addElement(('jabber:x:chandler', 'query')) receipt = iq.query.addElement('receipt') receipt['fromRepoId'] = self._repoId.str64() receipt['toRepoId'] = repoId.str64() receipt['uuid'] = collection.itsUUID.str64() receipt['version'] = str(share.localVersion) reactor.callFromThread(iq.send, to)
def _get_sync(self, view, iq, args): try: if 'toRepoId' in args and UUID(args['toRepoId']) != self._repoId: raise RepositoryMismatchError, args['toRepoId'] view.refresh(None, None, False) repoId = UUID(args['fromRepoId']) name = args['name'] version = int(args.get('version', '0')) uuid = args.get('uuid') if uuid is not None: uuid = UUID(uuid) collection, name, uuid = self.findCollection(view, name, uuid) share = self.findShare(view, collection, repoId, iq['from']) iq = client.IQ(self.client.xmlstream, "result") query = iq.addElement(("jabber:x:chandler", "query")) sync = query.addElement('sync') sync['name'] = name changes = self.computeChanges(view, version, collection, share) keys = set() compressed = len(changes) > 16 if compressed: builder = TreeBuilder() dom = formats.ElementTreeDOM() data = dom.openElement(builder, 'data') else: dom = DomishDOM() data = dom.openElement(sync, 'data') for key, (_changes, status) in changes.iteritems(): if key not in keys: if status & CItem.DELETED: dom.openElement(data, 'item', uuid=key.str64(), status='deleted') else: attrs = { 'uuid': key.str64() } if key in collection: attrs['status'] = 'member' item = dom.openElement(data, 'item', **attrs) share.format.exportProcess(dom, key, item, changes, keys) dom.closeElement(data, 'item') elif key in collection: dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(data, 'data') sync['fromRepoId'] = self._repoId.str64() sync['toRepoId'] = repoId.str64() sync['version'] = str(view.itsVersion) sync['uuid'] = collection.itsUUID.str64() if compressed: sync['compressed'] = 'true' out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') sync.children.append(b64encode(compress(out.getvalue()))) out.close() except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return iq