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 _get_sync(self, view, shareId, peerId, name, op): try: view.refresh(None, None, False) if shareId is not None: share = view[shareId] peerId = share.conduit.peerId toRepoId = share.repoId collection = share.contents name = collection.displayName uuid = collection.itsUUID version = share.localVersion else: collection, name, uuid = self.findCollection(view, name, None) toRepoId = None version = 0 replyTo = view[self.client.account].imap.replyToAddress.emailAddress share = self.findShare(view, collection, toRepoId, peerId) changes = self.computeChanges(view, version, collection, share) if op == 'sync' and not changes: share.localVersion = view.itsVersion + 1 view.commit() return None message = MIMEMultipart() message['From'] = replyTo message['Reply-To'] = replyTo message['To'] = peerId message['Subject'] = 'Chandler sent "%s" collection' %(name) message['X-chandler'] = 'p2p' textPart = MIMEBase('text', 'plain') textPart.set_payload('Chandler sent "%s"' %(name)) message.attach(textPart) attachment = MIMEBase('application', 'octet-stream') builder = TreeBuilder() dom = ElementTreeDOM() data = dom.openElement(builder, 'data') keys = set() for key, (_changes, status) in changes.iteritems(): if key not in keys: attrs = { 'uuid': key.str64() } if status & CItem.DELETED: attrs['status'] = 'deleted' item = dom.openElement(data, 'item', **attrs) else: 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: item = dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(builder, 'data') out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') data = compress(out.getvalue()) out.close() message['X-chandler-p2p-name'] = name message['X-chandler-p2p-from'] = self._repoId.str64() if toRepoId is not None: message['X-chandler-p2p-to'] = toRepoId.str64() message['X-chandler-p2p-item'] = "%s-%d" %(uuid.str64(), view.itsVersion) message['X-chandler-p2p-op'] = 'sync' attachment.set_payload(data) encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', name=name) message.attach(attachment) except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return message
def _get_sync(self, view, shareId, peerId, name, op): try: view.refresh(None, None, False) if shareId is not None: share = view[shareId] peerId = share.conduit.peerId toRepoId = share.repoId collection = share.contents name = collection.displayName uuid = collection.itsUUID version = share.localVersion else: collection, name, uuid = self.findCollection(view, name, None) toRepoId = None version = 0 replyTo = view[ self.client.account].imap.replyToAddress.emailAddress share = self.findShare(view, collection, toRepoId, peerId) changes = self.computeChanges(view, version, collection, share) if op == 'sync' and not changes: share.localVersion = view.itsVersion + 1 view.commit() return None message = MIMEMultipart() message['From'] = replyTo message['Reply-To'] = replyTo message['To'] = peerId message['Subject'] = 'Chandler sent "%s" collection' % (name) message['X-chandler'] = 'p2p' textPart = MIMEBase('text', 'plain') textPart.set_payload('Chandler sent "%s"' % (name)) message.attach(textPart) attachment = MIMEBase('application', 'octet-stream') builder = TreeBuilder() dom = ElementTreeDOM() data = dom.openElement(builder, 'data') keys = set() for key, (_changes, status) in changes.iteritems(): if key not in keys: attrs = {'uuid': key.str64()} if status & CItem.DELETED: attrs['status'] = 'deleted' item = dom.openElement(data, 'item', **attrs) else: 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: item = dom.openElement(data, 'item', uuid=key.str64(), status='member') dom.closeElement(data, 'item') dom.closeElement(builder, 'data') out = StringIO() ElementTree(builder.close()).write(out, 'utf-8') data = compress(out.getvalue()) out.close() message['X-chandler-p2p-name'] = name message['X-chandler-p2p-from'] = self._repoId.str64() if toRepoId is not None: message['X-chandler-p2p-to'] = toRepoId.str64() message['X-chandler-p2p-item'] = "%s-%d" % (uuid.str64(), view.itsVersion) message['X-chandler-p2p-op'] = 'sync' attachment.set_payload(data) encode_base64(attachment) attachment.add_header('Content-Disposition', 'attachment', name=name) message.attach(attachment) except: view.cancel() raise share.localVersion = view.itsVersion + 1 share.established = True share.ackPending = True view.commit() return message