Commit eacbecf5 authored by Nicolas Delaby's avatar Nicolas Delaby

Add log management, optimisation, typo

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