diff --git a/product/ERP5SyncML/Conduit/ERP5Conduit.py b/product/ERP5SyncML/Conduit/ERP5Conduit.py index def4c0e6f069477259ab7d8b885c56c38ea6186e..922b85ded5fbf64c3c0cc1f0e8cde1f05c6088b4 100644 --- a/product/ERP5SyncML/Conduit/ERP5Conduit.py +++ b/product/ERP5SyncML/Conduit/ERP5Conduit.py @@ -48,7 +48,7 @@ from xml.sax.saxutils import escape, unescape import re, copy import cStringIO -from zLOG import LOG +from zLOG import LOG, INFO, DEBUG try: from Ft.Xml.Domlette import Print, PrettyPrint except ImportError: @@ -180,10 +180,9 @@ class ERP5Conduit(XMLSyncUtilsMixin): and self.getSubObjectDepth(xml)>=1: sub_object_id = self.getSubObjectId(xml) if previous_xml is not None and sub_object_id is not None: - #LOG('addNode',0,'previous xml is not none and also sub_object_id') # Find the previous xml corresponding to this subobject - sub_previous_xml = self.getSubObjectXml(sub_object_id,previous_xml) - #LOG('addNode',0,'isSubObjectModification sub_p_xml: %s' % str(sub_previous_xml)) + sub_previous_xml = self.getSubObjectXml(sub_object_id, previous_xml) + LOG('addNode', DEBUG,'isSubObjectModification sub_previous_xml: %s' % str(sub_previous_xml)) if sub_previous_xml is not None: sub_object = None try: @@ -191,11 +190,11 @@ class ERP5Conduit(XMLSyncUtilsMixin): except (AttributeError, KeyError, TypeError): pass if sub_object is not None: - #LOG('addNode',0,'subobject.id: %s' % sub_object.id) + LOG('addNode', DEBUG, 'subobject.id: %s' % sub_object.id) # Change the xml in order to directly apply # modifications to the subobject sub_xml = self.getSubObjectXupdate(xml) - #LOG('addNode',0,'sub_xml: %s' % str(sub_xml)) + LOG('addNode', DEBUG, 'sub_xml: %s' % str(sub_xml)) # Then do the udpate conflict_list += self.addNode(xml=sub_xml,object=sub_object, previous_xml=sub_previous_xml, force=force, @@ -220,14 +219,12 @@ class ERP5Conduit(XMLSyncUtilsMixin): A node is deleted """ # In the case where we have to delete an object - #LOG('ERP5Conduit',0,'deleteNode') - #LOG('ERP5Conduit',0,'deleteNode, object.id: %s' % object.getId()) - #LOG('ERP5Conduit',0,'deleteNode, object path: %s' % repr(object.getPhysicalPath())) + LOG('ERP5Conduit.deleteNode', DEBUG, 'deleteNode, object path: %s' % repr(object.getPhysicalPath())) conflict_list = [] if xml is not None: xml = self.convertToXml(xml) if object_id is None: - #LOG('ERP5Conduit',0,'deleteNode, SubObjectDepth: %i' % self.getSubObjectDepth(xml)) + LOG('ERP5Conduit.deleteNode', DEBUG, 'deleteNode, SubObjectDepth: %i' % self.getSubObjectDepth(xml)) if xml.nodeName == self.xml_object_tag: object_id = self.getAttribute(xml,'id') elif self.getSubObjectDepth(xml)==1: @@ -241,7 +238,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): conflict_list += self.deleteNode(xml=sub_xml,object=sub_object, force=force, simulate=simulate, **kw) except (KeyError, AttributeError, TypeError): - #LOG('ERP5Conduit',0,'deleteNode, Unable to delete SubObject: %s' % str(sub_object_id)) + LOG('ERP5Conduit.deleteNode', DEBUG, 'deleteNode, Unable to delete SubObject: %s' % str(sub_object_id)) pass if object_id is not None: # We do have an object_id self.deleteObject(object, object_id) @@ -252,7 +249,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): if xml.nodeName in self.local_role_list and not simulate: # We want to del a local role user = self.getAttribute(xml,'id') - #LOG('local_role: ',0,'user: %s' % repr(user)) + LOG('ERP5Conduit.deleteNode local_role: ', DEBUG, 'user: %s' % repr(user)) if xml.nodeName.find(self.local_role_tag)>=0: object.manage_delLocalRoles([user]) elif xml.nodeName.find(self.local_group_tag)>=0: @@ -267,7 +264,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): try: object._delObject(object_id) except (AttributeError, KeyError): - #LOG('ERP5Conduit',0,'deleteObject, Unable to delete: %s' % str(object_id)) + LOG('ERP5Conduit.deleteObject', DEBUG, 'Unable to delete: %s' % str(object_id)) pass security.declareProtected(Permissions.ModifyPortalContent, 'updateNode') @@ -282,8 +279,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ conflict_list = [] xml = self.convertToXml(xml) - #LOG('updateNode',0,'xml.nodeName: %s' % xml.nodeName) - #LOG('updateNode, force: ',0,force) + LOG('ERP5Conduit.updateNode', DEBUG, 'xml.nodeName: %s' % xml.nodeName) + LOG('ERP5Conduit.updateNode, force: ', DEBUG, force) # we have an xupdate xml if xml.nodeName == 'xupdate:modifications': conflict_list += self.applyXupdate(object=object, xupdate=xml, @@ -292,12 +289,10 @@ class ERP5Conduit(XMLSyncUtilsMixin): # we may have only the part of an xupdate else: args = {} - #LOG('isSubObjectModification',0,'result: %s' % str(self.isSubObjectModification(xml))) if self.isProperty(xml) and not(self.isSubObjectModification(xml)): keyword = None for subnode in self.getAttributeNodeList(xml): if subnode.nodeName=='select': - #LOG('updateNode',0,'selection: %s' % str(subnode.nodeValue)) select_list = subnode.nodeValue.split('/') # Something like: #('','object[1]','sid[1]') new_select_list = () @@ -309,7 +304,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): keyword = select_list[len(select_list)-1] # this will be 'sid' data_xml = xml data = None - #LOG('updateNode',0,'keyword: %s' % str(keyword)) if xml.nodeName not in self.XUPDATE_INSERT_OR_ADD: for subnode in self.getElementNodeList(xml): if subnode.nodeName=='xupdate:element': @@ -343,7 +337,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): if not (keyword in self.NOT_EDITABLE_PROPERTY): # We will look for the data to enter data_type = object.getPropertyType(keyword) - #LOG('updateNode',0,'data_type: %s' % str(data_type)) + LOG('ERP5Conduit.updateNode', DEBUG, 'data_type: %s for keyword: %s' % (str(data_type), keyword)) data = self.convertXmlValue(data,data_type=data_type) args[keyword] = data args = self.getFormatedArgs(args=args) @@ -358,12 +352,12 @@ class ERP5Conduit(XMLSyncUtilsMixin): data_type=data_type) #current_data = object.getProperty(keyword) current_data = self.getProperty(object, keyword) - #LOG('updateNode',0,'Conflict data: %s' % str(data)) - #LOG('updateNode',0,'Conflict old_data: %s' % str(old_data)) - #LOG('updateNode',0,'Conflict current_data: %s' % str(current_data)) + LOG('ERP5Conduit.updateNode', DEBUG, 'Conflict data: %s' % str(data)) + LOG('ERP5Conduit.updateNode', DEBUG, 'Conflict old_data: %s' % str(old_data)) + LOG('ERP5Conduit.updateNode', DEBUG, 'Conflict current_data: %s' % str(current_data)) if (old_data != current_data) and (data != current_data) \ and keyword not in self.force_conflict_list: - #LOG('updateNode',0,'Conflict on : %s' % keyword) + LOG('ERP5Conduit.updateNode', DEBUG, 'Conflict on : %s' % keyword) # Hack in order to get the synchronization working for demo # XXX this have to be removed after #if not (data_type in self.binary_type_list): @@ -379,11 +373,6 @@ class ERP5Conduit(XMLSyncUtilsMixin): conflict.setLocalValue(current_data) conflict.setRemoteValue(data) conflict_list += [conflict] - #conflict_list += [Conflict(object_path=object.getPhysicalPath(), - # keyword=keyword, - # xupdate=string_io)] - #publisher_value=current_data, # not needed any more - #subscriber_value=data)] # not needed any more # We will now apply the argument with the method edit if args != {} and (isConflict==0 or force) and (not simulate): self.editDocument(object=object,**args) @@ -399,9 +388,9 @@ class ERP5Conduit(XMLSyncUtilsMixin): # This is the case where we have to call addNode conflict_list += self.addNode(xml=subnode,object=object,force=force, simulate=simulate,**kw)['conflict_list'] - elif keyword in (self.local_role_tag,self.local_permission_tag) and not simulate: + elif keyword in (self.local_role_tag, self.local_permission_tag) and not simulate: # This is the case where we have to update Roles or update permission - #LOG('updateNode',0,'we will add a local role') + #LOG('ERP5Conduit.updateNode', DEBUG, 'we will add a local role') #user = self.getSubObjectId(xml) #roles = self.convertXmlValue(data,data_type='tokens') #object.manage_setLocalRoles(user,roles) @@ -412,11 +401,10 @@ class ERP5Conduit(XMLSyncUtilsMixin): # We should find the object corresponding to # this update, so we have to look in the previous_xml sub_object_id = self.getSubObjectId(xml) - #LOG('updateNode',0,'isSubObjectModification sub_object_id: %s' % sub_object_id) + LOG('ERP5Conduit.updateNode', DEBUG,'isSubObjectModification sub_object_id: %s' % sub_object_id) if previous_xml is not None and sub_object_id is not None: - #LOG('updateNode',0,'previous xml is not none and also sub_object_id') sub_previous_xml = self.getSubObjectXml(sub_object_id,previous_xml) - #LOG('updateNode',0,'isSubObjectModification sub_p_xml: %s' % str(sub_previous_xml)) + LOG('ERP5Conduit.updateNode', DEBUG, 'isSubObjectModification sub_previous_xml: %s' % str(sub_previous_xml)) if sub_previous_xml is not None: sub_object = None try: @@ -424,11 +412,11 @@ class ERP5Conduit(XMLSyncUtilsMixin): except KeyError: pass if sub_object is not None: - #LOG('updateNode',0,'subobject.id: %s' % sub_object.id) + LOG('ERP5Conduit.updateNode', DEBUG, 'subobject.id: %s' % sub_object.id) # Change the xml in order to directly apply # modifications to the subobject sub_xml = self.getSubObjectXupdate(xml) - #LOG('updateNode',0,'sub_xml: %s' % str(sub_xml)) + LOG('ERP5Conduit.updateNode', DEBUG, 'sub_xml: %s' % str(sub_xml)) # Then do the udpate conflict_list += self.updateNode(xml=sub_xml, object=sub_object, force=force, previous_xml=sub_previous_xml, @@ -485,7 +473,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): data = data.encode(self.getEncoding()) data = data.replace('@@@','\n') if keyword == 'binary_data': - #LOG('ERP5Conduit.getFormatedArgs',0,'binary_data keyword: %s' % str(keyword)) + LOG('ERP5Conduit.getFormatedArgs', DEBUG, 'binary_data keyword: %s' % str(keyword)) msg = MIMEBase('application','octet-stream') Encoders.encode_base64(msg) msg.set_payload(data) diff --git a/product/ERP5SyncML/Publication.py b/product/ERP5SyncML/Publication.py index c46d8023db7a74926ab2ca1f02b0711c6dc85dfd..3f034f875341d06f56d1731f0dc8a2aff0155808 100644 --- a/product/ERP5SyncML/Publication.py +++ b/product/ERP5SyncML/Publication.py @@ -95,7 +95,7 @@ def addPublication( self, id, title='', REQUEST=None ): Add a new Category and generate UID by calling the ZSQLCatalog """ - o = Publication( id ,'','','','','') + o = Publication( id, '', '', '', '', '') self._setObject( id, o ) if REQUEST is not None: return self.manage_main(self, REQUEST, update_menu=1) @@ -143,9 +143,9 @@ class Publication(Subscription): # Constructor def __init__(self, id, title, publication_url, destination_path, - source_uri, query, xml_mapping, conduit, gpg_key, id_generator, - gid_generator, media_type, auth_required, authentication_format, - authentication_type, activity_enabled, synchronize_with_erp5_sites, + source_uri, query, xml_mapping, conduit, gpg_key, id_generator, + gid_generator, media_type, auth_required, authentication_format, + authentication_type, activity_enabled, synchronize_with_erp5_sites, sync_content_type): """ constructor @@ -157,7 +157,6 @@ class Publication(Subscription): self.setSourceURI(source_uri) self.setQuery(query) self.xml_mapping = xml_mapping - #self.list_subscribers = PersistentMapping() self.domain_type = self.PUB self.gpg_key = gpg_key self.setGidGenerator(gid_generator) @@ -231,26 +230,24 @@ class Publication(Subscription): """ Add a new subscriber to the publication """ - LOG('addSubscriber starting ...',0,'') # We have to remove the subscriber if it already exist (there were probably a reset on the client) self.delSubscriber(subscriber.getSubscriptionUrl()) new_id = subscriber.getId() if new_id is None: new_id = str(self.generateNewId()) subscriber.id = new_id - #if len(self.list_subscribers) == 0: - # self.list_subscribers = [] - #self.list_subscribers = self.list_subscribers + [subscriber] - self._setObject(new_id,subscriber) + self._setObject(new_id, subscriber) def getSubscriber(self, subscription_url): """ return the subscriber corresponding the to subscription_url """ - for o in self.objectValues(): - if o.getSubscriptionUrl() == subscription_url: - return o - return None + o = None + for sub in self.getSubscriberList(): + if sub.getSubscriptionUrl() == subscription_url: + o = sub + break + return o def getSubscriberList(self): """ @@ -263,16 +260,16 @@ class Publication(Subscription): """ Delete a subscriber for this publication """ - for o in self.objectValues(): + for o in self.getSubscriberList(): if o.getSubscriptionUrl() == subscription_url: - self._delObject(o.id) + self.activate().manage_delObjects(o.id) def resetAllSubscribers(self): """ Reset all subscribers """ - for o in self.objectValues(): - self._delObject(o.id) + for o in self.getSubscriberList(): + self.activate().manage_delObjects(o.id) def getConflictList(self): """ @@ -280,6 +277,6 @@ class Publication(Subscription): """ conflict_list = [] for subscriber in self.getSubscriberList(): - conflict_list += subscriber.getConflictList() + conflict_list.extend(subscriber.getConflictList()) return conflict_list diff --git a/product/ERP5SyncML/PublicationSynchronization.py b/product/ERP5SyncML/PublicationSynchronization.py index b0d9046c250167e3d3c21ebc259432d2634271fb..2d68b352c65cd246ef7704b3f20f7b1cf66e229b 100644 --- a/product/ERP5SyncML/PublicationSynchronization.py +++ b/product/ERP5SyncML/PublicationSynchronization.py @@ -39,11 +39,11 @@ from Products.PluggableAuthService.interfaces.plugins import\ from AccessControl.SecurityManagement import newSecurityManager import commands from DateTime import DateTime -from zLOG import LOG +from zLOG import LOG, DEBUG, INFO, WARNING class PublicationSynchronization(XMLSyncUtils): """ - + Receive the first XML message from the client """ def PubSyncInit(self, publication=None, xml_client=None, subscriber=None, @@ -52,8 +52,7 @@ class PublicationSynchronization(XMLSyncUtils): Read the client xml message Send the first XML message from the server """ - LOG('PubSyncInit',0,'Starting... publication: %s' % str(publication)) - + LOG('PubSyncInit', DEBUG, 'Starting... publication: %s' % (publication.getPath())) #the session id is set at the same value of those of the client subscriber.setSessionId(self.getSessionId(xml_client)) #same for the message id @@ -80,8 +79,8 @@ class PublicationSynchronization(XMLSyncUtils): # If slow sync, then resend everything if alert_code == self.SLOW_SYNC: - LOG('Warning !!!, reseting client synchronization for subscriber:',0, - subscriber) + LOG('Warning !!!, reseting client synchronization for subscriber:', WARNING, + subscriber.getPath()) subscriber.resetAllSignatures() # Check if the last time synchronization is the same as the client one @@ -89,16 +88,12 @@ class PublicationSynchronization(XMLSyncUtils): \nlast_anchor:\t\t\t%s\nnext_anchor:\t\t\t%s' % \ (subscriber.getNextAnchor(), subscriber.getLastAnchor(), last_anchor, \ next_anchor) - #LOG('PubSyncInit',0,mess) - if subscriber.getNextAnchor() != last_anchor: if last_anchor in (None, ''): - LOG('PubSyncInit',0,'anchor null') - #raise ValueError, "Sorry, the anchor was null" + LOG('PubSyncInit', DEBUG, 'anchor null') else: message = "bad anchors in PubSyncInit! " + \ subscriber.getNextAnchor() + " and " + last_anchor - LOG('PubSyncInit',0,message) else: subscriber.setNextAnchor(next_anchor) @@ -118,14 +113,14 @@ class PublicationSynchronization(XMLSyncUtils): if publication.isAuthenticationRequired(): #at the begining, the code is initialised at UNAUTHORIZED auth_code=self.UNAUTHORIZED - LOG('PubSyncInit',0,'authentication required') + LOG('PubSyncInit', INFO, 'authentication required') if not cred: auth_code=self.AUTH_REQUIRED - LOG("there's no credential !!!",0,'') + LOG("PubSyncInit there's no credential !!!", INFO,'') # Prepare the xml message for the Sync initialization package - xml(self.SyncMLChal(cmd_id, "SyncHdr", - publication.getPublicationUrl(), subscriber.getSubscriptionUrl(), - publication.getAuthenticationFormat(), + xml(self.SyncMLChal(cmd_id, "SyncHdr", + publication.getPublicationUrl(), subscriber.getSubscriptionUrl(), + publication.getAuthenticationFormat(), publication.getAuthenticationType(), auth_code)) cmd_id += 1 # chal message @@ -154,8 +149,7 @@ class PublicationSynchronization(XMLSyncUtils): break else: auth_code=self.UNAUTHORIZED - #in all others cases, the auth_code is set to UNAUTHORIZED - + #in all others cases, the auth_code is set to UNAUTHORIZED # Prepare the xml message for the Sync initialization package if auth_code == self.AUTH_ACCEPTED: @@ -163,25 +157,25 @@ class PublicationSynchronization(XMLSyncUtils): cmd_id, next_anchor, subscription=subscriber).values() xml(xml_status) # alert message - xml(self.SyncMLAlert(cmd_id, sync_type, subscriber.getTargetURI(), - subscriber.getSourceURI(), subscriber.getLastAnchor(), + xml(self.SyncMLAlert(cmd_id, sync_type, subscriber.getTargetURI(), + subscriber.getSourceURI(), subscriber.getLastAnchor(), next_anchor)) cmd_id += 1 else: # chal message - xml(self.SyncMLChal(cmd_id, "SyncHdr", - publication.getPublicationUrl(), subscriber.getSubscriptionUrl(), - publication.getAuthenticationFormat(), + xml(self.SyncMLChal(cmd_id, "SyncHdr", + publication.getPublicationUrl(), subscriber.getSubscriptionUrl(), + publication.getAuthenticationFormat(), publication.getAuthenticationType(), auth_code)) cmd_id += 1 - xml_status, cmd_id = self.SyncMLStatus(xml_client, - self.AUTH_REQUIRED, cmd_id, next_anchor, + xml_status, cmd_id = self.SyncMLStatus(xml_client, + self.AUTH_REQUIRED, cmd_id, next_anchor, subscription=subscriber).values() xml(xml_status) elif alert is not None: #if no identification is required : # syncml header - xml_status, cmd_id = self.SyncMLStatus(xml_client, self.AUTH_ACCEPTED, + xml_status, cmd_id = self.SyncMLStatus(xml_client, self.AUTH_ACCEPTED, cmd_id, next_anchor, subscription=subscriber).values() xml(xml_status) # alert message @@ -203,28 +197,27 @@ class PublicationSynchronization(XMLSyncUtils): xml(' </SyncBody>\n') xml('</SyncML>\n') xml_a = ''.join(xml_list) - if publication.getSyncContentType() == self.CONTENT_TYPE['SYNCML_WBXML']: xml_a = self.xml2wbxml(xml_a) self.sendResponse(from_url=publication.getPublicationUrl(), - to_url=subscriber.getSubscriptionUrl(), sync_id=publication.getTitle(), - xml=xml_a, domain=publication, + to_url=subscriber.getSubscriptionUrl(), sync_id=publication.getTitle(), + xml=xml_a, domain=publication, content_type=publication.getSyncContentType()) - return {'has_response':1,'xml':xml_a} + return {'has_response':1, 'xml':xml_a} def PubSync(self, publication_path, msg=None, RESPONSE=None, subscriber=None): """ This is the synchronization method for the server """ - LOG('PubSync',0,'Starting... publication: %s' % str(publication_path)) + LOG('PubSync', DEBUG, 'Starting... publication: %s' % (publication_path)) # Read the request from the client publication = self.unrestrictedTraverse(publication_path) xml_client = msg if xml_client is None: xml_client = self.readResponse(from_url=publication.getPublicationUrl()) - #LOG('PubSync',0,'Starting... msg: %s' % str(xml_client)) + LOG('PubSync', DEBUG, 'Starting... msg: %s' % str(xml_client)) result = None if xml_client is not None: @@ -233,14 +226,13 @@ class PublicationSynchronization(XMLSyncUtils): first_node = xml_client.childNodes[0] if first_node.nodeName != "SyncML": - #LOG('PubSync',0,'This is not a SyncML Message') + LOG('PubSync', INFO, 'This is not a SyncML Message') raise ValueError, "Sorry, This is not a SyncML Message" alert_code = self.getAlertCode(xml_client) - # Get informations from the header client_header = first_node.childNodes[1] if client_header.nodeName != "SyncHdr": - #LOG('PubSync',0,'This is not a SyncML Header') + LOG('PubSync', INFO, 'This is not a SyncML Header') raise ValueError, "Sorry, This is not a SyncML Header" subscription_url = self.getSubscriptionUrl(client_header) # Get the subscriber or create it if not already in the list @@ -272,8 +264,8 @@ class PublicationSynchronization(XMLSyncUtils): elif subscriber is not None: # This looks like we are starting a synchronization after # a conflict resolution by the user - result = self.PubSyncInit(publication=publication, xml_client=None, - subscriber=subscriber,sync_type=self.TWO_WAY) + result = self.PubSyncInit(publication=publication, xml_client=None, + subscriber=subscriber, sync_type=self.TWO_WAY) if RESPONSE is not None: RESPONSE.redirect('managePublications') @@ -284,4 +276,4 @@ class PublicationSynchronization(XMLSyncUtils): """ The modidification message for the publication """ - return self.SyncModif(publication,xml_client) + return self.SyncModif(publication, xml_client) diff --git a/product/ERP5SyncML/Subscription.py b/product/ERP5SyncML/Subscription.py index 7b2cf64147f2503921779257d45b3cc2f1a31851..20615f721b5575c2a0b0ba4be703b404a73d27a1 100644 --- a/product/ERP5SyncML/Subscription.py +++ b/product/ERP5SyncML/Subscription.py @@ -37,7 +37,7 @@ from Products.ERP5Type.Base import Base from Products.ERP5Type import Permissions from Products.ERP5Type import PropertySheet from DateTime import DateTime -from zLOG import LOG +from zLOG import LOG, DEBUG, INFO import md5 @@ -141,7 +141,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') p_sync.applyPublisherValue(self) def applyPublisherDocument(self): @@ -149,7 +149,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') p_sync.applyPublisherDocument(self) def getPublisherDocument(self): @@ -157,7 +157,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') return p_sync.getPublisherDocument(self) def getPublisherDocumentPath(self): @@ -165,7 +165,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') return p_sync.getPublisherDocumentPath(self) def getSubscriberDocument(self): @@ -173,7 +173,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') return p_sync.getSubscriberDocument(self) def getSubscriberDocumentPath(self): @@ -181,7 +181,7 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') return p_sync.getSubscriberDocumentPath(self) def applySubscriberDocument(self): @@ -189,14 +189,14 @@ class Conflict(SyncCode, Base): after a conflict resolution, we have decided to keep the local version of this object """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') p_sync.applySubscriberDocument(self) def applySubscriberValue(self,object=None): """ get the domain """ - p_sync = getToolByName(self,'portal_synchronizations') + p_sync = getToolByName(self, 'portal_synchronizations') p_sync.applySubscriberValue(self,object=object) def setSubscriber(self, subscriber): @@ -229,12 +229,11 @@ class Conflict(SyncCode, Base): """ copy_path = self.copy_path return copy_path - + def setCopyPath(self, path): """ """ self.copy_path = path - class Signature(Folder,SyncCode): """ @@ -249,10 +248,14 @@ class Signature(Folder,SyncCode): """ isIndexable = 0 isPortalContent = 0 # Make sure RAD generated accessors at the class level - + # Constructor - def __init__(self, id=None, rid=None, status=None, xml_string=None, - object=None): + def __init__(self, + id=None, + rid=None, + status=None, + xml_string=None, + object=None): if object is not None: self.setPath(object.getPhysicalPath()) self.setObjectId(object.getId()) @@ -312,7 +315,7 @@ class Signature(Folder,SyncCode): """ get the force value (if we need to force update or not) """ - return getattr(self,'path',None) + return getattr(self, 'path', None) def setPath(self, path): """ @@ -337,28 +340,28 @@ class Signature(Folder,SyncCode): get the last modfication date, so that we don't always check the xml """ - return getattr(self,'modification_date',None) + return getattr(self, 'modification_date', None) def setLastModificationDate(self,value): """ set the last modfication date, so that we don't always check the xml """ - setattr(self,'modification_date',value) + setattr(self, 'modification_date', value) def getLastSynchronizationDate(self): """ get the last modfication date, so that we don't always check the xml """ - return getattr(self,'synchronization_date',None) + return getattr(self, 'synchronization_date', None) def setLastSynchronizationDate(self,value): """ set the last modfication date, so that we don't always check the xml """ - setattr(self,'synchronization_date',value) + setattr(self, 'synchronization_date', value) def setXML(self, xml): """ @@ -373,7 +376,7 @@ class Signature(Folder,SyncCode): """ get the XML corresponding to the object """ - xml = getattr(self,'xml',None) + xml = getattr(self, 'xml', None) if xml == '': xml = None return xml @@ -441,7 +444,7 @@ class Signature(Folder,SyncCode): """ set the rid """ - if rid is type(u'a'): + if rid is type(u'a'): rid = rid.encode('utf-8') self.rid = rid @@ -455,7 +458,7 @@ class Signature(Folder,SyncCode): """ set the id """ - if id is type(u'a'): + if id is type(u'a'): id = id.encode('utf-8') self.id = id @@ -469,7 +472,7 @@ class Signature(Folder,SyncCode): """ set the gid """ - if gid is type(u'a'): + if gid is type(u'a'): gid = gid.encode('utf-8') self.gid = gid @@ -483,7 +486,7 @@ class Signature(Folder,SyncCode): """ set the id of the object associated to this signature """ - if id is type(u'a'): + if id is type(u'a'): id = id.encode('utf-8') self.object_id = id @@ -507,7 +510,7 @@ class Signature(Folder,SyncCode): Set the partial string we will have to deliver in the future """ - #LOG('Subscriber.getPartialXML',0,'partial_xml: %s' % str(self.partial_xml)) + #LOG('Subscriber.getPartialXML', DEBUG, 'partial_xml: %s' % str(self.partial_xml)) if self.partial_xml is not None: self.partial_xml = self.partial_xml.replace('@-@@-@','--') # need to put back '--' return self.partial_xml @@ -544,7 +547,6 @@ class Signature(Folder,SyncCode): """ Return the actual action for a partial synchronization """ - # LOG('setConflictList, list',0,conflict_list) if conflict_list is None or conflict_list==[]: self.resetConflictList() else: @@ -554,7 +556,7 @@ class Signature(Folder,SyncCode): """ Return the actual action for a partial synchronization """ - # LOG('delConflict, conflict',0,conflict) + LOG('delConflict, conflict', DEBUG, conflict) conflict_list = [] for c in self.getConflictList(): #LOG('delConflict, c==conflict',0,c==aq_base(conflict)) @@ -575,7 +577,6 @@ def addSubscription( self, id, title='', REQUEST=None ): """ Add a new Subscribption """ - LOG('addSubscription starting...',0,'') o = Subscription( id ,'','','','','','') self._setObject( id, o ) if REQUEST is not None: @@ -646,10 +647,10 @@ class Subscription(Folder, SyncCode): ) # Constructor - def __init__(self, id, title, publication_url, subscription_url, - destination_path, source_uri, target_uri, query, xml_mapping, - conduit, gpg_key, id_generator, gid_generator, media_type, login, - password, activity_enabled, alert_code, synchronize_with_erp5_sites, + def __init__(self, id, title, publication_url, subscription_url, + destination_path, source_uri, target_uri, query, xml_mapping, + conduit, gpg_key, id_generator, gid_generator, media_type, login, + password, activity_enabled, alert_code, synchronize_with_erp5_sites, sync_content_type): """ We need to create a dictionnary of @@ -686,8 +687,7 @@ class Subscription(Folder, SyncCode): #self.signatures = PersitentMapping() def getAlertCodeList(self): - #XXX replace by a dictionary or a list in SyncCode - return [self.TWO_WAY, self.ONE_WAY_FROM_SERVER] + return self.CODE_LIST def getAlertCode(self): return getattr(self, 'alert_code', 200) @@ -721,7 +721,7 @@ class Subscription(Folder, SyncCode): setter for title """ self.title = value - + def setSourceURI(self, value): """ setter for source_uri @@ -751,7 +751,7 @@ class Subscription(Folder, SyncCode): """ content type used by the subscriber """ - self.sync_content_type=sync_content_type + self.sync_content_type = sync_content_type # the varible name is sync_content_type instead of content_type because # content_type seems to be a function name already used @@ -768,16 +768,16 @@ class Subscription(Folder, SyncCode): # XXXXXXXXXXXXXXXXXXXXXXXXXXXXX # XXX for debugging only, to be removed #dict_sign = {} - #for o in self.objectValues(): + #for o in self.getSignatureList(): #dict_sign[o.getId()] = o.getStatus() - # LOG('getSignature',0,'signatures_status: %s' % str(dict_sign)) + # LOG('getSignature', DEBUG, 'signatures_status: %s' % str(dict_sign)) # XXXXXXXXXXXXXXXXXXXXXXXXXXXXX code = self.SLOW_SYNC - if len(self.objectValues()) > 0: + if len(self.getSignatureList()) > 0: code = self.getAlertCode() if default is not None: code = default - #LOG('Subscription',0,'getSynchronizationType: %s' % code) + #LOG('Subscription', DEBUG, 'getSynchronizationType: %s' % code) return code def setXMLMapping(self, value): @@ -801,7 +801,7 @@ class Subscription(Folder, SyncCode): """ return True if the synchronisation is between two erp5 sites """ - return getattr(self, 'synchronize_with_erp5_sites', None) + return getattr(self, 'synchronize_with_erp5_sites', True) def checkCorrectRemoteSessionId(self, session_id): """ @@ -810,7 +810,7 @@ class Subscription(Folder, SyncCode): return True if the session id was not seen, False if already seen """ - last_session_id = getattr(self,'last_session_id',None) + last_session_id = getattr(self, 'last_session_id', None) if last_session_id == session_id: return False self.last_session_id = session_id @@ -824,8 +824,8 @@ class Subscription(Folder, SyncCode): return True if the message id was not seen, False if already seen """ last_message_id = getattr(self,'last_message_id',None) - # LOG('checkCorrectRemoteMessageId last_message_id =',0,last_message_id) - # LOG('checkCorrectRemoteMessageId message_id =',0,message_id) + LOG('checkCorrectRemoteMessageId last_message_id = ', DEBUG, last_message_id) + LOG('checkCorrectRemoteMessageId message_id = ', DEBUG, message_id) if last_message_id == message_id: return False self.last_message_id = message_id @@ -835,13 +835,13 @@ class Subscription(Folder, SyncCode): """ set the last message id to 0 """ - self.last_message_id=last_message_id + self.last_message_id = last_message_id def getLastSentMessage(self): """ This is the getter for the last message we have sent """ - return getattr(self,'last_sent_message','') + return getattr(self, 'last_sent_message', '') def setLastSentMessage(self,xml): """ @@ -889,7 +889,7 @@ class Subscription(Folder, SyncCode): """ return the gnupg key name """ - return getattr(self,'gpg_key','') + return getattr(self, 'gpg_key', '') def setGPGKey(self, value): """ @@ -971,7 +971,7 @@ class Subscription(Folder, SyncCode): """ set the type of media used """ - if media_type in (None,''): + if media_type in (None, ''): media_type = self.MEDIA_TYPE['TEXT_XML'] self.media_type = media_type @@ -985,7 +985,7 @@ class Subscription(Folder, SyncCode): """ set the login at new_login """ - self.login=new_login + self.login = new_login def getPassword(self): """ @@ -997,8 +997,7 @@ class Subscription(Folder, SyncCode): """ set the password at new_password """ - self.password=new_password - + self.password = new_password def setAuthentication(self, auth): """ @@ -1037,7 +1036,7 @@ class Subscription(Folder, SyncCode): o_gid = None gid_gen = self.getGidGenerator() if callable(gid_gen): - o_gid=gid_gen(object) + o_gid = gid_gen(object) elif getattr(o_base, gid_gen, None) is not None: generator = getattr(object, gid_gen) o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant @@ -1066,17 +1065,17 @@ class Subscription(Folder, SyncCode): o_id = signature.getObjectId() #try with id param too, because gid is not catalogged object_list = self.getObjectList(gid = b16decode(gid), id = o_id) - #LOG('getObjectFromGid :',0,'object_list=%s, gid=%s, o_id=%s' % (object_list, gid, o_id)) + LOG('getObjectFromGid :', DEBUG, 'object_list=%s, gid=%s, o_id=%s' % (object_list, gid, o_id)) if o is not None and o in object_list: return o #LOG('entering in the slow loop of getObjectFromGid !!!',0,'') object_list = self.getObjectList(gid = b16decode(gid)) - #LOG('getObjectFromGid :', 0, 'object_list slow loop=%s, gid=%s' % (object_list, gid)) + LOG('getObjectFromGid :', DEBUG, 'object_list slow loop=%s, gid=%s' % (object_list, gid)) for o in object_list: o_gid = self.getGidFromObject(o) if o_gid == gid: return o - #LOG('getObjectFromGid',0,'returning None') + LOG('getObjectFromGid', DEBUG, 'returning None') return None def getObjectFromId(self, id): @@ -1103,17 +1102,7 @@ class Subscription(Folder, SyncCode): o = destination.getPortalObject().restrictedTraverse(signature.getPath()) except: pass - return o - - - -# def setOneWaySyncFromServer(self,value): -# """ -# If this option is enabled, then we will not -# send our own modifications -# """ -# self.one_way_sync_from_server = value -# + return o def getObjectList(self, **kw): """ @@ -1124,7 +1113,7 @@ class Subscription(Folder, SyncCode): query = self.getQuery() query_list = [] if query is not None and isinstance(query, str): - query_method = getattr(destination,query,None) + query_method = getattr(destination, query, None) if query_method is not None: query_list = query_method(**kw) elif callable(query): # used in the test @@ -1132,7 +1121,7 @@ class Subscription(Folder, SyncCode): return [x for x in query_list if not getattr(x,'_conflict_resolution',False)] - def generateNewIdWithGenerator(self, object=None,gid=None): + def generateNewIdWithGenerator(self, object=None, gid=None): """ This tries to generate a new Id """ @@ -1141,15 +1130,15 @@ class Subscription(Folder, SyncCode): o_base = aq_base(object) new_id = None if callable(id_generator): - new_id = id_generator(object,gid=gid) + new_id = id_generator(object, gid=gid) elif getattr(o_base, id_generator, None) is not None: generator = getattr(object, id_generator) new_id = generator() else: # This is probably a python script generator = getattr(object, id_generator) - new_id = generator(object=object,gid=gid) - #LOG('generateNewId, new_id: ',0,new_id) + new_id = generator(object=object, gid=gid) + LOG('generateNewId, new_id: ', DEBUG, new_id) return new_id return None @@ -1158,7 +1147,7 @@ class Subscription(Folder, SyncCode): This set the method name wich allows to generate a new id """ - if method in ('','None'): + if method in ('', 'None'): method = None self.synchronization_id_generator = method @@ -1203,7 +1192,7 @@ class Subscription(Folder, SyncCode): return the current subscription """ return self - + def setSessionId(self, session_id): """ set the session id @@ -1229,9 +1218,6 @@ class Subscription(Folder, SyncCode): """ return the message id """ - #self.message_id += 1 - #return self.message_id - #return 5 value = getattr(self, 'message_id', 0) self.message_id = value +1 return self.message_id @@ -1247,7 +1233,7 @@ class Subscription(Folder, SyncCode): set the message id to 0 """ self.message_id = 0 - + def setMessageId(self, message_id): """ set the message id to message_id @@ -1298,7 +1284,7 @@ class Subscription(Folder, SyncCode): """ add a Signature to the subscription """ - if self.getSignatureFromGid(signature.getGid()) != None: + if self.getSignatureFromGid(signature.getGid()) is not None: self.delSignature(signature.getGid()) self._setObject(signature.getGid(), aq_base(signature)) @@ -1306,12 +1292,11 @@ class Subscription(Folder, SyncCode): """ del a Signature of the subscription """ - #del self.signatures[gid] self._delObject(gid) def getSignatureFromObjectId(self, id): """ - return the signature corresponding to the gid + return the signature corresponding to the id """ o = None # XXX very slow @@ -1343,35 +1328,23 @@ class Subscription(Folder, SyncCode): """ Returns the list of gids from signature """ - object_id_list = [] - for signature in self.getSignatureList(): - if signature.getObjectId() is not None: - object_id_list.append(signature.getObjectId()) - return object_id_list + return [s for s in self.getSignatureList() if s.getObjectId() is not None] def getGidList(self): """ Returns the list of gids from signature """ - gid_list = [] - for signature in self.getSignatureList(): - if signature.getGid() is not None: - gid_list.append(signature.getGid()) - return gid_list + return [s.getGid() for s in self.getSignatureList() if s.getGid() is not None] def getRidList(self): """ Returns the list of rids from signature """ - rid_list = [] - for signature in self.getSignatureList(): - if signature.getRid() is not None: - rid_list.append(signature.getRid()) - return rid_list + return [s.getRid() for s in self.getSignatureList() if s.getRid() is not None] def getSignatureList(self): """ - add a Signature to the subscription + Returns the list of Signatures """ return self.objectValues() @@ -1379,16 +1352,17 @@ class Subscription(Folder, SyncCode): """ Check if there's a signature with this uid """ - #return self.signatures.has_key(gid) return self.getSignatureFromGid(gid) is not None def resetAllSignatures(self): """ - Reset all signatures + Reset all signatures in activities """ - while len(self.objectIds())>0: - for id in self.objectIds(): - self._delObject(id) + object_id_list = [id for id in self.getObjectIds()] + object_list_len = len(object_id_list) + for i in xrange(0, object_list_len, 100): + current_id_list = object_id_list[i:i+100] + self.activate().manage_delObjects(current_id_list) def getConflictList(self): """ @@ -1396,7 +1370,7 @@ class Subscription(Folder, SyncCode): """ conflict_list = [] for signature in self.getSignatureList(): - conflict_list += signature.getConflictList() + conflict_list.extend(signature.getConflictList()) return conflict_list def getRemainingObjectPathList(self): @@ -1404,14 +1378,14 @@ class Subscription(Folder, SyncCode): We should now wich objects should still synchronize """ - return getattr(self,'remaining_object_path_list',None) + return getattr(self, 'remaining_object_path_list', None) def setRemainingObjectPathList(self, value): """ We should now wich objects should still synchronize """ - setattr(self,'remaining_object_path_list',value) + setattr(self, 'remaining_object_path_list', value) def removeRemainingObjectPath(self, object_path): """ @@ -1430,13 +1404,14 @@ class Subscription(Folder, SyncCode): """ Set the status of every object as NOT_SYNCHRONIZED """ - for o in self.objectValues(): + for s in self.getSignatureList(): # Change the status only if we are not in a conflict mode - if not(o.getStatus() in (self.CONFLICT,self.PUB_CONFLICT_MERGE, - self.PUB_CONFLICT_CLIENT_WIN)): - o.setStatus(self.NOT_SYNCHRONIZED) - o.setPartialXML(None) - o.setTempXML(None) + if s.getStatus() not in (self.CONFLICT, + self.PUB_CONFLICT_MERGE, + self.PUB_CONFLICT_CLIENT_WIN): + s.setStatus(self.NOT_SYNCHRONIZED) + s.setPartialXML(None) + s.setTempXML(None) self.setRemainingObjectPathList(None) @@ -1445,8 +1420,8 @@ class Subscription(Folder, SyncCode): return True if the subscriber is authenticated for this session, False in other case """ - return self.is_authenticated - + return getattr(self, 'is_authenticated', None) + def setAuthenticated(self, value): """ set at True or False the value of is_authenticated is the subscriber @@ -1464,7 +1439,7 @@ class Subscription(Folder, SyncCode): return b64encode(string_to_encode) #elif format is .... put here the other formats else:#if there is no format corresponding with format, raise an error - #LOG('encode : unknown or not implemented format :', 0, format) + LOG('encode : unknown or not implemented format : ', INFO, format) raise ValueError, "Sorry, the server ask for the format %s but it's unknow or not implemented" % format def decode(self, format, string_to_decode): @@ -1478,7 +1453,7 @@ class Subscription(Folder, SyncCode): return b64decode(string_to_decode) #elif format is .... put here the other formats else:#if there is no format corresponding with format, raise an error - #LOG('decode : unknown or not implemented format :', 0, format) + LOG('decode : unknown or not implemented format :', INFO, format) raise ValueError, "Sorry, the format %s is unknow or not implemented" % format def isDecodeEncodeTheSame(self, string_encoded, string_decoded, format): @@ -1486,20 +1461,16 @@ class Subscription(Folder, SyncCode): return True if the string_encoded is equal to string_decoded encoded in format """ - isTheSame=False - if self.encode(format, string_decoded) == string_encoded: - isTheSame=True - return isTheSame - + return self.encode(format, string_decoded) == string_encoded def setUser(self, user): """ save the user logged in to log him on each transaction """ - self.user=user + self.user = user def getUser(self): """ retrun the user logged in """ - return self.user + return getattr(self, 'user', None) diff --git a/product/ERP5SyncML/SubscriptionSynchronization.py b/product/ERP5SyncML/SubscriptionSynchronization.py index 086d7041b44dd5fd0d061702cc14563316ddcb42..581326736abd0258f47c8b82adb9ed41c6885cab 100644 --- a/product/ERP5SyncML/SubscriptionSynchronization.py +++ b/product/ERP5SyncML/SubscriptionSynchronization.py @@ -32,7 +32,7 @@ from XMLSyncUtils import XMLSyncUtils, Parse import commands from Conduit.ERP5Conduit import ERP5Conduit from DateTime import DateTime -from zLOG import LOG +from zLOG import LOG, DEBUG, INFO class SubscriptionSynchronization(XMLSyncUtils): @@ -48,8 +48,8 @@ class SubscriptionSynchronization(XMLSyncUtils): xml = xml_list.append xml('<SyncML>\n') # syncml header - xml(self.SyncMLHeader(subscription.incrementSessionId(), - subscription.incrementMessageId(), subscription.getPublicationUrl(), + xml(self.SyncMLHeader(subscription.incrementSessionId(), + subscription.incrementMessageId(), subscription.getPublicationUrl(), subscription.getSubscriptionUrl(), source_name=subscription.getLogin())) # syncml body @@ -62,7 +62,7 @@ class SubscriptionSynchronization(XMLSyncUtils): xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(), subscription.getTargetURI(), subscription.getSourceURI(), - subscription.getLastAnchor(), + subscription.getLastAnchor(), subscription.getNextAnchor())) cmd_id += 1 syncml_put = self.SyncMLPut(cmd_id, subscription) @@ -74,9 +74,9 @@ class SubscriptionSynchronization(XMLSyncUtils): xml_a = ''.join(xml_list) self.sendResponse(from_url=subscription.subscription_url, - to_url=subscription.publication_url, sync_id=subscription.getTitle(), - xml=xml_a,domain=subscription, - content_type=subscription.getSyncContentType()) + to_url=subscription.publication_url, sync_id=subscription.getTitle(), + xml=xml_a,domain=subscription, + content_type=subscription.getSyncContentType()) return {'has_response':1,'xml':xml_a} @@ -87,7 +87,7 @@ class SubscriptionSynchronization(XMLSyncUtils): response = None #check if subsync replies to this messages subscription = self.unrestrictedTraverse(subscription_path) if msg==None and (subscription.getSubscriptionUrl()).find('file')>=0: - msg = self.readResponse(sync_id=subscription.getSubscriptionUrl(), + msg = self.readResponse(sync_id=subscription.getSubscriptionUrl(), from_url=subscription.getSubscriptionUrl()) if msg==None: response = self.SubSyncInit(subscription) @@ -100,11 +100,11 @@ class SubscriptionSynchronization(XMLSyncUtils): status_code_syncHdr = status_list[0]['code'] if status_code_syncHdr.isdigit(): status_code_syncHdr = int(status_code_syncHdr) - #LOG('readResponse status code :',0,status_code_syncHdr) + LOG('SubSync status code : ', DEBUG, status_code_syncHdr) if status_code_syncHdr == self.AUTH_REQUIRED: if self.checkChal(xml_client): authentication_format, authentication_type = self.getChal(xml_client) - #LOG('auth_required :',0, 'format:%s, type:%s' % (authentication_format, authentication_type)) + LOG('SubSync auth_required :', DEBUG, 'format:%s, type:%s' % (authentication_format, authentication_type)) if authentication_format is not None and \ authentication_type is not None: subscription.setAuthenticationFormat(authentication_format) @@ -113,14 +113,14 @@ class SubscriptionSynchronization(XMLSyncUtils): raise ValueError, "Sorry, the server chalenge for an \ authentication, but the authentication format is not find" - #LOG('readResponse', 0, 'Authentication required') + LOG('SubSync', INFO, 'Authentication required') response = self.SubSyncCred(subscription, xml_client) elif status_code_syncHdr == self.UNAUTHORIZED: - LOG('readResponse', 0, 'Bad authentication') - return {'has_response':0,'xml':xml_client} + LOG('SubSync', INFO, 'Bad authentication') + return {'has_response':0, 'xml':xml_client} else: response = self.SubSyncModif(subscription, xml_client) - else: + else: response = self.SubSyncModif(subscription, xml_client) if RESPONSE is not None: @@ -141,12 +141,12 @@ class SubscriptionSynchronization(XMLSyncUtils): data=subscription.encode(subscription.getAuthenticationFormat(), data) xml(self.SyncMLHeader( subscription.incrementSessionId(), - subscription.incrementMessageId(), + subscription.incrementMessageId(), subscription.getPublicationUrl(), - subscription.getSubscriptionUrl(), - source_name=subscription.getLogin(), + subscription.getSubscriptionUrl(), + source_name=subscription.getLogin(), dataCred=data, - authentication_format=subscription.getAuthenticationFormat(), + authentication_format=subscription.getAuthenticationFormat(), authentication_type=subscription.getAuthenticationType())) # syncml body @@ -174,7 +174,7 @@ class SubscriptionSynchronization(XMLSyncUtils): xml=xml_a,domain=subscription, content_type=subscription.getSyncContentType()) - return {'has_response':1,'xml':xml_a} + return {'has_response':1, 'xml':xml_a} def SubSyncModif(self, subscription, xml_client): """ diff --git a/product/ERP5SyncML/SyncCode.py b/product/ERP5SyncML/SyncCode.py index e4883ee8fb9cf477bcfb517f530cc00c46e0fbc9..0667d38b4244e1a8f3212ba3f8a95a19e110ff79 100644 --- a/product/ERP5SyncML/SyncCode.py +++ b/product/ERP5SyncML/SyncCode.py @@ -40,6 +40,7 @@ class SyncCode(Persistent): ONE_WAY_FROM_SERVER = 204 WAITING_DATA = 214 REFRESH_REQUIRED = 508 + CODE_LIST = ( TWO_WAY, ONE_WAY_FROM_SERVER ) # SyncML Status Codes SUCCESS = 200 diff --git a/product/ERP5SyncML/SynchronizationTool.py b/product/ERP5SyncML/SynchronizationTool.py index 072596b79e461c2de8360df570049624539090f9..a376be15d17194bb1f31d02abd4832acc7456bb2 100644 --- a/product/ERP5SyncML/SynchronizationTool.py +++ b/product/ERP5SyncML/SynchronizationTool.py @@ -60,7 +60,7 @@ import string import commands import random from DateTime import DateTime -from zLOG import LOG +from zLOG import LOG, TRACE, DEBUG, INFO class TimeoutHTTPConnection(httplib.HTTPConnection): """ @@ -76,7 +76,7 @@ class TimeoutHTTPHandler(urllib2.HTTPHandler): -class SynchronizationTool( SubscriptionSynchronization, +class SynchronizationTool( SubscriptionSynchronization, PublicationSynchronization, UniqueObject, Folder): """ This tool implements the synchronization algorithm @@ -183,7 +183,7 @@ class SynchronizationTool( SubscriptionSynchronization, authentication_type='', RESPONSE=None, activity_enabled = False, sync_content_type='application/vnd.syncml+xml', synchronize_with_erp5_sites=True): - """ + """ create a new publication """ #if not('publications' in self.objectIds()): @@ -191,12 +191,12 @@ class SynchronizationTool( SubscriptionSynchronization, # self._setObject(publications.id, publications) folder = self.getObjectContainer() new_id = self.getPublicationIdFromTitle(title) - pub = Publication(new_id, title, publication_url, - destination_path, source_uri, query, xml_mapping, - conduit, gpg_key, synchronization_id_generator, - gid_generator, media_type, auth_required, - authentication_format, authentication_type, - activity_enabled, synchronize_with_erp5_sites, + pub = Publication(new_id, title, publication_url, + destination_path, source_uri, query, xml_mapping, + conduit, gpg_key, synchronization_id_generator, + gid_generator, media_type, auth_required, + authentication_format, authentication_type, + activity_enabled, synchronize_with_erp5_sites, sync_content_type) folder._setObject( new_id, pub ) #if len(self.list_publications) == 0: @@ -205,16 +205,16 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('managePublications') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_addSubscription') def manage_addSubscription(self, title, publication_url, subscription_url, destination_path, source_uri, target_uri, query, xml_mapping, conduit, gpg_key, synchronization_id_generator=None, gid_generator=None, media_type=None, login=None, password=None, - RESPONSE=None, activity_enabled=False, - alert_code=SyncCode.TWO_WAY, - synchronize_with_erp5_sites = True, + RESPONSE=None, activity_enabled=False, + alert_code=SyncCode.TWO_WAY, + synchronize_with_erp5_sites = True, sync_content_type='application/vnd.syncml+xml'): """ XXX should be renamed as addSubscription @@ -308,7 +308,7 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('manageSubscriptions') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_deletePublication') def manage_deletePublication(self, title, RESPONSE=None): """ @@ -320,7 +320,7 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('managePublications') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_deleteSubscription') def manage_deleteSubscription(self, title, RESPONSE=None): """ @@ -332,7 +332,7 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('manageSubscriptions') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_resetPublication') def manage_resetPublication(self, title, RESPONSE=None): """ @@ -343,7 +343,7 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('managePublications') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_resetSubscription') def manage_resetSubscription(self, title, RESPONSE=None): """ @@ -355,7 +355,7 @@ class SynchronizationTool( SubscriptionSynchronization, if RESPONSE is not None: RESPONSE.redirect('manageSubscriptions') - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'manage_syncSubscription') def manage_syncSubscription(self, title, RESPONSE=None): """ @@ -372,8 +372,8 @@ class SynchronizationTool( SubscriptionSynchronization, Return a list of publications """ folder = self.getObjectContainer() - object_list = folder.objectValues() - object_list = filter(lambda x: x.id.find('pub')==0,object_list) + object_list = [pub for pub in folder.objectValues() if pub.getDomainType() == self.PUB] + #object_list = filter(lambda x: x.id.find('pub')==0,object_list) return object_list security.declareProtected(Permissions.AccessContentsInformation, @@ -382,10 +382,12 @@ class SynchronizationTool( SubscriptionSynchronization, """ Return the publications with this id """ + pub = None for p in self.getPublicationList(): if p.getTitle() == title: - return p - return None + pub = p + break + return pub security.declareProtected(Permissions.AccessContentsInformation, 'getObjectContainer') @@ -407,18 +409,19 @@ class SynchronizationTool( SubscriptionSynchronization, Return a list of publications """ folder = self.getObjectContainer() - object_list = folder.objectValues() - object_list = filter(lambda x: x.id.find('sub')==0,object_list) + object_list = [sub for sub in folder.objectValues() if sub.getDomainType() == self.SUB] + #object_list = filter(lambda x: x.id.find('sub')==0,object_list) return object_list def getSubscription(self, title): """ Returns the subscription with this title """ + sub = None for s in self.getSubscriptionList(): if s.getTitle() == title: - return s - return None + sub = s + return sub security.declareProtected(Permissions.AccessContentsInformation, @@ -426,7 +429,6 @@ class SynchronizationTool( SubscriptionSynchronization, def getSynchronizationList(self): """ Returns the list of subscriptions and publications - """ return self.getSubscriptionList() + self.getPublicationList() @@ -437,9 +439,9 @@ class SynchronizationTool( SubscriptionSynchronization, Returns the list of subscribers and subscriptions """ s_list = [] - s_list += self.getSubscriptionList() + s_list.extend(self.getSubscriptionList()) for publication in self.getPublicationList(): - s_list += publication.getSubscriberList() + s_list.extend(publication.getSubscriberList()) return s_list security.declareProtected(Permissions.AccessContentsInformation, @@ -458,27 +460,17 @@ class SynchronizationTool( SubscriptionSynchronization, for subscriber in publication.getSubscriberList(): sub_conflict_list = subscriber.getConflictList() for conflict in sub_conflict_list: - #conflict.setDomain('Publication') conflict.setSubscriber(subscriber) - #conflict.setDomainId(subscriber.getId()) if path is None or conflict.getObjectPath() == path: conflict_list += [conflict.__of__(subscriber)] for subscription in self.getSubscriptionList(): sub_conflict_list = subscription.getConflictList() - #LOG('SynchronizationTool.getConflictList, sub_conflict_list',0, - #sub_conflict_list) + LOG('SynchronizationTool.getConflictList, sub_conflict_list', DEBUG, + sub_conflict_list) for conflict in sub_conflict_list: - #conflict.setDomain('Subscription') conflict.setSubscriber(subscription) - #conflict.setDomainId(subscription.getId()) if path is None or conflict.getObjectPath() == path: conflict_list += [conflict.__of__(subscription)] - #if path is not None: # Retrieve only conflicts for a given path - # new_list = [] - # for conflict in conflict_list: - # if conflict.getObjectPath() == path: - # new_list += [conflict.__of__(self)] - # return new_list return conflict_list security.declareProtected(Permissions.AccessContentsInformation, @@ -511,32 +503,32 @@ class SynchronizationTool( SubscriptionSynchronization, path = self.resolveContext(context) conflict_list = self.getConflictList() state_list= [] - #LOG('getSynchronizationState',0,'path: %s' % str(path)) + LOG('getSynchronizationState', DEBUG, 'path: %s' % str(path)) for conflict in conflict_list: if conflict.getObjectPath() == path: - #LOG('getSynchronizationState',0,'found a conflict: %s' % str(conflict)) + LOG('getSynchronizationState', DEBUG, 'found a conflict: %s' % str(conflict)) state_list += [[conflict.getSubscriber(),self.CONFLICT]] for domain in self.getSynchronizationList(): destination = domain.getDestinationPath() - #LOG('getSynchronizationState',0,'destination: %s' % str(destination)) + LOG('getSynchronizationState', TRACE, 'destination: %s' % str(destination)) j_path = '/'.join(path) - #LOG('getSynchronizationState',0,'j_path: %s' % str(j_path)) + LOG('getSynchronizationState', TRACE, 'j_path: %s' % str(j_path)) if j_path.find(destination)==0: o_id = j_path[len(destination)+1:].split('/')[0] - #LOG('getSynchronizationState',0,'o_id: %s' % o_id) + LOG('getSynchronizationState', TRACE, 'o_id: %s' % o_id) subscriber_list = [] if domain.domain_type==self.PUB: subscriber_list = domain.getSubscriberList() else: subscriber_list = [domain] - #LOG('getSynchronizationState, subscriber_list:',0,subscriber_list) + LOG('getSynchronizationState, subscriber_list:', TRACE, subscriber_list) for subscriber in subscriber_list: signature = subscriber.getSignatureFromObjectId(o_id) #XXX check if signature could be not None ... if signature is not None: state = signature.getStatus() - #LOG('getSynchronizationState:',0,'sub.dest :%s, state: %s' % \ - #(subscriber.getSubscriptionUrl(),str(state))) + LOG('getSynchronizationState:', TRACE, 'sub.dest :%s, state: %s' % \ + (subscriber.getSubscriptionUrl(),str(state))) found = None # Make sure there is not already a conflict giving the state for state_item in state_list: @@ -546,7 +538,12 @@ class SynchronizationTool( SubscriptionSynchronization, state_list += [[subscriber,state]] return state_list - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.AccessContentsInformation, + 'getAlertCodeList') + def getAlertCodeList(self): + return self.CODE_LIST + + security.declareProtected(Permissions.ModifyPortalContent, 'applyPublisherValue') def applyPublisherValue(self, conflict): """ @@ -556,38 +553,37 @@ class SynchronizationTool( SubscriptionSynchronization, object = self.unrestrictedTraverse(conflict.getObjectPath()) subscriber = conflict.getSubscriber() # get the signature: - #LOG('p_sync.applyPublisherValue, subscriber: ',0,subscriber) + LOG('p_sync.applyPublisherValue, subscriber: ', DEBUG, subscriber) signature = subscriber.getSignatureFromObjectId(object.getId()) # XXX may be change for rid copy_path = conflict.getCopyPath() - #LOG('p_sync.applyPublisherValue, copy_path: ',0,copy_path) + LOG('p_sync.applyPublisherValue, copy_path: ', TRACE, copy_path) signature.delConflict(conflict) if signature.getConflictList() == []: if copy_path is not None: - #LOG('p_sync.applyPublisherValue, conflict_list empty on : ',0,signature) + LOG('p_sync.applyPublisherValue, conflict_list empty on : ', TRACE, signature) # Delete the copy of the object if the there is one directory = object.aq_parent copy_id = copy_path[-1] - #LOG('p_sync.applyPublisherValue, copy_id: ',0,copy_id) + LOG('p_sync.applyPublisherValue, copy_id: ', TRACE, copy_id) if hasattr(directory.aq_base, 'hasObject'): # optimize the case of a BTree folder - #LOG('p_sync.applyPublisherValue, deleting...: ',0,copy_id) + LOG('p_sync.applyPublisherValue, deleting...: ', TRACE, copy_id) if directory.hasObject(copy_id): directory._delObject(copy_id) elif copy_id in directory.objectIds(): directory._delObject(copy_id) signature.setStatus(self.PUB_CONFLICT_MERGE) - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'applyPublisherDocument') def applyPublisherDocument(self, conflict): """ apply the publisher value for all conflict of the given document """ subscriber = conflict.getSubscriber() - #LOG('applyPublisherDocument, subscriber: ',0,subscriber) for c in self.getConflictList(conflict.getObjectPath()): if c.getSubscriber() == subscriber: - #LOG('applyPublisherDocument, applying on conflict: ',0,conflict) + LOG('applyPublisherDocument, applying on conflict: ', DEBUG, conflict) c.applyPublisherValue() security.declareProtected(Permissions.AccessContentsInformation, @@ -606,9 +602,8 @@ class SynchronizationTool( SubscriptionSynchronization, apply the publisher value for all conflict of the given document """ publisher_object_path = self.getPublisherDocumentPath(conflict) - #LOG('getPublisherDocument publisher_object_path',0,publisher_object_path) + LOG('getPublisherDocument publisher_object_path', TRACE, publisher_object_path) publisher_object = self.unrestrictedTraverse(publisher_object_path) - #LOG('getPublisherDocument publisher_object',0,publisher_object) return publisher_object @@ -621,23 +616,23 @@ class SynchronizationTool( SubscriptionSynchronization, Thus, the manager will be able to open both version of the document before selecting which one to keep. """ - subscriber = conflict.getSubscriber() publisher_object_path = conflict.getObjectPath() publisher_object = self.unrestrictedTraverse(publisher_object_path) - publisher_xml = self.getXMLObject(object=publisher_object,xml_mapping\ - = subscriber.getXMLMapping()) - + publisher_xml = self.getXMLObject( + object=publisher_object, + xml_mapping=subscriber.getXMLMapping()) directory = publisher_object.aq_parent object_id = docid if object_id in directory.objectIds(): directory._delObject(object_id) # Import the conduit and get it conduit_name = subscriber.getConduit() - conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]), - globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() - conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id) + conduit = self.getConduitByName(conduit_name) + conduit.addNode( + xml=publisher_xml, + object=directory, + object_id=object_id) subscriber_document = directory._getOb(object_id) for c in self.getConflictList(conflict.getObjectPath()): if c.getSubscriber() == subscriber: @@ -646,7 +641,7 @@ class SynchronizationTool( SubscriptionSynchronization, def _getCopyId(self, object): directory = object.aq_inner.aq_parent - if directory.getId() != 'portal_repository': + if directory.getId() != 'portal_repository': object_id = object.getId() + '_conflict_copy' if object_id in directory.objectIds(): directory._delObject(object_id) @@ -656,10 +651,9 @@ class SynchronizationTool( SubscriptionSynchronization, new_rev = repotool.getFreeRevision(docid) + 10 # make sure it's not gonna provoke conflicts object_id = repotool._getId(docid, new_rev) return object_id - + security.declareProtected(Permissions.AccessContentsInformation, 'getSubscriberDocumentPath') - def getSubscriberDocumentPath(self, conflict): """ apply the publisher value for all conflict of the given document @@ -672,19 +666,14 @@ class SynchronizationTool( SubscriptionSynchronization, publisher_object = self.unrestrictedTraverse(publisher_object_path) publisher_xml = subscriber.getXMLFromObject(publisher_object) directory = publisher_object.aq_inner.aq_parent - object_id = self._getCopyId(publisher_object) + object_id = self._getCopyId(publisher_object) # Import the conduit and get it conduit_name = subscriber.getConduit() - if conduit_name.startswith('Products'): - path = conduit_name - conduit_name = conduit_name.split('.')[-1] - conduit_module = __import__(path, globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() - else: - conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]), - globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() - conduit.addNode(xml=publisher_xml,object=directory,object_id=object_id) + conduit = self.getConduitByName(conduit_name) + conduit.addNode( + xml=publisher_xml, + object=directory, + object_id=object_id) subscriber_document = directory._getOb(object_id) subscriber_document._conflict_resolution = 1 for c in self.getConflictList(conflict.getObjectPath()): @@ -693,7 +682,7 @@ class SynchronizationTool( SubscriptionSynchronization, copy_path = subscriber_document.getPhysicalPath() conflict.setCopyPath(copy_path) return copy_path - + security.declareProtected(Permissions.AccessContentsInformation, 'getSubscriberDocument') def getSubscriberDocument(self, conflict): @@ -735,9 +724,7 @@ class SynchronizationTool( SubscriptionSynchronization, signature = subscriber.getSignatureFromObjectId(object.getId()) # XXX may be change for rid # Import the conduit and get it conduit_name = subscriber.getConduit() - conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]), - globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() + conduit = self.getConduitByName(conduit_name) for xupdate in conflict.getXupdateList(): conduit.updateNode(xml=xupdate,object=object,force=1) if solve_conflict: @@ -756,9 +743,9 @@ class SynchronizationTool( SubscriptionSynchronization, directory._delObject(copy_id) signature.setStatus(self.PUB_CONFLICT_MERGE) - security.declareProtected(Permissions.ModifyPortalContent, + security.declareProtected(Permissions.ModifyPortalContent, 'managePublisherValue') - def managePublisherValue(self, subscription_url, property_id, object_path, + def managePublisherValue(self, subscription_url, property_id, object_path, RESPONSE=None): """ Do whatever needed in order to store the local value on @@ -766,20 +753,18 @@ class SynchronizationTool( SubscriptionSynchronization, Suggestion (API) add method to view document with applied xupdate - of a given subscriber XX + of a given subscriber XX (ex. viewSubscriberDocument?path=ddd&subscriber_id=dddd) Version=Version CPS """ # Retrieve the conflict object - #LOG('manageLocalValue',0,'%s %s %s' % (str(subscription_url), - # str(property_id), - # str(object_path))) + LOG('manageLocalValue', DEBUG, '%s %s %s' % (str(subscription_url), + str(property_id), + str(object_path))) for conflict in self.getConflictList(): - #LOG('manageLocalValue, conflict:',0,conflict) if conflict.getPropertyId() == property_id: - #LOG('manageLocalValue',0,'found the property_id') - if '/'.join(conflict.getObjectPath())==object_path: - if conflict.getSubscriber().getSubscriptionUrl()==subscription_url: + if '/'.join(conflict.getObjectPath()) == object_path: + if conflict.getSubscriber().getSubscriptionUrl() == subscription_url: conflict.applyPublisherValue() if RESPONSE is not None: RESPONSE.redirect('manageConflicts') @@ -792,31 +777,29 @@ class SynchronizationTool( SubscriptionSynchronization, Do whatever needed in order to store the remote value locally and confirmed that the remote box should keep it's value """ - #LOG('manageLocalValue',0,'%s %s %s' % (str(subscription_url), - # str(property_id), - # str(object_path))) + LOG('manageLocalValue', DEBUG, '%s %s %s' % (str(subscription_url), + str(property_id), + str(object_path))) for conflict in self.getConflictList(): - #LOG('manageLocalValue, conflict:',0,conflict) if conflict.getPropertyId() == property_id: - #LOG('manageLocalValue',0,'found the property_id') - if '/'.join(conflict.getObjectPath())==object_path: - if conflict.getSubscriber().getSubscriptionUrl()==subscription_url: + if '/'.join(conflict.getObjectPath()) == object_path: + if conflict.getSubscriber().getSubscriptionUrl() == subscription_url: conflict.applySubscriberValue() if RESPONSE is not None: RESPONSE.redirect('manageConflicts') - - security.declareProtected(Permissions.ModifyPortalContent, + + security.declareProtected(Permissions.ModifyPortalContent, 'manageSubscriberDocument') def manageSubscriberDocument(self, subscription_url, object_path): """ """ for conflict in self.getConflictList(): - if '/'.join(conflict.getObjectPath())==object_path: - if conflict.getSubscriber().getSubscriptionUrl()==subscription_url: + if '/'.join(conflict.getObjectPath()) == object_path: + if conflict.getSubscriber().getSubscriptionUrl() == subscription_url: conflict.applySubscriberDocument() break self.managePublisherDocument(object_path) - + security.declareProtected(Permissions.ModifyPortalContent, 'managePublisherDocument') def managePublisherDocument(self, object_path): @@ -826,7 +809,7 @@ class SynchronizationTool( SubscriptionSynchronization, while retry: retry = False for conflict in self.getConflictList(): - if '/'.join(conflict.getObjectPath())==object_path: + if '/'.join(conflict.getObjectPath()) == object_path: conflict.applyPublisherDocument() retry = True break @@ -855,17 +838,15 @@ class SynchronizationTool( SubscriptionSynchronization, We will look at the url and we will see if we need to send mail, http response, or just copy to a file. """ - #LOG('sendResponse, self.getPhysicalPath: ',0,self.getPhysicalPath()) - #LOG('sendResponse, to_url: ',0,to_url) - #LOG('sendResponse, from_url: ',0,from_url) - #LOG('sendResponse, sync_id: ',0,sync_id) - #LOG('sendResponse, xml: \n',0,xml) + LOG('sendResponse, self.getPhysicalPath: ', DEBUG, self.getPhysicalPath()) + LOG('sendResponse, to_url: ', DEBUG, to_url) + LOG('sendResponse, from_url: ', DEBUG, from_url) + LOG('sendResponse, sync_id: ', DEBUG, sync_id) + LOG('sendResponse, xml: \n', DEBUG, xml) if content_type == self.CONTENT_TYPE['SYNCML_WBXML']: xml = self.xml2wbxml(xml) - #LOG('sendHttpResponse, xml after wbxml: \n',0,self.hexdump(xml)) - - + #LOG('sendHttpResponse, xml after wbxml: \n', DEBUG, self.hexdump(xml)) if isinstance(xml, unicode): xml = xml.encode('utf-8') if domain is not None: @@ -879,7 +860,7 @@ class SynchronizationTool( SubscriptionSynchronization, (status,output)=commands.getstatusoutput('gpg --yes --homedir \ /var/lib/zope/Products/ERP5SyncML/gnupg_keys -r "%s" -se \ /tmp/%s.gz' % (gpg_key,filename)) - #LOG('readResponse, gpg output:',0,output) + #LOG('readResponse, gpg output:', DEBUG, output) encrypted = file('/tmp/%s.gz.gpg' % filename,'r') xml = encrypted.read() encrypted.close() @@ -889,24 +870,20 @@ class SynchronizationTool( SubscriptionSynchronization, if isinstance(to_url, str): if to_url.find('http://')==0: domain = aq_base(domain) - #LOG('domain.domain_type',0,domain.domain_type) - #LOG("getattr(domain, 'getActivityEnabled', None)",0,getattr(domain, 'getActivityEnabled', None)) - #LOG("domain.getActivityEnabled()",0,domain.getActivityEnabled()) if domain.domain_type == self.PUB and not domain.getActivityEnabled(): # not use activity # XXX Make sure this is not a problem return None #use activities to send send an http response - #LOG('sendResponse, will start sendHttpResponse, xml',0,'') + LOG('sendResponse, will start sendHttpResponse, xml', DEBUG, '') self.activate(activity='RAMQueue').sendHttpResponse(sync_id=sync_id, to_url=to_url, - xml=xml, + xml=xml, domain_path=domain.getPath(), content_type=content_type) elif to_url.find('file://')==0: filename = to_url[len('file:/'):] stream = file(filename,'w') - #LOG('sendResponse, filename: ',0,filename) stream.write(xml) stream.close() # we have to use local files (unit testing for example @@ -914,17 +891,14 @@ class SynchronizationTool( SubscriptionSynchronization, # we will send an email to_address = to_url[len('mailto:'):] from_address = from_url[len('mailto:'):] - self.sendMail(from_address,to_address,sync_id,xml) + self.sendMail(from_address, to_address, sync_id, xml) return xml security.declarePrivate('sendHttpResponse') - def sendHttpResponse(self, to_url=None, sync_id=None, xml=None, + def sendHttpResponse(self, to_url=None, sync_id=None, xml=None, domain_path=None, content_type='application/vnd.syncml+xml'): domain = self.unrestrictedTraverse(domain_path) - #LOG('sendHttpResponse, self.getPhysicalPath: ',0,self.getPhysicalPath()) - #LOG('sendHttpResponse, starting with domain:',0,domain) - - #LOG('sendHttpResponse, xml:',0,xml) + LOG('sendHttpResponse, starting with domain:', DEBUG, domain) if domain is not None: if domain.domain_type == self.PUB and not domain.getActivityEnabled(): return xml @@ -932,7 +906,7 @@ class SynchronizationTool( SubscriptionSynchronization, proxy_url = '' if os.environ.has_key('http_proxy'): proxy_url = os.environ['http_proxy'] - #LOG('sendHttpResponse, proxy_url:',0,proxy_url) + LOG('sendHttpResponse, proxy_url:', DEBUG, proxy_url) if proxy_url !='': proxy_handler = urllib2.ProxyHandler({"http" :proxy_url}) else: @@ -965,7 +939,7 @@ class SynchronizationTool( SubscriptionSynchronization, # - http://svn.zope.org/soap/trunk/ if domain.getSynchronizeWithERP5Sites(): - LOG('Synchronization with another ERP5 instance ...',0,'') + LOG('Synchronization with another ERP5 instance ...', DEBUG, '') if to_url.find('readResponse')<0: to_url = to_url + '/portal_synchronizations/readResponse' encoded = urllib.urlencode(to_encode) @@ -980,33 +954,23 @@ class SynchronizationTool( SubscriptionSynchronization, url_file = urllib2.urlopen(request) result = url_file.read() except socket.error, msg: - self.activate(activity='RAMQueue').sendHttpResponse(to_url=to_url, - sync_id=sync_id, xml=xml, domain_path=domain.getPath(), + self.activate(activity='RAMQueue').sendHttpResponse(to_url=to_url, + sync_id=sync_id, xml=xml, domain_path=domain.getPath(), content_type=content_type) - LOG('sendHttpResponse, socket ERROR:',0,msg) - #LOG('sendHttpResponse, url,data',0,(url, data)) + LOG('sendHttpResponse, socket ERROR:', INFO, msg) + LOG('sendHttpResponse, url, data', INFO, (url, data)) return except urllib2.URLError, msg: - LOG("sendHttpResponse, can't open url %s :" % to_url, 0, msg) - LOG('sendHttpResponse, to_url,data',0,(to_url, data)) + LOG("sendHttpResponse, can't open url %s :" % to_url, INFO, msg) + LOG('sendHttpResponse, to_url, data', INFO, (to_url, data)) return - - #LOG('sendHttpResponse, before result, domain:',0,domain) if domain is not None: if domain.domain_type == self.SUB and not domain.getActivityEnabled(): #if we don't use activity : gpg_key = domain.getGPGKey() - if result not in (None,''): - #if gpg_key not in ('',None): - # result = self.sendResponse(domain=domain,xml=result,send=0) - #uf = self.acl_users - #user = UnrestrictedUser('syncml','syncml',['Manager','Member'],'') - #user = uf.getUserById('syncml').__of__(uf) - #newSecurityManager(None, user) - #self.activate(activity='RAMQueue').readResponse(sync_id=sync_id,text=result) - - self.readResponse(sync_id=sync_id,text=result) + if result not in (None, ''): + self.readResponse(sync_id=sync_id, text=result) return result security.declarePublic('sync') @@ -1016,68 +980,68 @@ class SynchronizationTool( SubscriptionSynchronization, """ # Login as a manager to make sure we can create objects uf = self.acl_users - user = UnrestrictedUser('syncml','syncml',['Manager','Member'],'') + user = UnrestrictedUser('syncml', 'syncml', ['Manager', 'Member'], '') newSecurityManager(None, user) message_list = self.portal_activities.getMessageList() - #LOG('sync, message_list:',0,message_list) + LOG('sync, message_list:', DEBUG, message_list) if len(message_list) == 0: for subscription in self.getSubscriptionList(): - #LOG('sync, type(subcription):',0,type(subscription)) + LOG('sync, type(subcription):', DEBUG, type(subscription)) self.activate(activity='RAMQueue').SubSync(subscription.getPath()) security.declarePublic('readResponse') - def readResponse(self, text=None, sync_id=None, to_url=None, from_url=None): + def readResponse(self, text='', sync_id=None, to_url=None, from_url=None): """ We will look at the url and we will see if we need to send mail, http response, or just copy to a file. """ - #LOG('readResponse, text :', 0, text) - #LOG('readResponse, text :', 0, self.hexdump(text)) + LOG('readResponse, text :', DEBUG, text) + #LOG('readResponse, hexdump(text) :', DEBUG, self.hexdump(text)) # Login as a manager to make sure we can create objects uf = self.acl_users user = uf.getUserById('syncml').__of__(uf) - user = UnrestrictedUser('syncml','syncml',['Manager','Member'],'') + user = UnrestrictedUser('syncml', 'syncml', ['Manager', 'Member'], '') newSecurityManager(None, user) status_code = None - if text is not None: + if text not in ('', None): # XXX We will look everywhere for a publication/subsription with # the id sync_id, this is not so good, but there is no way yet # to know if we will call a publication or subscription XXX gpg_key = '' for publication in self.getPublicationList(): - if publication.getTitle()==sync_id: + if publication.getTitle() == sync_id: gpg_key = publication.getGPGKey() domain = publication if gpg_key == '': for subscription in self.getSubscriptionList(): - if subscription.getTitle()==sync_id: + if subscription.getTitle() == sync_id: gpg_key = subscription.getGPGKey() domain = subscription # decrypt the message if needed if gpg_key not in (None,''): - filename = str(random.randrange(1,2147483600)) + '.txt' + filename = str(random.randrange(1, 2147483600)) + '.txt' encrypted = file('/tmp/%s.gz.gpg' % filename,'w') encrypted.write(text) encrypted.close() (status,output)=commands.getstatusoutput('gpg --homedir \ /var/lib/zope/Products/ERP5SyncML/gnupg_keys -r "%s" --decrypt \ /tmp/%s.gz.gpg > /tmp/%s.gz' % (gpg_key, filename, filename)) - #LOG('readResponse, gpg output:', 0, output) + LOG('readResponse, gpg output:', TRACE, output) (status,output)=commands.getstatusoutput('gunzip /tmp/%s.gz' % filename) decrypted = file('/tmp/%s' % filename,'r') text = decrypted.read() - #LOG('readResponse, text:', 0, text) + LOG('readResponse, text:', TRACE, text) decrypted.close() commands.getstatusoutput('rm -f /tmp/%s' % filename) commands.getstatusoutput('rm -f /tmp/%s.gz.gpg' % filename) # Get the target and then find the corresponding publication or # Subscription - #LOG('type(text) : ',0,type(text)) + LOG('type(text) : ', TRACE, type(text)) if domain.getSyncContentType() == self.CONTENT_TYPE['SYNCML_WBXML']: text = self.wbxml2xml(text) - #LOG('readResponse, text after wbxml :\n', 0, text) + LOG('readResponse, text after wbxml :\n', TRACE, text) xml = Parse(text) url = self.getTarget(xml) for publication in self.getPublicationList(): @@ -1089,37 +1053,33 @@ class SynchronizationTool( SubscriptionSynchronization, text) return ' ' else: - result = self.PubSync(publication.getPath(),xml) + result = self.PubSync(publication.getPath(), xml) # Then encrypt the message xml = result['xml'] - #must be commented because this method is alredy called - #xml = self.sendResponse(xml=xml,domain=publication,send=0) - if publication.getSyncContentType() == self.CONTENT_TYPE['SYNCML_WBXML']: + if publication.getSyncContentType() ==\ + self.CONTENT_TYPE['SYNCML_WBXML']: xml = self.xml2wbxml(xml) return xml - for subscription in self.getSubscriptionList(): - if subscription.getSubscriptionUrl()==url and \ - subscription.getTitle()==sync_id: + if subscription.getSubscriptionUrl() == url and \ + subscription.getTitle() == sync_id: subscription_path = self.getSubscription(sync_id).getPath() - self.activate(activity='RAMQueue').SubSync(subscription_path, + self.activate(activity='RAMQueue').SubSync(subscription_path, text) return ' ' - #result = self.SubSync(self.getSubscription(sync_id),xml) # we use from only if we have a file elif isinstance(from_url, str): - if from_url.find('file://')==0: + if from_url.find('file://') == 0: try: filename = from_url[len('file:/'):] - stream = file(filename,'r') + stream = file(filename, 'r') xml = stream.read() - #stream.seek(0) - #LOG('readResponse',0,'Starting... msg: %s' % str(stream.read())) + LOG('readResponse', DEBUG, 'file... msg: %s' % str(stream.read())) except IOError: - LOG('readResponse, cannot read file: ',0,filename) + LOG('readResponse, cannot read file: ', DEBUG, filename) xml = None - if xml is not None and len(xml)==0: + if xml is not None and len(xml) == 0: xml = None return xml @@ -1140,14 +1100,11 @@ class SynchronizationTool( SubscriptionSynchronization, return 'sub_' + title security.declareProtected(Permissions.ModifyPortalContent, 'addNode') - def addNode(self, conduit='ERP5Conduit',**kw): + def addNode(self, conduit='ERP5Conduit', **kw): """ """ # Import the conduit and get it - from Products.ERP5SyncML import Conduit - conduit_module = __import__('.'.join([Conduit.__name__, conduit]), - globals(), locals(), ['']) - conduit_object = getattr(conduit_module, conduit)() + conduit_object = self.getConduitByName(conduit) return conduit_object.addNode(**kw) def hexdump(self, raw=''): @@ -1162,29 +1119,29 @@ class SynchronizationTool( SubscriptionSynchronization, start = 0 done = False while not done: - end = start + 16 - max = len(str(raw)) - if end > max: - end = max - done = True - chunk = raw[start:end] - for i in xrange(len(chunk)): - if i > 0: - spacing = " " - else: - spacing = "" - buf += "%s%02x" % (spacing, ord(chunk[i])) - if done: - for i in xrange(16 - (end % 16)): - buf += " " - buf += " " - for c in chunk: - val = ord(c) - if val >= 33 and val <= 126: - buf += c - else: - buf += "." - buf += "\n" - start += 16 - return buf + end = start + 16 + max = len(str(raw)) + if end > max: + end = max + done = True + chunk = raw[start:end] + for i in xrange(len(chunk)): + if i > 0: + spacing = " " + else: + spacing = "" + buf += "%s%02x" % (spacing, ord(chunk[i])) + if done: + for i in xrange(16 - (end % 16)): + buf += " " + buf += " " + for c in chunk: + val = ord(c) + if val >= 33 and val <= 126: + buf += c + else: + buf += "." + buf += "\n" + start += 16 + return buf InitializeClass( SynchronizationTool ) diff --git a/product/ERP5SyncML/XMLSyncUtils.py b/product/ERP5SyncML/XMLSyncUtils.py index 3fe6c838861d8ad72c781e8e1459e87064c09606..14f236d03347959d7134b09c0faf852329268c0e 100644 --- a/product/ERP5SyncML/XMLSyncUtils.py +++ b/product/ERP5SyncML/XMLSyncUtils.py @@ -33,11 +33,11 @@ from StringIO import StringIO from xml.dom.ext import PrettyPrint from ERP5Diff import ERP5Diff import random -from zLOG import LOG +from zLOG import LOG, INFO, DEBUG, TRACE try: from Products.CMFActivity.ActiveObject import ActiveObject except ImportError: - LOG('XMLSyncUtils',0,"Can't import ActiveObject") + LOG('XMLSyncUtils', INFO, "Can't import ActiveObject") class ActiveObject: pass import commands @@ -45,7 +45,7 @@ import commands try: from Ft.Xml import Parse except ImportError: - LOG('XMLSyncUtils',0,"Can't import Parse") + LOG('XMLSyncUtils', INFO, "Can't import Parse") class Parse: def __init__(self, *args, **kw): raise ImportError, "Sorry, it was not possible to import Ft library" @@ -131,7 +131,6 @@ class XMLSyncUtilsMixin(SyncCode): #list of element in the SyncBody bloc syncbody_element_list = remote_xml.xpath('//SyncBody/*') - message_id = self.getMessageId(remote_xml) xml_list = [] xml = xml_list.append @@ -155,8 +154,7 @@ class XMLSyncUtilsMixin(SyncCode): xml(' </Status>\n') #add the status bloc corresponding to the receive command for syncbody_element in syncbody_element_list: - - #LOG('SyncMLStatus : ',0,"command:%s, subscription:%s" % (str(syncbody_element.nodeName), subscription)) + LOG('SyncMLStatus : ', DEBUG, "command:%s, subscription:%s" % (str(syncbody_element.nodeName), subscription)) if str(syncbody_element.nodeName) not in ('Status', 'Final', 'Get'): xml(' <Status>\n') xml(' <CmdID>%s</CmdID>\n' % cmd_id) @@ -172,8 +170,6 @@ class XMLSyncUtilsMixin(SyncCode): source_ref = syncbody_element.xpath('string(.//Source/LocURI)').encode('utf-8') if source_ref not in (None, ''): xml(' <SourceRef>%s</SourceRef>\n' % source_ref ) - - #xml(' <Data>%s</Data>\n' % subscriber.getSynchronizationType()) if syncbody_element.nodeName.encode('utf-8') == 'Add': xml(' <Data>%s</Data>\n' % str(self.ITEM_ADDED)) elif syncbody_element.nodeName.encode('utf-8') == 'Alert' and \ @@ -183,8 +179,6 @@ class XMLSyncUtilsMixin(SyncCode): else: xml(' <Data>%s</Data>\n' % str(self.SUCCESS)) - # if syncbody_element.xpath('.//Item') not in ([], None, '') and\ - # syncbody_element.xpath('.//Item.....'): #contient une ancre Next... if str(syncbody_element.nodeName) == 'Alert': xml(' <Item>\n') xml(' <Data>\n') @@ -197,15 +191,19 @@ class XMLSyncUtilsMixin(SyncCode): if str(syncbody_element.nodeName) == 'Get' and subscription != None: cmd_ref = syncbody_element.xpath('string(.//CmdID)').encode('utf-8') - syncml_result = self.SyncMLPut(cmd_id, subscription, markup='Results', - cmd_ref=cmd_ref, message_id=self.getMessageId(remote_xml)) + syncml_result = self.SyncMLPut( + cmd_id, + subscription, + markup='Results', + cmd_ref=cmd_ref, + message_id=self.getMessageId(remote_xml)) xml(syncml_result) cmd_id += 1 xml_a = ''.join(xml_list) return {'xml':xml_a, 'cmd_id':cmd_id} - def SyncMLConfirmation(self, cmd_id=None, target_ref=None, cmd=None, - sync_code=None, msg_ref=None, cmd_ref=None, source_ref=None, + def SyncMLConfirmation(self, cmd_id=None, target_ref=None, cmd=None, + sync_code=None, msg_ref=None, cmd_ref=None, source_ref=None, remote_xml=None): """ This is used in order to confirm that an object was correctly @@ -238,8 +236,8 @@ class XMLSyncUtilsMixin(SyncCode): xml(' </Status>\n') xml_a = ''.join(xml_list) return xml_a - - def SyncMLChal(self, cmd_id, cmd, target_ref, source_ref, auth_format, + + def SyncMLChal(self, cmd_id, cmd, target_ref, source_ref, auth_format, auth_type, data_code): """ This is used in order to ask crendentials @@ -264,25 +262,15 @@ class XMLSyncUtilsMixin(SyncCode): xml_a = ''.join(xml_list) return xml_a - def SyncMLPut(self, cmd_id, subscription, markup='Put', cmd_ref=None, + def SyncMLPut(self, cmd_id, subscription, markup='Put', cmd_ref=None, message_id=None): """ this is used to inform the server of the CTType version supported but if the server use it to respond to a Get request, it's a <Result> markup instead of <Put> """ - from Products.ERP5SyncML import Conduit - # Import the conduit and get it conduit_name = subscription.getConduit() - if conduit_name.startswith('Products'): - path = conduit_name - conduit_name = conduit_name.split('.')[-1] - conduit_module = __import__(path, globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() - else: - conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]), - globals(), locals(), ['']) - conduit = getattr(conduit_module, conduit_name)() + conduit = self.getConduitByName(conduit_name) #if the conduit support the SyncMLPut : if hasattr(conduit, 'getCapabilitiesCTTypeList') and \ hasattr(conduit, 'getCapabilitiesVerCTList') and \ @@ -368,7 +356,7 @@ class XMLSyncUtilsMixin(SyncCode): header = "Subject: %s\n" % id_sync header += "To: %s\n\n" % toaddr msg = header + msg - #LOG('SubSendMail',0,'from: %s, to: %s' % (fromaddr,toaddr)) + LOG('SubSendMail', DEBUG,'from: %s, to: %s' % (fromaddr,toaddr)) server = smtplib.SMTP('localhost') server.sendmail(fromaddr, toaddr, msg) # if we want to send the email to someone else (debugging) @@ -376,7 +364,7 @@ class XMLSyncUtilsMixin(SyncCode): server.quit() def addXMLObject(self, cmd_id=0, object=None, xml_string=None, - more_data=0,gid=None, media_type=None): + more_data=0, gid=None, media_type=None): """ Add an object with the SyncML protocol """ @@ -423,8 +411,6 @@ class XMLSyncUtilsMixin(SyncCode): xml(' <Source>\n') xml(' <LocURI>%s</LocURI>\n' % object_gid) xml(' </Source>\n') - #xml(' <Data>\n') #this 2 lines seems to be useless - #xml(' </Data>\n') xml(' </Item>\n') xml(' </Delete>\n') xml_a = ''.join(xml_list) @@ -472,7 +458,7 @@ class XMLSyncUtilsMixin(SyncCode): attr_ns = xupdate_doc.createAttribute('xmlns:xupdate') attr_ns.value = 'http://www.xmldb.org/xupdate' attr_version = xupdate_doc.createAttribute('version') - attr_version.value='1.0' + attr_version.value = '1.0' xupdate_doc.documentElement.setAttributeNode(attr_ns) xupdate_doc.documentElement.setAttributeNode(attr_version) xupdate = xupdate_doc.toxml() @@ -488,7 +474,7 @@ class XMLSyncUtilsMixin(SyncCode): session_id = xml.xpath('string(/SyncML/SyncHdr/SessionID)') session_id = int(session_id) return session_id - + def getMessageId(self, xml): """ We will retrieve the message id of the message @@ -533,7 +519,7 @@ class XMLSyncUtilsMixin(SyncCode): if isinstance(source_uri, unicode): source_uri = source_uri.encode('utf-8') return source_uri - + def getTargetURI(self, xml): """ return the target uri of the data base @@ -551,7 +537,7 @@ class XMLSyncUtilsMixin(SyncCode): if isinstance(subscription_url, unicode): subscription_url = subscription_url.encode('utf-8') return subscription_url - + def getStatusTarget(self, xml): """ Return the value of the alert code inside the xml_stream @@ -574,13 +560,12 @@ class XMLSyncUtilsMixin(SyncCode): """ Return the value of the command inside the xml_stream """ + cmd = None if xml.nodeName=='Status': cmd = xml.xpath('string(//Status/Cmd)') if isinstance(cmd, unicode): cmd = cmd.encode('utf-8') - return cmd - else: - return None + return cmd def getCred(self, xml): """ @@ -604,14 +589,12 @@ class XMLSyncUtilsMixin(SyncCode): """ Check if there's a Cred section in the xml_stream """ - if xml_stream.xpath('string(SyncML/SyncHdr/Cred)') not in ('', None, []): - return True - return False + return xml_stream.xpath('string(SyncML/SyncHdr/Cred)') not in ('', None, []) def getChal(self, xml): """ return the chalenge information : format and type - """ + """ format=None type=None @@ -627,19 +610,13 @@ class XMLSyncUtilsMixin(SyncCode): """ Check if there's a Chal section in the xml_stream """ - if xml_stream.xpath('string(SyncML/SyncBody/Status/Chal)') \ - not in ('', None, []): - return True - return False + return xml_stream.xpath('string(SyncML/SyncBody/Status/Chal)') not in ('', None, []) def checkMap(self, xml_stream): """ Check if there's a Map section in the xml_stream """ - if xml_stream.xpath('string(SyncML/SyncBody/Map)') \ - not in ('', None, []): - return True - return False + return xml_stream.xpath('string(SyncML/SyncBody/Map)') not in ('', None, []) def setRidWithMap(self, xml_stream, subscriber): """ @@ -651,7 +628,7 @@ class XMLSyncUtilsMixin(SyncCode): gid = map_item.xpath('string(.//Target/LocURI)').encode('utf-8') signature = subscriber.getSignatureFromGid(gid) rid = map_item.xpath('string(.//Source/LocURI)').encode('utf-8') - signature.setRid(rid) + signature.setRid(rid) def getAlertCode(self, xml_stream): """ @@ -667,28 +644,19 @@ class XMLSyncUtilsMixin(SyncCode): """ Check if there's an Alert section in the xml_stream """ - alert = False - if xml_stream.xpath('string(SyncML/SyncBody/Alert)') not in ('', None, []): - alert = True - return alert + return xml_stream.xpath('string(SyncML/SyncBody/Alert)') not in ('', None, []) def checkSync(self, xml_stream): """ Check if there's an Sync section in the xml_xtream """ - sync = False - if xml_stream.xpath('string(SyncML/SyncBody/Sync)') not in ('', None, []): - sync = True - return sync + return xml_stream.xpath('string(SyncML/SyncBody/Sync)') not in ('', None, []) def checkStatus(self, xml_stream): """ Check if there's a Status section in the xml_xtream """ - status = False - if xml_stream.xpath('string(SyncML/SyncBody/Status)') not in ('', None, []): - status = True - return status + return xml_stream.xpath('string(SyncML/SyncBody/Status)') not in ('', None, []) def getSyncActionList(self, xml_stream): """ @@ -755,9 +723,7 @@ class XMLSyncUtilsMixin(SyncCode): """ Return the rid of the object described by the action """ - if action.xpath('Item/MoreData') not in ([],None) : - return True - return False + return action.xpath('Item/MoreData') not in ([],None) def getActionType(self, action): """ @@ -783,7 +749,7 @@ class XMLSyncUtilsMixin(SyncCode): if subnode.nodeType == subnode.TEXT_NODE: subnode_list += [subnode] return subnode_list - + def getAttributeNodeList(self, node): """ Return childNodes that are ElementNode @@ -800,7 +766,7 @@ class XMLSyncUtilsMixin(SyncCode): if object is not None, this usually means we want to set the actual xupdate on the signature. """ - LOG('getSyncMLData starting...',0,'') + LOG('getSyncMLData starting...', DEBUG, domain.getId()) if isinstance(conduit, str): conduit = self.getConduitByName(conduit) local_gid_list = [] @@ -815,21 +781,22 @@ class XMLSyncUtilsMixin(SyncCode): local_gid_list = map(lambda x: domain.getGidFromObject(x),object_list) # Objects to remove - #LOG('remove object to remove ...',0,'') + LOG('remove object to remove ...', DEBUG, '') for object_gid in subscriber.getGidList(): if object_gid not in local_gid_list: # This is an object to remove signature = subscriber.getSignatureFromGid(object_gid) - if signature.getStatus()!=self.PARTIAL: # If partial, then we have a signature - # but no local object + if signature.getStatus() != self.PARTIAL: + # If partial, then we have a signature but no local object xml_object = signature.getXML() if xml_object is not None: # This prevent to delete an object that - # we were not able to create + # we were not able to create rid = signature.getRid() - #if rid != None: - # object_gid=rid #to use the remote id if it exist - syncml_data += self.deleteXMLObject(xml_object=signature.getXML()\ - or '', object_gid=object_gid, rid=rid,cmd_id=cmd_id) + syncml_data += self.deleteXMLObject( + xml_object=signature.getXML() or '', + object_gid=object_gid, + rid=rid, + cmd_id=cmd_id) cmd_id += 1 #delete Signature if object does not exist anymore for known_gid in subscriber.getGidList(): @@ -851,18 +818,18 @@ class XMLSyncUtilsMixin(SyncCode): if syncml_data.count('\n') < self.MAX_LINES and not \ object.id.startswith('.'): # If not we have to cut - #LOG('getSyncMLData',0,'object_path: %s' % '/'.join(object_path)) - #LOG('getSyncMLData',0,'xml_mapping: %s' % str(domain.getXMLMapping())) - #LOG('getSyncMLData',0,'code: %s' % str(self.getAlertCode(remote_xml))) - #LOG('getSyncMLData',0,'gid_list: %s' % str(local_gid_list)) - #LOG('getSyncMLData',0,'subscriber.getGidList: %s' % subscriber.getGidList()) - #LOG('getSyncMLData',0,'hasSignature: %s' % str(subscriber.hasSignature(object_gid))) - #LOG('getSyncMLData',0,'alert_code == slowsync: %s' % str(self.getAlertCode(remote_xml)==self.SLOW_SYNC)) + LOG('getSyncMLData', DEBUG, 'object_path: %s' % '/'.join(object_path)) + LOG('getSyncMLData', DEBUG, 'xml_mapping: %s' % str(domain.getXMLMapping())) + LOG('getSyncMLData', DEBUG, 'code: %s' % str(self.getAlertCode(remote_xml))) + LOG('getSyncMLData', DEBUG, 'gid_list: %s' % str(local_gid_list)) + LOG('getSyncMLData', DEBUG, 'subscriber.getGidList: %s' % subscriber.getGidList()) + LOG('getSyncMLData', DEBUG, 'hasSignature: %s' % str(subscriber.hasSignature(object_gid))) + LOG('getSyncMLData', DEBUG, 'alert_code == slowsync: %s' % str(self.getAlertCode(remote_xml) == self.SLOW_SYNC)) signature = subscriber.getSignatureFromGid(object_gid) ## Here we first check if the object was modified or not by looking at dates #if signature is not None: - #LOG('getSyncMLData',0,'signature.getStatus: %s' % signature.getStatus()) + #LOG('getSyncMLData', DEBUG, 'signature.getStatus: %s' % signature.getStatus()) status = self.SENT more_data=0 # For the case it was never synchronized, we have to send everything @@ -871,13 +838,13 @@ class XMLSyncUtilsMixin(SyncCode): elif signature is None or (signature.getXML() is None and \ signature.getStatus() != self.PARTIAL) or \ self.getAlertCode(remote_xml) == self.SLOW_SYNC: - #LOG('getSyncMLData',0,'Current object.getPath: %s' % object.getPath()) + LOG('getSyncMLData', DEBUG, 'Current object.getPath: %s' % object.getPath()) xml_object = domain.getXMLFromObject(object) xml_string = xml_object if isinstance(xml_string, unicode): xml_string = xml_object.encode('utf-8') gid = subscriber.getGidFromObject(object) - signature = Signature(id=gid,object=object) + signature = Signature(id=gid, object=object) signature.setTempXML(xml_object) if xml_string.count('\n') > self.MAX_LINES: if xml_string.find('--') >= 0: # This make comment fails, so we need to replace @@ -890,7 +857,7 @@ class XMLSyncUtilsMixin(SyncCode): short_string += rest_string[:rest_string.find('\n')+1] rest_string = xml_string[len(short_string):] i += 1 - #LOG('getSyncMLData',0,'setPartialXML with: %s' % str(rest_string)) + LOG('getSyncMLData', DEBUG, 'setPartialXML with: %s' % str(rest_string)) signature.setPartialXML(rest_string) status = self.PARTIAL signature.setAction('Add') @@ -898,21 +865,28 @@ class XMLSyncUtilsMixin(SyncCode): gid = signature.getRid()#in fisrt, we try with rid if there is one if gid == None: gid = signature.getGid() - syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object, - gid=gid, xml_string=xml_string, - more_data=more_data, media_type=subscriber.getMediaType()) + syncml_data += self.addXMLObject( + cmd_id=cmd_id, + object=object, + gid=gid, + xml_string=xml_string, + more_data=more_data, + media_type=subscriber.getMediaType()) cmd_id += 1 signature.setStatus(status) subscriber.addSignature(signature) - elif signature.getStatus()==self.NOT_SYNCHRONIZED \ - or signature.getStatus()==self.PUB_CONFLICT_MERGE: # We don't have synchronized this object yet + elif signature.getStatus() == self.NOT_SYNCHRONIZED \ + or signature.getStatus() == self.PUB_CONFLICT_MERGE: + # We don't have synchronized this object yet xml_object = domain.getXMLFromObject(object) - #LOG('getSyncMLData',0,'checkMD5: %s' % str(signature.checkMD5(xml_object))) - #LOG('getSyncMLData',0,'getStatus: %s' % str(signature.getStatus())) - if signature.getStatus()==self.PUB_CONFLICT_MERGE: - xml_confirmation += self.SyncMLConfirmation(cmd_id=cmd_id, - source_ref=signature.getGid(), sync_code=self.CONFLICT_MERGE, - cmd='Replace') + LOG('getSyncMLData', DEBUG, 'checkMD5: %s' % str(signature.checkMD5(xml_object))) + LOG('getSyncMLData', DEBUG, 'getStatus: %s' % str(signature.getStatus())) + if signature.getStatus() == self.PUB_CONFLICT_MERGE: + xml_confirmation += self.SyncMLConfirmation( + cmd_id=cmd_id, + source_ref=signature.getGid(), + sync_code=self.CONFLICT_MERGE, + cmd='Replace') set_synchronized = 1 if not signature.checkMD5(xml_object): set_synchronized = 0 @@ -926,69 +900,80 @@ class XMLSyncUtilsMixin(SyncCode): if xml_string.count('\n') > self.MAX_LINES: # This make comment fails, so we need to replace if xml_string.find('--') >= 0: - xml_string = xml_string.replace('--','@-@@-@') + xml_string = xml_string.replace('--', '@-@@-@') i = 0 - more_data=1 - short_string = '' + more_data = 1 + short_string_list = [] + short_string_list_ap = short_string_list.append rest_string = xml_string while i < self.MAX_LINES: - short_string += rest_string[:rest_string.find('\n')+1] - rest_string = xml_string[len(short_string):] + short_string_list_ap(rest_string[:rest_string.find('\n')+1]) + rest_string = xml_string[len(''.join(short_string_list)):] i += 1 signature.setPartialXML(rest_string) status = self.PARTIAL signature.setAction('Replace') - xml_string = '<!--' + short_string + '-->' + xml_string = '<!--' + ''.join(short_string_list) + '-->' signature.setStatus(status) if subscriber.getMediaType() != self.MEDIA_TYPE['TEXT_XML']: xml_string = domain.getXMLFromObject(object) rid = signature.getRid()#in fisrt, we try with rid if there is one gid = signature.getGid() - syncml_data += self.replaceXMLObject(cmd_id=cmd_id, object=object, - gid=gid, rid=rid, - xml_string=xml_string, - more_data=more_data, - media_type=subscriber.getMediaType()) + syncml_data += self.replaceXMLObject( + cmd_id=cmd_id, object=object, + gid=gid, rid=rid, + xml_string=xml_string, + more_data=more_data, + media_type=subscriber.getMediaType()) cmd_id += 1 signature.setTempXML(xml_object) # Now we can apply the xupdate from the subscriber subscriber_xupdate = signature.getSubscriberXupdate() - #LOG('getSyncMLData subscriber_xupdate',0,subscriber_xupdate) + LOG('getSyncMLData subscriber_xupdate', DEBUG, subscriber_xupdate) if subscriber_xupdate is not None: old_xml = signature.getXML() - conduit.updateNode(xml=subscriber_xupdate, object=object, - previous_xml=old_xml, force=(domain.getDomainType() == self.SUB), - simulate=0) + conduit.updateNode( + xml=subscriber_xupdate, + object=object, + previous_xml=old_xml, + force=(domain.getDomainType() == self.SUB), + simulate=0) xml_object = domain.getXMLFromObject(object) signature.setTempXML(xml_object) if set_synchronized: # We have to do that after this previous update # We should not have this case when we are in CONFLICT_MERGE signature.setStatus(self.SYNCHRONIZED) - elif signature.getStatus()==self.PUB_CONFLICT_CLIENT_WIN: + elif signature.getStatus() == self.PUB_CONFLICT_CLIENT_WIN: # We have decided to apply the update # XXX previous_xml will be geXML instead of getTempXML because # some modification was already made and the update # may not apply correctly xml_update = signature.getPartialXML() - conduit.updateNode(xml=signature.getPartialXML(), object=object, - previous_xml=signature.getXML(),force=1) - xml_confirmation += self.SyncMLConfirmation(cmd_id=cmd_id, - target_ref=object_gid, sync_code=self.CONFLICT_CLIENT_WIN, - cmd='Replace') + conduit.updateNode( + xml=signature.getPartialXML(), + object=object, + previous_xml=signature.getXML(), + force=1) + xml_confirmation += self.SyncMLConfirmation( + cmd_id=cmd_id, + target_ref=object_gid, + sync_code=self.CONFLICT_CLIENT_WIN, + cmd='Replace') signature.setStatus(self.SYNCHRONIZED) - elif signature.getStatus()==self.PARTIAL: + elif signature.getStatus() == self.PARTIAL: xml_string = signature.getPartialXML() if xml_string.count('\n') > self.MAX_LINES: i = 0 more_data=1 - short_string = '' + short_string_list = [] + short_string_list_ap = short_string_list.append rest_string = xml_string while i < self.MAX_LINES: - short_string += rest_string[:rest_string.find('\n')+1] - rest_string = xml_string[len(short_string):] + short_string_list_ap(rest_string[:rest_string.find('\n')+1]) + rest_string = xml_string[len(''.join(short_string_list)):] i += 1 signature.setPartialXML(rest_string) - xml_string = short_string + xml_string = ''.join(short_string_list) status = self.PARTIAL if xml_string.find('--') >= 0: # This make comment fails, so we need to replace xml_string = xml_string.replace('--','@-@@-@') @@ -996,20 +981,28 @@ class XMLSyncUtilsMixin(SyncCode): signature.setStatus(status) if(subscriber.getMediaType() != self.MEDIA_TYPE['TEXT_XML']): xml_string = domain.getXMLFromObject(object) - #LOG('xml_string =', 0, xml_string) - if signature.getAction()=='Replace': + if signature.getAction() == 'Replace': rid = signature.getRid()#in fisrt, we try with rid if there is one gid = signature.getGid() - syncml_data += self.replaceXMLObject(cmd_id=cmd_id, object=object, - gid=gid, rid=rid, xml_string=xml_string, more_data=more_data, - media_type=subscriber.getMediaType()) - elif signature.getAction()=='Add': + syncml_data += self.replaceXMLObject( + cmd_id=cmd_id, + object=object, + gid=gid, + rid=rid, + xml_string=xml_string, + more_data=more_data, + media_type=subscriber.getMediaType()) + elif signature.getAction() == 'Add': gid = signature.getRid()#in fisrt, we try with rid if there is one if gid == None: gid = signature.getGid() - syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object, - gid=gid, xml_string=xml_string, - more_data=more_data, media_type=subscriber.getMediaType()) + syncml_data += self.addXMLObject( + cmd_id=cmd_id, + object=object, + gid=gid, + xml_string=xml_string, + more_data=more_data, + media_type=subscriber.getMediaType()) if not more_data: subscriber.removeRemainingObjectPath(object_path) else: @@ -1022,7 +1015,7 @@ class XMLSyncUtilsMixin(SyncCode): return result def applyActionList(self, domain=None, subscriber=None, cmd_id=0, - remote_xml=None,conduit=None,simulate=0): + remote_xml=None, conduit=None, simulate=0): """ This just look to a list of action to do, then id applies each action one by one, thanks to a conduit @@ -1030,8 +1023,8 @@ class XMLSyncUtilsMixin(SyncCode): xml_confirmation = '' has_next_action = 0 destination = self.unrestrictedTraverse(domain.getDestinationPath()) - #LOG('applyActionList args',0,'domain : %s\n subscriber : %s\n cmd_id : %s' % (domain, subscriber, cmd_id)) - LOG('applyActionList', 0, self.getSyncActionList(remote_xml)) + LOG('applyActionList args', DEBUG, 'domain : %s\n subscriber : %s\n cmd_id : %s' % (domain.getPath(), subscriber.getPath(), cmd_id)) + LOG('applyActionList', DEBUG, self.getSyncActionList(remote_xml)) for action in self.getSyncActionList(remote_xml): if isinstance(action, unicode): action = action.encode('utf-8') @@ -1047,19 +1040,19 @@ class XMLSyncUtilsMixin(SyncCode): gid=rid else: gid=rid - object_id = domain.generateNewIdWithGenerator(object=destination,gid=gid) + object_id = domain.generateNewIdWithGenerator(object=destination, gid=gid) signature = subscriber.getSignatureFromGid(gid) if signature is not None and rid != gid: #in this case, the object was created on another subscriber than erp5 # and we should save it's remote id signature.setRid(rid) - #LOG('gid == rid ?', 0, 'gid=%s, rid=%s' % (gid, rid)) + LOG('gid == rid ?', DEBUG, 'gid=%s, rid=%s' % (gid, rid)) object = subscriber.getObjectFromGid(gid) if object == None: object = subscriber.getObjectFromRid(rid) - #LOG('applyActionList subscriber.getObjectFromGid %s' % gid,0,object) + LOG('applyActionList subscriber.getObjectFromGid %s' % gid, DEBUG, object) if signature is None: - #LOG('applyActionList, signature is None',0,signature) + LOG('applyActionList, signature is None', DEBUG, signature) if gid == rid: signature = Signature(id=gid, status=self.NOT_SYNCHRONIZED, object=object).__of__(subscriber) @@ -1069,7 +1062,6 @@ class XMLSyncUtilsMixin(SyncCode): signature.setObjectId(object_id) subscriber.addSignature(signature) force = signature.getForce() - #LOG('applyActionList',0,'object: %s' % repr(object)) if self.checkActionMoreData(action) == 0: data_subnode = None if partial_data != None: @@ -1078,7 +1070,7 @@ class XMLSyncUtilsMixin(SyncCode): data_subnode = signature.getPartialXML() + partial_data else: data_subnode = partial_data - #LOG('SyncModif',0,'data_subnode: %s' % data_subnode) + LOG('applyActionList', DEBUG, 'data_subnode: %s' % data_subnode) if subscriber.getMediaType() == self.MEDIA_TYPE['TEXT_XML']: data_subnode = Parse(data_subnode) data_subnode = data_subnode.childNodes[0] # Because we just created a new xml @@ -1098,7 +1090,6 @@ class XMLSyncUtilsMixin(SyncCode): conflict_list += add_data['conflict_list'] # Retrieve directly the object from addNode object = add_data['object'] - #LOG('XMLSyncUtils, in ADD add_data',0,add_data) if object is not None: signature.setPath(object.getPhysicalPath()) signature.setObjectId(object.getId()) @@ -1113,7 +1104,7 @@ class XMLSyncUtilsMixin(SyncCode): if add_data['conflict_list'] not in ('', None, []): conflict_list += add_data['conflict_list'] if object is not None: - #LOG('SyncModif',0,'addNode, found the object') + LOG('applyActionList', DEBUG, 'addNode, found the object') if reset: #After a reset we want copy the LAST XML view on Signature. #this implementation is not sufficient, need to be improved. @@ -1133,18 +1124,20 @@ class XMLSyncUtilsMixin(SyncCode): remote_xml=action) cmd_id +=1 elif action.nodeName == 'Replace': - #LOG('SyncModif',0,'object: %s will be updated...' % str(object)) + LOG('applyActionList', DEBUG, 'object: %s will be updated...' % str(object)) if object is not None: - #LOG('SyncModif',0,'object: %s will be updated...' % object.id) + LOG('applyActionList', DEBUG, 'object: %s will be updated...' % object.id) signature = subscriber.getSignatureFromGid(gid) if signature is None: signature = subscriber.getSignatureFromRid(gid) - #LOG('SyncModif',0,'previous signature: %s' % str(signature)) + LOG('applyActionList', DEBUG, 'previous signature: %s' % str(signature)) previous_xml = signature.getXML() - #LOG('SyncModif',0,'previous signature: %i' % len(previous_xml)) - conflict_list += conduit.updateNode(xml=data_subnode, object=object, - previous_xml=signature.getXML(),force=force, - simulate=simulate) + conflict_list += conduit.updateNode( + xml=data_subnode, + object=object, + previous_xml=signature.getXML(), + force=force, + simulate=simulate) xml_object = domain.getXMLFromObject(object) signature.setTempXML(xml_object) if conflict_list != []: @@ -1153,67 +1146,66 @@ class XMLSyncUtilsMixin(SyncCode): signature.setConflictList(signature.getConflictList() \ + conflict_list) string_io = StringIO() - PrettyPrint(data_subnode,stream=string_io) + PrettyPrint(data_subnode, stream=string_io) data_subnode_string = string_io.getvalue() signature.setPartialXML(data_subnode_string) elif not simulate: signature.setStatus(self.SYNCHRONIZED) - xml_confirmation += self.SyncMLConfirmation(\ - cmd_id=cmd_id, - cmd='Replace', - sync_code=status_code, - remote_xml=action) + xml_confirmation += self.SyncMLConfirmation( + cmd_id=cmd_id, + cmd='Replace', + sync_code=status_code, + remote_xml=action) cmd_id +=1 if simulate: # This means we are on the publisher side and we want to store # the xupdate from the subscriber and we also want to generate # the current xupdate from the last synchronization string_io = StringIO() - PrettyPrint(data_subnode,stream=string_io) + PrettyPrint(data_subnode, stream=string_io) data_subnode_string = string_io.getvalue() - #LOG('applyActionList, subscriber_xupdate:',0,data_subnode_string) + LOG('applyActionList, subscriber_xupdate:', TRACE, data_subnode_string) signature.setSubscriberXupdate(data_subnode_string) elif action.nodeName == 'Delete': object_id = signature.getId() - #LOG('Delete on : ',0, (signature.getId(), subscriber.getObjectFromGid(object_id))) - if subscriber.getMediaType() != self.MEDIA_TYPE['TEXT_XML']: + LOG('applyActionList Delete on : ', DEBUG, (signature.getId(), subscriber.getObjectFromGid(object_id))) + if subscriber.getMediaType() != self.MEDIA_TYPE['TEXT_XML']: data_subnode = self.getDataText(action) else: data_subnode = self.getDataSubNode(action) if subscriber.getObjectFromGid(object_id) not in (None, ''): #if the object exist: - conduit.deleteNode(xml=data_subnode, object=destination, - object_id=subscriber.getObjectFromGid(object_id).getId()) + conduit.deleteNode( + xml=data_subnode, + object=destination, + object_id=subscriber.getObjectFromGid(object_id).getId()) subscriber.delSignature(gid) xml_confirmation += self.SyncMLConfirmation( - cmd_id=cmd_id, - cmd='Delete', - sync_code=status_code, - remote_xml=action) + cmd_id=cmd_id, + cmd='Delete', + sync_code=status_code, + remote_xml=action) else: # We want to retrieve more data signature.setStatus(self.PARTIAL) - #LOG('SyncModif',0,'setPartialXML: %s' % str(previous_partial)) previous_partial = signature.getPartialXML() or '' - #if previous_partial.find(partial_data)<0: # XXX bad thing previous_partial += partial_data + LOG('applyActionList', DEBUG, 'setPartialXML: %s' % str(previous_partial)) signature.setPartialXML(previous_partial) - #LOG('SyncModif',0,'previous_partial: %s' % str(previous_partial)) - #LOG('SyncModif',0,'waiting more data for :%s' % signature.getId()) - #xml_confirmation += self.SyncMLConfirmation(cmd_id, object_gid, - # self.WAITING_DATA, action.nodeName) - xml_confirmation += self.SyncMLConfirmation(\ - cmd_id=cmd_id, - cmd=action.nodeName, - sync_code=self.WAITING_DATA, - remote_xml=action) + LOG('applyActionList', DEBUG, 'previous_partial: %s' % str(previous_partial)) + LOG('applyActionList', DEBUG, 'waiting more data for :%s' % signature.getId()) + xml_confirmation += self.SyncMLConfirmation( + cmd_id=cmd_id, + cmd=action.nodeName, + sync_code=self.WAITING_DATA, + remote_xml=action) if conflict_list != [] and signature is not None: # We had a conflict signature.setStatus(self.CONFLICT) - return (xml_confirmation,has_next_action,cmd_id) + return (xml_confirmation, has_next_action, cmd_id) - def applyStatusList(self, subscriber=None,remote_xml=None): + def applyStatusList(self, subscriber=None, remote_xml=None): """ This read a list of status list (ie syncml confirmations). This method have to change status codes on signatures @@ -1224,9 +1216,6 @@ class XMLSyncUtilsMixin(SyncCode): if status_list != []: for status in status_list: status_cmd = status['cmd'] - #if status_cmd in ('Delete'): - # object_gid = status['target'] - #else: object_gid = status['source'] if object_gid in ('', None, []): object_gid = status['target'] @@ -1298,27 +1287,24 @@ class XMLSyncUtils(XMLSyncUtilsMixin): """ Modification Message, this is used after the first message in order to send modifications. - """ - """ - Send the server modification, this happens after the Synchronization - initialization + Send the server modification, this happens after the Synchronization + initialization """ has_response = 0 #check if syncmodif replies to this messages cmd_id = 1 # specifies a SyncML message-unique command identifier - LOG('SyncModif',0,'Starting... domain: %s' % str(domain)) - + LOG('SyncModif', DEBUG, 'Starting... domain: %s' % domain.getId()) first_node = remote_xml.childNodes[0] # Get informations from the header xml_header = first_node.childNodes[1] if xml_header.nodeName != "SyncHdr": - LOG('PubSyncModif',0,'This is not a SyncML Header') + LOG('SyncModif', INFO, 'This is not a SyncML Header') raise ValueError, "Sorry, This is not a SyncML Header" subscriber = domain # If we are the client, this is fine simulate = 0 # used by applyActionList, should be 0 for client if domain.domain_type == self.PUB: simulate = 1 - subscription_url = self.getSubscriptionUrl(xml_header) + subscription_url = self.getSubscriptionUrl(xml_header) subscriber = domain.getSubscriber(subscription_url) # We have to check if this message was not already, this can be dangerous @@ -1326,72 +1312,84 @@ class XMLSyncUtils(XMLSyncUtilsMixin): message_id = self.getMessageId(remote_xml) correct_message = subscriber.checkCorrectRemoteMessageId(message_id) if not correct_message: # We need to send again the message - LOG('SyncModif, no correct message:',0,"sending again...") + LOG('SyncModif, no correct message:', INFO, "sending again...") last_xml = subscriber.getLastSentMessage() - LOG("last_xml :", 0, last_xml) + LOG("SyncModif last_xml :", INFO, last_xml) if last_xml != '': has_response = 1 if domain.domain_type == self.PUB: # We always reply - self.sendResponse(from_url=domain.publication_url, - to_url=subscriber.subscription_url, sync_id=domain.getTitle(), - xml=last_xml,domain=domain, - content_type=domain.getSyncContentType()) + self.sendResponse( + from_url=domain.publication_url, + to_url=subscriber.subscription_url, + sync_id=domain.getTitle(), + xml=last_xml,domain=domain, + content_type=domain.getSyncContentType()) elif domain.domain_type == self.SUB: - self.sendResponse(from_url=domain.subscription_url, - to_url=domain.publication_url, sync_id=domain.getTitle(), - xml=last_xml, domain=domain, - content_type=domain.getSyncContentType()) - return {'has_response':has_response,'xml':last_xml} + self.sendResponse( + from_url=domain.subscription_url, + to_url=domain.publication_url, + sync_id=domain.getTitle(), + xml=last_xml, + domain=domain, + content_type=domain.getSyncContentType()) + return {'has_response':has_response, 'xml':last_xml} subscriber.setLastSentMessage('') # First apply the list of status codes (destination_waiting_more_data,has_status_list) = self.applyStatusList( - subscriber=subscriber, - remote_xml=remote_xml) + subscriber=subscriber, + remote_xml=remote_xml) alert_code = self.getAlertCode(remote_xml) # Import the conduit and get it conduit = self.getConduitByName(subscriber.getConduit()) # Then apply the list of actions (xml_confirmation, has_next_action, cmd_id) = self.applyActionList( - cmd_id=cmd_id, - domain=domain, - subscriber=subscriber, - remote_xml=remote_xml, - conduit=conduit, simulate=simulate) - #LOG('SyncModif, has_next_action:',0,has_next_action) - + cmd_id=cmd_id, + domain=domain, + subscriber=subscriber, + remote_xml=remote_xml, + conduit=conduit, simulate=simulate) xml_list = [] xml = xml_list.append xml('<SyncML>\n') # syncml header if domain.domain_type == self.PUB: - xml(self.SyncMLHeader(subscriber.getSessionId(), - subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(), - domain.getPublicationUrl())) + xml(self.SyncMLHeader( + subscriber.getSessionId(), + subscriber.incrementMessageId(), + subscriber.getSubscriptionUrl(), + domain.getPublicationUrl())) elif domain.domain_type == self.SUB: - xml(self.SyncMLHeader(domain.getSessionId(), domain.incrementMessageId(), - domain.getPublicationUrl(), domain.getSubscriptionUrl())) - + xml(self.SyncMLHeader( + domain.getSessionId(), domain.incrementMessageId(), + domain.getPublicationUrl(), + domain.getSubscriptionUrl())) # Add or replace objects syncml_data = '' # syncml body xml(' <SyncBody>\n') - xml_status, cmd_id = self.SyncMLStatus(remote_xml, self.SUCCESS, cmd_id, - subscriber.getNextAnchor(), subscription=subscriber).values() + xml_status, cmd_id = self.SyncMLStatus( + remote_xml, + self.SUCCESS, + cmd_id, + subscriber.getNextAnchor(), + subscription=subscriber).values() xml(xml_status) destination_url = '' # alert message if we want more data if destination_waiting_more_data == 1: - xml(self.SyncMLAlert(cmd_id, self.WAITING_DATA, - subscriber.getTargetURI(), - subscriber.getSourceURI(), - subscriber.getLastAnchor(), - subscriber.getNextAnchor())) + xml(self.SyncMLAlert( + cmd_id, + self.WAITING_DATA, + subscriber.getTargetURI(), + subscriber.getSourceURI(), + subscriber.getLastAnchor(), + subscriber.getNextAnchor())) # Now we should send confirmations cmd_id_before_getsyncmldata = cmd_id cmd_id = cmd_id+1 @@ -1432,14 +1430,17 @@ class XMLSyncUtils(XMLSyncUtilsMixin): domain = self.unrestrictedTraverse(kw['domain_relative_url']) subscriber = self.unrestrictedTraverse(kw['subscriber_relative_url']) conduit = subscriber.getConduit() - result = self.getSyncMLData(domain = domain, subscriber = subscriber, - conduit = conduit, max = self.MAX_OBJECTS, **kw) + result = self.getSyncMLData( + domain = domain, + subscriber = subscriber, + conduit = conduit, + max = self.MAX_OBJECTS, + **kw) syncml_data = result['syncml_data'] cmd_id = result['cmd_id'] kw['syncml_data'] = syncml_data kw['cmd_id'] = cmd_id finished = result['finished'] - #LOG('finished =',0,finished) if not finished: self.activate(activity='SQLQueue').SyncModifActivity(**kw) else: @@ -1450,9 +1451,16 @@ class XMLSyncUtils(XMLSyncUtilsMixin): xml_list = kw['xml_list'] has_status_list = kw['has_status_list'] has_response = kw['has_response'] - return self.sendSyncModif(syncml_data, cmd_id_before_getsyncmldata, - subscriber, domain, xml_confirmation, - remote_xml, xml_list, has_status_list, has_response) + return self.sendSyncModif( + syncml_data, + cmd_id_before_getsyncmldata, + subscriber, + domain, + xml_confirmation, + remote_xml, + xml_list, + has_status_list, + has_response) def sendSyncModif(self, syncml_data, cmd_id_before_getsyncmldata, subscriber, domain, xml_confirmation, remote_xml, xml_list, @@ -1479,20 +1487,25 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if domain.domain_type == self.PUB: # We always reply subscriber.setLastSentMessage(xml_a) - self.sendResponse(from_url=domain.publication_url, - to_url=subscriber.subscription_url, sync_id=domain.getTitle(), - xml=xml_a,domain=domain, - content_type=domain.getSyncContentType()) + self.sendResponse( + from_url=domain.publication_url, + to_url=subscriber.subscription_url, + sync_id=domain.getTitle(), + xml=xml_a, + domain=domain, + content_type=domain.getSyncContentType()) has_response = 1 elif domain.domain_type == self.SUB: if self.checkAlert(remote_xml) or \ - (xml_confirmation,syncml_data)!=('','') or \ + (xml_confirmation,syncml_data) != ('','') or \ has_status_list: subscriber.setLastSentMessage(xml_a) - self.sendResponse(from_url=domain.subscription_url, - to_url=domain.publication_url, sync_id=domain.getTitle(), - xml=xml_a,domain=domain, - content_type=domain.getSyncContentType()) + self.sendResponse( + from_url=domain.subscription_url, + to_url=domain.publication_url, + sync_id=domain.getTitle(), + xml=xml_a,domain=domain, + content_type=domain.getSyncContentType()) has_response = 1 return {'has_response':has_response,'xml':xml_a} @@ -1500,7 +1513,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): """ convert xml string to wbxml using a temporary file """ - LOG('xml2wbxml starting ...',0,'') + LOG('xml2wbxml starting ...', DEBUG, '') import os f = open('/tmp/xml2wbxml', 'w') f.write(xml) @@ -1515,7 +1528,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): """ convert wbxml string to xml using a temporary file """ - LOG('wbxml2xml starting ...',0,'') + LOG('wbxml2xml starting ...', DEBUG, '') import os f = open('/tmp/wbxml2xml', 'w') f.write(wbxml) diff --git a/product/ERP5SyncML/XupdateUtils.py b/product/ERP5SyncML/XupdateUtils.py index a21c16ea4e4342df1fe7833843f84b7a7dc0dd90..38b2d431010afe3341fcf6bb310f5577a8871e76 100644 --- a/product/ERP5SyncML/XupdateUtils.py +++ b/product/ERP5SyncML/XupdateUtils.py @@ -48,7 +48,7 @@ class XupdateUtils(XMLSyncUtilsMixin): for subnode in self.getElementNodeList(xupdate): selection_name = '' if subnode.nodeName in self.XUPDATE_INSERT_OR_ADD: - conflict_list += conduit.addNode(xml=subnode,object=object, \ + conflict_list += conduit.addNode(xml=subnode, object=object, \ force=force, **kw) elif subnode.nodeName in self.XUPDATE_DEL: conflict_list += conduit.deleteNode(xml=subnode, object=object, \ @@ -56,9 +56,6 @@ class XupdateUtils(XMLSyncUtilsMixin): elif subnode.nodeName in self.XUPDATE_UPDATE: conflict_list += conduit.updateNode(xml=subnode, object=object, \ force=force, **kw) - #elif subnode.nodeName in self.XUPDATE_INSERT: - # conflict_list += conduit.addNode(xml=subnode, object=object, force=force, **kw) - return conflict_list diff --git a/product/ERP5SyncML/dtml/manageSubscriptions.dtml b/product/ERP5SyncML/dtml/manageSubscriptions.dtml index c9080c922562f036896fd7e5e0a46df104b99104..4651e731637a4ac798d8d219b7f33f762f3e518b 100644 --- a/product/ERP5SyncML/dtml/manageSubscriptions.dtml +++ b/product/ERP5SyncML/dtml/manageSubscriptions.dtml @@ -66,12 +66,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. </label></div> </td> <td align="left" valign="top"> - <select name="alert_code"> - <dtml-in getAlertCodeList> - <dtml-let item=sequence-item> - <option value="<dtml-var item>" <dtml-if expr="getAlertCode() == str(item)">SELECTED</dtml-if>><dtml-var item></option> - </dtml-let> - </dtml-in> + <select name="alert_code"> + <dtml-in getAlertCodeList> + <dtml-let item=sequence-item> + <option value="<dtml-var item>" <dtml-if expr="getAlertCode() == item">SELECTED</dtml-if>><dtml-var item></option> + </dtml-let> + </dtml-in> + </select> </td> </tr> <tr> diff --git a/product/ERP5SyncML/dtml/manage_addSubscription.dtml b/product/ERP5SyncML/dtml/manage_addSubscription.dtml index 7af2e44a255c850c919240a03e02e7f7427abb1f..630d40bdeda457bdd9934b521491eed845679c75 100644 --- a/product/ERP5SyncML/dtml/manage_addSubscription.dtml +++ b/product/ERP5SyncML/dtml/manage_addSubscription.dtml @@ -147,7 +147,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. </label></div> </td> <td align="left" valign="top"> - <input type="checkbox" name="synchronize_with_erp5_sites" value="1"> + <input type="checkbox" name="synchronize_with_erp5_sites" value="1" checked="checked"> </td> </tr> <tr>