[Erp5-report] r14280 - /erp5/trunk/products/ERP5SyncML/

nobody at svn.erp5.org nobody at svn.erp5.org
Mon Apr 30 16:34:22 CEST 2007


Author: seb
Date: Mon Apr 30 16:34:22 2007
New Revision: 14280

URL: http://svn.erp5.org?rev=14280&view=rev
Log:
Commit the work of Fabien
- use list of string instead of adding string to strings
  in order to improve performance
- use message id instead of session id. Increase message id
  for each message
- start to implement authentication

Modified:
    erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py
    erp5/trunk/products/ERP5SyncML/Subscription.py
    erp5/trunk/products/ERP5SyncML/SubscriptionSynchronization.py
    erp5/trunk/products/ERP5SyncML/SyncCode.py
    erp5/trunk/products/ERP5SyncML/SynchronizationTool.py
    erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py

Modified: erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py (original)
+++ erp5/trunk/products/ERP5SyncML/PublicationSynchronization.py Mon Apr 30 16:34:22 2007
@@ -39,12 +39,21 @@
 
 class PublicationSynchronization(XMLSyncUtils):
 
-  def PubSyncInit(self, publication=None, xml_client=None, subscriber=None, sync_type=None):
+  def PubSyncInit(self, publication=None, xml_client=None, subscriber=None, 
+      sync_type=None, auth_required=0):
     """
       Read the client xml message
       Send the first XML message from the server
     """
     LOG('PubSyncInit',0,'Starting... publication: %s' % str(publication))
+   
+    #the session id is set at the same value of those of the client
+    subscriber.setSessionId(self.getSessionId(xml_client))
+    # for a new session, the message Id must be reset
+    subscriber.resetMessageId()     
+    #the last_message_id is 1 because the message that 
+    #we are about to send is the message 1      
+    subscriber.initLastMessageId(1)
 
     alert = None
     # Get informations from the body
@@ -53,55 +62,91 @@
       next_anchor = self.getAlertNextAnchor(xml_client)
       alert = self.checkAlert(xml_client)
       alert_code = self.getAlertCode(xml_client)
-
-      # If slow sync, then resend everything
-      if alert_code == self.SLOW_SYNC:
-        LOG('Warning !!!, reseting client synchronization for subscriber:',0,subscriber)
-        subscriber.resetAllSignatures()
-
-      # Check if the last time synchronization is the same as the client one
-      if subscriber.getNextAnchor() != last_anchor:
-        if last_anchor == None:
-          LOG('PubSyncInit',0,'anchor null')
+      cred = self.checkCred(xml_client)
+      #XXX this is in developement, it's just for tests
+      if not cred and auth_required:
+        LOG('PubSyncInit',0,'authentication required')
+	      # Prepare the xml message for the Sync initialization package
+        cmd_id = 1 # specifies a SyncML message-unique command identifier
+        xml_list = []
+        xml = xml_list.append
+        xml('<SyncML>\n')
+        # syncml header
+        xml(self.SyncMLHeader(subscriber.getSessionId(),
+          subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(), 
+          publication.getPublicationUrl()))
+        # syncml body
+        xml(' <SyncBody>\n')
+	      # chal message
+        xml(self.SyncMLChal(cmd_id, "SyncHdr", publication.getPublicationUrl(), 
+          subscriber.getSubscriptionUrl(), "b64", "syncml:auth-basic", 
+          self.UNAUTHORIZED))
+        cmd_id += 1
+
+        xml(' </SyncBody>\n')
+
+        xml('</SyncML>\n')
+        xml_a = ''.join(xml_list)
+
+        self.sendResponse(from_url=publication.getPublicationUrl(),
+          to_url=subscriber.getSubscriptionUrl(),sync_id=publication.getTitle(),
+          xml=xml_a,domain=publication)
+      else :
+        # If slow sync, then resend everything
+        if alert_code == self.SLOW_SYNC:
+          LOG('Warning !!!, reseting client synchronization for subscriber:',0,
+              subscriber)
+          subscriber.resetAllSignatures()
+
+        # Check if the last time synchronization is the same as the client one
+        mess='\nsubscriber.getNextAnchor:\t%s\nsubscriber.getLastAnchor:\t%s\
+        \nlast_anchor:\t\t\t%s\nnext_anchor:\t\t\t%s' % (subscriber.getNextAnchor(), 
+        subscriber.getLastAnchor(), last_anchor, next_anchor)
+        LOG('PubSyncInit',0,mess)
+        
+        if subscriber.getNextAnchor() != last_anchor:
+          if last_anchor == None:
+            LOG('PubSyncInit',0,'anchor null')
+            raise ValueError, "Sorry, the anchor was null"
+          else:
+            message = "bad anchors in PubSyncInit! " + subscriber.getNextAnchor() + \
+                      " and " + last_anchor
+            LOG('PubSyncInit',0,message)
         else:
-          message = "bad anchors in PubSyncInit! " + subscriber.getNextAnchor() + \
-                    " and " + last_anchor
-          LOG('PubSyncInit',0,message)
-      else:
-        subscriber.setNextAnchor(next_anchor)
-
+	        subscriber.setNextAnchor(next_anchor)
       # We have to set every object as NOT_SYNCHRONIZED
       subscriber.startSynchronization()
     else:
       # We have started the sync from the server (may be for a conflict resolution)
       pass
 
-    xml = ""
-    #if alert is not None:
-    if 1:
+    if alert is not None and auth_required==0:
+    #if 1:
       # Prepare the xml message for the Sync initialization package
       cmd_id = 1 # specifies a SyncML message-unique command identifier
-      xml = ""
-      xml += '<SyncML>\n'
-
+      xml_list = []
+      xml = xml_list.append
+
+      xml('<SyncML>\n')
       # syncml header
-      xml += self.SyncMLHeader(subscriber.getSessionId(), "1",
-          subscriber.getSubscriptionUrl(), publication.getPublicationUrl())
-
+      xml(self.SyncMLHeader(subscriber.getSessionId(), 
+        subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(), 
+        publication.getPublicationUrl()))
       # syncml body
-      xml += ' <SyncBody>\n'
+      xml(' <SyncBody>\n')
       # alert message
-      xml += self.SyncMLAlert(cmd_id, sync_type, subscriber.getSubscriptionUrl(),
-            publication.getPublicationUrl(), subscriber.getLastAnchor(), subscriber.getNextAnchor())
+      xml(self.SyncMLAlert(cmd_id, sync_type, subscriber.getSubscriptionUrl(),
+        publication.getPublicationUrl(), subscriber.getLastAnchor(), 
+        subscriber.getNextAnchor()))
       cmd_id += 1
-      xml += ' </SyncBody>\n'
-
-      xml += '</SyncML>\n'
-
-    self.sendResponse(from_url=publication.getPublicationUrl(),
-         to_url=subscriber.getSubscriptionUrl(),sync_id=publication.getTitle(),xml=xml,
-         domain=publication)
-    return {'has_response':1,'xml':xml}
+      xml(' </SyncBody>\n')
+      xml('</SyncML>\n')
+      xml_a = ''.join(xml_list)
+
+      self.sendResponse(from_url=publication.getPublicationUrl(),
+        to_url=subscriber.getSubscriptionUrl(), sync_id=publication.getTitle(), 
+        xml=xml_a, domain=publication)
+    return {'has_response':1,'xml':xml_a}
 
 
   def PubSync(self, id, msg=None, RESPONSE=None, subscriber=None):
@@ -118,23 +163,27 @@
     publication = self.getPublication(id)
 
     if xml_client is not None:
-      if type(xml_client) in (type('a'),type(u'a')):
+      if isinstance(xml_client, str) or isinstance(xml_client, unicode):
         xml_client = parseString(xml_client)
       first_node = xml_client.childNodes[0]
 
       if first_node.nodeName != "SyncML":
         LOG('PubSync',0,'This is not a SyncML Message')
-        return
+        raise ValueError, "Sorry, This is not a SyncML Message"
       alert_code = self.getAlertCode(xml_client)
 
       # Get informations from the header
       client_header = first_node.childNodes[1]
       if client_header.nodeName != "SyncHdr":
         LOG('PubSync',0,'This is not a SyncML Header')
-        return
+        raise ValueError, "Sorry, This is not a SyncML Header"
       for subnode in client_header.childNodes:
-        if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Source":
-          subscription_url = str(subnode.childNodes[0].data)
+        if subnode.nodeType == subnode.ELEMENT_NODE and \
+            subnode.nodeName == "Source":
+          for subnode2 in subnode.childNodes:
+            if subnode2.nodeType == subnode2.ELEMENT_NODE and \
+                subnode2.nodeName == "LocURI":
+              subscription_url = str(subnode2.childNodes[0].data)
       # Get the subscriber or create it if not already in the list
       subscriber = publication.getSubscriber(subscription_url)
       if subscriber == None:
@@ -142,19 +191,21 @@
         subscriber.setXMLMapping(publication.getXMLMapping())
         publication.addSubscriber(subscriber)
         # first synchronization
-        result = self.PubSyncInit(publication,xml_client,subscriber=subscriber,sync_type=self.SLOW_SYNC)
-
-
-      elif self.checkAlert(xml_client) and alert_code in (self.TWO_WAY,self.SLOW_SYNC):
-        result = self.PubSyncInit(publication=publication,
-                         xml_client=xml_client, subscriber=subscriber,sync_type=alert_code)
+        result = self.PubSyncInit(publication,xml_client,subscriber=subscriber,
+            sync_type=self.SLOW_SYNC)
+
+
+      elif self.checkAlert(xml_client) and \
+          alert_code in (self.TWO_WAY,self.SLOW_SYNC):
+        result = self.PubSyncInit(publication=publication, 
+            xml_client=xml_client, subscriber=subscriber, sync_type=alert_code)
       else:
         result = self.PubSyncModif(publication, xml_client)
     elif subscriber is not None:
       # This looks like we are starting a synchronization after
       # a conflict resolution by the user
-      result = self.PubSyncInit(publication=publication,
-                      xml_client=None, subscriber=subscriber,sync_type=self.TWO_WAY)
+      result = self.PubSyncInit(publication=publication, xml_client=None, 
+          subscriber=subscriber,sync_type=self.TWO_WAY)
 
     if RESPONSE is not None:
       RESPONSE.redirect('managePublications')

Modified: erp5/trunk/products/ERP5SyncML/Subscription.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/Subscription.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/Subscription.py (original)
+++ erp5/trunk/products/ERP5SyncML/Subscription.py Mon Apr 30 16:34:22 2007
@@ -660,7 +660,7 @@
     self.setConduit(conduit)
     Folder.__init__(self, id)
     self.title = title
-
+    
     #self.signatures = PersitentMapping()
 
   def getTitle(self):
@@ -723,6 +723,26 @@
     self.last_session_id = session_id
     return 1
 
+  def checkCorrectRemoteMessageId(self, message_id):
+    """
+    We will see if the last message id was the same
+    wich means that the same message was sent again
+
+    return 1 if the message id was not seen, 0 if already seen
+    """
+    last_message_id = getattr(self,'last_message_id',None)
+    LOG('checkCorrectRemoteMessageId  last_message_id =',0,last_message_id)
+    LOG('checkCorrectRemoteMessageId  message_id =',0,message_id)
+    if last_message_id == message_id:
+      return 0
+    self.last_message_id = message_id
+    return 1
+
+  def initLastMessageId(self, last_message_id=None):
+    """
+    set the last message id to 0
+    """
+    self.last_message_id=last_message_id
 
   def getLastSentMessage(self):
     """
@@ -926,7 +946,7 @@
     query_list = []
     if query is None:
       return query_list
-    if type(query) is type('a'):
+    if isinstance(query, str):
       query_method = getattr(destination,query,None)
       if query_method is not None:
         query_list = query_method()
@@ -1009,13 +1029,50 @@
       return the current subscription
     """
     return self
+    
+  def setSessionId(self, session_id):
+    """
+      set the session id
+    """
+    self.session_id = session_id
 
   def getSessionId(self):
     """
       return the session id
     """
+    #self.session_id += 1 #to be commented
+    return self.session_id
+
+  def incrementSessionId(self):
+    """
+      increment and return the session id
+    """
     self.session_id += 1
+    self.resetMessageId() # for a new session, the message Id must be reset
     return self.session_id
+
+  def incrementMessageId(self):
+    """
+      return the message id
+    """
+    #self.message_id += 1
+    #return self.message_id
+    #return 5
+    value = getattr(self, 'message_id', 0)
+    self.message_id = value +1
+    return self.message_id
+
+  def getMessageId(self):
+    """
+      increment and return the message id
+    """
+    return self.message_id
+
+  def resetMessageId(self):
+    """
+      set the message id to 0
+    """
+    self.message_id = 0
 
   def getLastAnchor(self):
     """

Modified: erp5/trunk/products/ERP5SyncML/SubscriptionSynchronization.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/SubscriptionSynchronization.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/SubscriptionSynchronization.py (original)
+++ erp5/trunk/products/ERP5SyncML/SubscriptionSynchronization.py Mon Apr 30 16:34:22 2007
@@ -44,38 +44,43 @@
     """
     LOG('SubSyncInit',0,'starting....')
     cmd_id = 1 # specifies a SyncML message-unique command identifier
-    xml = ""
-    xml += '<SyncML>\n'
-
+    xml_list = []
+    xml = xml_list.append
+    xml('<SyncML>\n')
     # syncml header
-    xml += self.SyncMLHeader(subscription.getSessionId(), "1",
-        subscription.getPublicationUrl(), subscription.getSubscriptionUrl())
+    xml(self.SyncMLHeader(subscription.incrementSessionId(), 
+      subscription.incrementMessageId(), subscription.getPublicationUrl(), 
+      subscription.getSubscriptionUrl()))
 
     # syncml body
-    xml += ' <SyncBody>\n'
+    xml(' <SyncBody>\n')
     subscription.NewAnchor()
+    subscription.initLastMessageId()
 
     # We have to set every object as NOT_SYNCHRONIZED
     subscription.startSynchronization()
 
     # alert message
-    xml += self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
+    xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
                             subscription.getPublicationUrl(),
                             subscription.getDestinationPath(),
-                            subscription.getLastAnchor(), subscription.getNextAnchor())
+                            subscription.getLastAnchor(), 
+                            subscription.getNextAnchor()))
     cmd_id += 1
 
-    xml += '  <Put>\n'
-    xml += '   <CmdID>%s</CmdID>\n' % cmd_id ; cmd_id += 1
-    xml += '  </Put>\n'
-    xml += ' </SyncBody>\n'
+    xml('  <Put>\n')
+    xml('   <CmdID>%s</CmdID>\n' % cmd_id)
+    cmd_id += 1
+    xml('  </Put>\n')
+    xml(' </SyncBody>\n')
+    xml('</SyncML>\n')
+    xml_a = ''.join(xml_list)
 
-    xml += '</SyncML>\n'
+    self.sendResponse(from_url=subscription.subscription_url,
+        to_url=subscription.publication_url, sync_id=subscription.getTitle(), 
+        xml=xml_a,domain=subscription)
 
-    self.sendResponse(from_url=subscription.subscription_url, to_url=subscription.publication_url,
-                sync_id=subscription.getTitle(), xml=xml,domain=subscription)
-
-    return {'has_response':1,'xml':xml}
+    return {'has_response':1,'xml':xml_a}
 
   def SubSync(self, id, msg=None, RESPONSE=None):
     """
@@ -83,17 +88,17 @@
     """
     LOG('SubSync',0,'starting... id: %s' % str(id))
     LOG('SubSync',0,'starting... msg: %s' % str(msg))
-
     response = None #check if subsync replies to this messages
     subscription = self.getSubscription(id)
 
     if msg==None and (subscription.getSubscriptionUrl()).find('file')>=0:
-      msg = self.readResponse(sync_id=id,from_url=subscription.getSubscriptionUrl())
+      msg = self.readResponse(sync_id=id, 
+          from_url=subscription.getSubscriptionUrl())
     if msg==None:
       response = self.SubSyncInit(self.getSubscription(id))
     else:
       xml_client = msg
-      if type(xml_client) in (type('a'),type(u'a')):
+      if isinstance(xml_client, str) or isinstance(xml_client, unicode):
         xml_client = parseString(xml_client)
       response = self.SubSyncModif(self.getSubscription(id),xml_client)
 

Modified: erp5/trunk/products/ERP5SyncML/SyncCode.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/SyncCode.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/SyncCode.py (original)
+++ erp5/trunk/products/ERP5SyncML/SyncCode.py Mon Apr 30 16:34:22 2007
@@ -47,6 +47,9 @@
                        # whatever is needed to change(replace)
   CONFLICT_CLIENT_WIN = 208 # The client is the "winner", we keep
                             # the version of the client
+  UNAUTHORIZED = 401
+  AUTH_REQUIRED = 407
+  AUTH_ACCEPTED = 212
 
   # Difference between publication and subscription
   PUB = 1

Modified: erp5/trunk/products/ERP5SyncML/SynchronizationTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/SynchronizationTool.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/SynchronizationTool.py (original)
+++ erp5/trunk/products/ERP5SyncML/SynchronizationTool.py Mon Apr 30 16:34:22 2007
@@ -734,9 +734,9 @@
     """
     if context is None:
       return context
-    elif type(context) is type(()):
+    elif isinstance(context, tuple):
       return context
-    elif type(context) is type('a'):
+    elif isinstance(context, tuple):
       return tuple(context.split('/'))
     else:
       return context.getPhysicalPath()
@@ -751,7 +751,7 @@
     LOG('sendResponse, to_url: ',0,to_url)
     LOG('sendResponse, from_url: ',0,from_url)
     LOG('sendResponse, sync_id: ',0,sync_id)
-    LOG('sendResponse, xml: ',0,xml)
+    LOG('sendResponse, xml: \n',0,xml)
     if domain is not None:
       gpg_key = domain.getGPGKey()
       if gpg_key not in ('',None):
@@ -768,14 +768,14 @@
         commands.getstatusoutput('rm -f /tmp/%s.gz' % filename)
         commands.getstatusoutput('rm -f /tmp/%s.gz.gpg' % filename)
     if send:
-      if type(to_url) is type('a'):
+      if isinstance(to_url, str):
         if to_url.find('http://')==0:
           # XXX Make sure this is not a problem
           if domain.domain_type == self.PUB:
             return None
           # we will send an http response
           domain = aq_base(domain)
-          LOG('sendResponse, will start sendHttpResponse, xml',0,xml)
+          LOG('sendResponse, will start sendHttpResponse, xml\n',0,xml)
           self.activate(activity='RAMQueue').sendHttpResponse(sync_id=sync_id,
                                            to_url=to_url,
                                            xml=xml, domain=domain)
@@ -907,30 +907,38 @@
         commands.getstatusoutput('rm -f /tmp/%s.gz.gpg' % filename)
       # Get the target and then find the corresponding publication or
       # Subscription
-      LOG('readResponse, xml before parseSTring',0,text)
+      LOG('readResponse, xml before parseSTring\n',0,text)
       xml = parseString(text)
-      url = ''
-      for subnode in self.getElementNodeList(xml):
-        if subnode.nodeName == 'SyncML':
-          for subnode1 in self.getElementNodeList(subnode):
-            if subnode1.nodeName == 'SyncHdr':
-              for subnode2 in self.getElementNodeList(subnode1):
-                if subnode2.nodeName == 'Target':
-                  url = subnode2.childNodes[0].data 
+      
+      #XXX this function is not very optimized and should be improved
+      url = self.getTarget(xml)
+      
       for publication in self.getPublicationList():
         if publication.getPublicationUrl()==url and publication.getTitle()==sync_id:
           result = self.PubSync(sync_id,xml)
           # Then encrypt the message
           xml = result['xml']
-          xml = self.sendResponse(xml=xml,domain=publication,send=0)
+
+          #must be commented because this method is alredy called
+          #xml = self.sendResponse(xml=xml,domain=publication,send=0)
           return xml
       for subscription in self.getSubscriptionList():
-        if subscription.getSubscriptionUrl()==url and subscription.getTitle()==sync_id:
-          result = self.activate(activity='RAMQueue').SubSync(sync_id,xml)
+        if subscription.getSubscriptionUrl()==url and \
+            subscription.getTitle()==sync_id:
+          next_status = self.getNextSyncBodyStatus(xml, None)
+          if next_status is not None:
+            status_code = self.getStatusCode(next_status)
+            LOG('readResponse status code :',0,status_code)
+            if status_code == self.UNAUTHORIZED or \
+                status_code == self.AUTH_REQUIRED:
+              LOG('readResponse', 0, 'Authentication required')
+              raise ValueError, "Authentication required"
+          else: 
+            result = self.activate(activity='RAMQueue').SubSync(sync_id,xml)
           #result = self.SubSync(sync_id,xml)
 
     # we use from only if we have a file 
-    elif type(from_url) is type('a'):
+    elif isinstance(from_url, str):
       if from_url.find('file://')==0:
         try:
           filename = from_url[len('file:/'):]

Modified: erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py?rev=14280&r1=14279&r2=14280&view=diff
==============================================================================
--- erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py (original)
+++ erp5/trunk/products/ERP5SyncML/XMLSyncUtils.py Mon Apr 30 16:34:22 2007
@@ -46,78 +46,124 @@
 
 class XMLSyncUtilsMixin(SyncCode):
 
-  def SyncMLHeader(self, session_id, msg_id, target, source):
+  def SyncMLHeader(self, session_id, msg_id, target, source, target_name=None, 
+      source_name=None):
     """
       Since the Header is always almost the same, this is the
       way to set one quickly.
     """
-    xml = ""
-    xml += ' <SyncHdr>\n'
-    xml += '  <VerDTD>1.1</VerDTD>\n'
-    xml += '  <VerProto>SyncML/1.1</VerProto>\n'
-    xml += '  <SessionID>%s</SessionID>\n' % session_id
-    xml += '  <MsgID>%s</MsgID>\n' % msg_id
-    xml += '  <Target>%s</Target>\n' % target
-    xml += '  <Source>%s</Source>\n' % source
-    xml += ' </SyncHdr>\n'
-    return xml
-
-  def SyncMLAlert(self, cmd_id, sync_code, target, source, last_anchor, next_anchor):
+    xml_list = []
+    xml = xml_list.append
+    xml(' <SyncHdr>\n')
+    xml('  <VerDTD>1.1</VerDTD>\n')
+    xml('  <VerProto>SyncML/1.1</VerProto>\n')
+    xml('  <SessionID>%s</SessionID>\n' % session_id)
+    xml('  <MsgID>%s</MsgID>\n' % msg_id)
+    xml('  <Target>\n')
+    xml('   <LocURI>%s</LocURI>\n' % target)
+    if target_name is not None:
+      xml('   <LocName>%s</LocName>\n' %target_name)
+    xml('  </Target>\n')
+    xml('  <Source>\n')
+    xml('   <LocURI>%s</LocURI>\n' % source) 
+    if source_name is not None:
+      xml('   <LocName>%s</LocName>\n' % source_name)
+    xml('  </Source>\n')
+    xml(' </SyncHdr>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
+
+  def SyncMLAlert(self, cmd_id, sync_code, target, source, last_anchor, 
+      next_anchor):
     """
       Since the Alert section is always almost the same, this is the
       way to set one quickly.
     """
-    xml = ""
-    xml += '  <Alert>\n'
-    xml += '   <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '   <Data>%s</Data>\n' % sync_code
-    xml += '   <Item>\n'
-    xml += '    <Target>%s</Target>\n' % target
-    xml += '    <Source>%s</Source>\n' % source
-    xml += '    <Meta>\n'
-    xml += '     <Anchor xmlns=\'syncml:metinf\'>\n'
-    xml += '      <Last>%s</Last>\n' % last_anchor
-    xml += '      <Next>%s</Next>\n' % next_anchor
-    xml += '     </Anchor>\n'
-    xml += '    </Meta>\n'
-    xml += '   </Item>\n'
-    xml += '  </Alert>\n'
-    return xml
-
-  def SyncMLStatus(self, cmd_id, target_ref, source_ref, sync_code, next_anchor):
+    xml_list = []
+    xml = xml_list.append
+    xml('  <Alert>\n')
+    xml('   <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('   <Data>%s</Data>\n' % sync_code)
+    xml('   <Item>\n')
+    xml('    <Target>\n')
+    xml('     <LocURI>%s</LocURI>\n' % target)
+    xml('    </Target>\n')
+    xml('    <Source>\n')
+    xml('     <LocURI>%s</LocURI>\n' % source)
+    xml('    </Source>\n')
+    xml('    <Meta>\n')
+    xml('     <Anchor xmlns=\'syncml:metinf\'>\n')
+    xml('      <Last>%s</Last>\n' % last_anchor)
+    xml('      <Next>%s</Next>\n' % next_anchor)
+    xml('     </Anchor>\n')
+    xml('    </Meta>\n')
+    xml('   </Item>\n')
+    xml('  </Alert>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
+
+  def SyncMLStatus(self, cmd_id, target_ref, source_ref, sync_code, 
+      next_anchor):
     """
       Since the Status section is always almost the same, this is the
       way to set one quickly.
     """
-    xml = ""
-    xml += '  <Status>\n'
-    xml += '   <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '   <TargetRef>%s</TargetRef>\n' % target_ref
-    xml += '   <SourceRef>%s</SourceRef>\n' % source_ref
-    xml += '   <Data>%s</Data>\n' % sync_code
-    xml += '   <Item>\n'
-    xml += '    <Data>\n'
-    xml += '     <Anchor xmlns=\'syncml:metinf\'>\n'
-    xml += '      <Next>%s</Next>\n' % next_anchor
-    xml += '     </Anchor>\n'
-    xml += '    </Data>\n'
-    xml += '   </Item>\n'
-    xml += '  </Status>\n'
-    return xml
+    xml_list = []
+    xml = xml_list.append
+    xml('  <Status>\n')
+    xml('   <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('   <TargetRef>%s</TargetRef>\n' % target_ref)
+    xml('   <SourceRef>%s</SourceRef>\n' % source_ref)
+    xml('   <Data>%s</Data>\n' % sync_code)
+    xml('   <Item>\n')
+    xml('    <Data>\n')
+    xml('     <Anchor xmlns=\'syncml:metinf\'>\n')
+    xml('      <Next>%s</Next>\n' % next_anchor)
+    xml('     </Anchor>\n')
+    xml('    </Data>\n')
+    xml('   </Item>\n')
+    xml('  </Status>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
 
   def SyncMLConfirmation(self, cmd_id, target_ref, sync_code, cmd):
     """
-    This is used in order ton confirm that an object was correctly
+    This is used in order to confirm that an object was correctly
     synchronized
     """
-    xml = ""
-    xml += '  <Status>\n'
-    xml += '   <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '   <TargetRef>%s</TargetRef>\n' % target_ref
-    xml += '   <Cmd>%s</Cmd>' % cmd
-    xml += '   <Data>%s</Data>\n' % sync_code
-    xml += '  </Status>\n'
-    return xml
+    xml_list = []
+    xml = xml_list.append
+    xml('  <Status>\n')
+    xml('   <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('   <TargetRef>%s</TargetRef>\n' % target_ref)
+    xml('   <Cmd>%s</Cmd>\n' % cmd)
+    xml('   <Data>%s</Data>\n' % sync_code)
+    xml('  </Status>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
+    
+  def SyncMLChal(self, cmd_id, cmd, target_ref, source_ref, auth_format, 
+      auth_type, data_code):
+    """
+    This is used in order to ask crendentials
+    """
+    xml_list = []
+    xml = xml_list.append
+    xml('  <Status>\n')
+    xml('   <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('   <Cmd>%s</Cmd>\n' % cmd)
+    xml('   <TargetRef>%s</TargetRef>\n' % target_ref)
+    xml('   <SourceRef>%s</SourceRef>\n' % source_ref)
+    xml('   <Chal>\n')
+    xml('    <Meta>\n')
+    xml('     <Format>%s</Format>\n' % auth_format)
+    xml('     <Type>%s</Type>\n' % auth_type)
+    xml('    </Meta>\n')
+    xml('   </Chal>\n')
+    xml('   <Data>%s</Data>\n' % str(data_code))
+    xml('  </Status>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
 
   def sendMail(self, fromaddr, toaddr, id_sync, msg):
     """
@@ -140,55 +186,67 @@
     """
       Add an object with the SyncML protocol
     """
-    xml = ""
-    xml += '   <Add>\n'
-    xml += '    <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '    <Meta><Type>%s</Type></Meta>\n' % object.portal_type
-    xml += '    <Item>\n'
-    xml += '     <Source><LocURI>%s</LocURI></Source>\n' % gid
-    xml += '     <Data>\n'
-    xml += xml_string
-    xml += '     </Data>\n'
+    xml_list = []
+    xml = xml_list.append
+    xml('   <Add>\n')
+    xml('    <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('    <Meta><Type>%s</Type></Meta>\n' % object.portal_type)
+    xml('    <Item>\n')
+    xml('     <Source>\n')
+    xml('      <LocURI>%s</LocURI>\n' % gid)
+    xml('     </Source>\n')
+    xml('     <Data>\n')
+    xml(xml_string)
+    xml('     </Data>\n')
     if more_data == 1:
-      xml += '     <MoreData/>\n'
-    xml += '    </Item>\n'
-    xml += '   </Add>\n'
-    return xml
+      xml('     <MoreData/>\n')
+    xml('    </Item>\n')
+    xml('   </Add>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
 
   def deleteXMLObject(self, cmd_id=0, object_gid=None, xml_object=''):
     """
-      Add an object with the SyncML protocol
-    """
-    xml = ""
-    xml += '   <Delete>\n'
-    xml += '    <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '    <Item>\n'
-    xml += '     <Source><LocURI>%s</LocURI></Source>\n' % object_gid
-    xml += '     <Data>\n'
-    xml += '     </Data>\n'
-    xml += '    </Item>\n'
-    xml += '   </Delete>\n'
-    return xml
+      Delete an object with the SyncML protocol
+    """
+    xml_list = []
+    xml = xml_list.append
+    xml('   <Delete>\n')
+    xml('    <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('    <Item>\n')
+    xml('     <Source>\n')
+    xml('      <LocURI>%s</LocURI>\n' % object_gid)
+    xml('     </Source>\n')
+    xml('     <Data>\n')
+    xml('     </Data>\n')
+    xml('    </Item>\n')
+    xml('   </Delete>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
 
   def replaceXMLObject(self, cmd_id=0, object=None, xml_string=None,
                        more_data=0,gid=None):
     """
-      Add an object with the SyncML protocol
-    """
-    xml = ""
-    xml += '   <Replace>\n'
-    xml += '    <CmdID>%s</CmdID>\n' % cmd_id
-    xml += '    <Meta><Type>%s</Type></Meta>\n' % object.portal_type
-    xml += '    <Item>\n'
-    xml += '     <Source><LocURI>%s</LocURI></Source>\n' % str(gid)
-    xml += '     <Data>\n'
-    xml += xml_string
-    xml += '     </Data>\n'
+      Replace an object with the SyncML protocol
+    """
+    xml_list = []
+    xml = xml_list.append
+    xml('   <Replace>\n')
+    xml('    <CmdID>%s</CmdID>\n' % cmd_id)
+    xml('    <Meta><Type>%s</Type></Meta>\n' % object.portal_type)
+    xml('    <Item>\n')
+    xml('     <Source>\n')
+    xml('      <LocURI>%s</LocURI>\n' % str(gid))
+    xml('     </Source>\n')
+    xml('     <Data>\n')
+    xml(xml_string)
+    xml('     </Data>\n')
     if more_data == 1:
-      xml += '     <MoreData/>\n'
-    xml += '    </Item>\n'
-    xml += '   </Replace>\n'
-    return xml
+      xml('     <MoreData/>\n')
+    xml('    </Item>\n')
+    xml('   </Replace>\n')
+    xml_a = ''.join(xml_list)
+    return xml_a
 
   def getXupdateObject(self, object=None, xml_mapping=None, old_xml=None):
     """
@@ -206,7 +264,8 @@
     file2 = open('/tmp/%s'% old_filename,'w')
     file2.write(old_xml)
     file2.close()
-    xupdate = commands.getoutput('erp5diff /tmp/%s /tmp/%s' % (old_filename,new_filename))
+    xupdate = commands.getoutput('erp5diff /tmp/%s /tmp/%s' % 
+        (old_filename,new_filename))
     xupdate = xupdate[xupdate.find('<xupdate:modifications'):]
     commands.getstatusoutput('rm -f /tmp/%s' % old_filename)
     commands.getstatusoutput('rm -f /tmp/%s' % new_filename)
@@ -240,6 +299,38 @@
               if subnode2.nodeName == 'SessionID':
                 session_id = int(subnode2.childNodes[0].data)
     return session_id
+    
+    
+  def getMessageId(self, xml):
+    """
+    We will retrieve the message id of the message
+    """
+    message_id = 0
+    for subnode in self.getElementNodeList(xml):
+      if subnode.nodeName == 'SyncML':
+        for subnode1 in self.getElementNodeList(subnode):
+          if subnode1.nodeName == 'SyncHdr':
+            for subnode2 in self.getElementNodeList(subnode1):
+              if subnode2.nodeName == 'MsgID':
+                message_id = int(subnode2.childNodes[0].data)
+    return message_id
+
+  def getTarget(self, xml):
+    """
+    return the target in the SyncHdr section
+    """
+    url = ''
+    for subnode in self.getElementNodeList(xml):
+      if subnode.nodeName == 'SyncML':
+        for subnode1 in self.getElementNodeList(subnode):
+          if subnode1.nodeName == 'SyncHdr':
+            for subnode2 in self.getElementNodeList(subnode1):
+              if subnode2.nodeName == 'Target':
+                for subnode3 in self.getElementNodeList(subnode2):
+                  if subnode3.nodeName == 'LocURI':
+                    url = subnode3.childNodes[0].data
+    return url
+
 
   def getAlertLastAnchor(self, xml_stream):
     """
@@ -251,18 +342,23 @@
     # Get informations from the body
     client_body = first_node.childNodes[3]
     for subnode in client_body.childNodes:
-      if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Alert":
+      if subnode.nodeType == subnode.ELEMENT_NODE and \
+          subnode.nodeName == "Alert":
         for subnode2 in subnode.childNodes:
-          if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == "Item":
+          if subnode2.nodeType == subnode2.ELEMENT_NODE and \
+              subnode2.nodeName == "Item":
             for subnode3 in subnode2.childNodes:
-              if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == "Meta":
-               for subnode4 in subnode3.childNodes:
-                  if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == "Anchor":
+              if subnode3.nodeType == subnode3.ELEMENT_NODE and \
+                  subnode3.nodeName == "Meta":
+                for subnode4 in subnode3.childNodes:
+                  if subnode4.nodeType == subnode4.ELEMENT_NODE and \
+                      subnode4.nodeName == "Anchor":
                     for subnode5 in subnode4.childNodes:
                       # Get the last time we had a synchronization
-                     if subnode5.nodeType == subnode5.ELEMENT_NODE and subnode5.nodeName == "Last":
+                     if subnode5.nodeType == subnode5.ELEMENT_NODE and \
+                         subnode5.nodeName == "Last":
                         last_anchor = subnode5.childNodes[0].data
-                        return last_anchor
+    return last_anchor
 
   def getAlertNextAnchor(self, xml_stream):
     """
@@ -278,16 +374,21 @@
     if client_body.nodeName != "SyncBody":
       print "This is not a SyncML Body"
     for subnode in client_body.childNodes:
-      if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Alert":
+      if subnode.nodeType == subnode.ELEMENT_NODE and \
+          subnode.nodeName == "Alert":
         for subnode2 in subnode.childNodes:
-          if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == "Item":
+          if subnode2.nodeType == subnode2.ELEMENT_NODE and \
+              subnode2.nodeName == "Item":
             for subnode3 in subnode2.childNodes:
-              if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == "Meta":
+              if subnode3.nodeType == subnode3.ELEMENT_NODE and \
+                  subnode3.nodeName == "Meta":
                 for subnode4 in subnode3.childNodes:
-                 if subnode4.nodeType == subnode4.ELEMENT_NODE and subnode4.nodeName == "Anchor":
+                 if subnode4.nodeType == subnode4.ELEMENT_NODE and \
+                     subnode4.nodeName == "Anchor":
                     for subnode5 in subnode4.childNodes:
                       # Get the last time we had a synchronization
-                      if subnode5.nodeType == subnode5.ELEMENT_NODE and subnode5.nodeName == "Next":
+                      if subnode5.nodeType == subnode5.ELEMENT_NODE and \
+                          subnode5.nodeName == "Next":
                         next_anchor = subnode5.childNodes[0].data
                         return next_anchor
 
@@ -298,7 +399,8 @@
     # Get informations from the body
     if xml.nodeName=='Status':
       for subnode in xml.childNodes:
-        if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'TargetRef':
+        if subnode.nodeType == subnode.ELEMENT_NODE and \
+            subnode.nodeName == 'TargetRef':
           return subnode.childNodes[0].data
     return None
 
@@ -309,9 +411,31 @@
     # Get informations from the body
     if xml.nodeName=='Status':
       for subnode in xml.childNodes:
-        if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Data':
+        if subnode.nodeType == subnode.ELEMENT_NODE and \
+            subnode.nodeName == 'Data':
           return int(subnode.childNodes[0].data)
     return None
+
+
+  #def getStatusCode(self, xml):
+  #  """
+  #    Return the value of the alert code inside the xml_stream
+  #  """
+  #  # Get informations from the body
+  #  first_node = xml.childNodes[0]
+  #  if first_node.nodeName != "SyncML":
+  #    print "This is not a SyncML message"
+  #
+  #  client_body = first_node.childNodes[3]
+  #  if client_body.nodeName != "SyncBody":
+  #    print "This is not a SyncML Body"
+  #  
+  #  for subnode in client_body.childNodes:
+  #    if subnode.nodeName=='Status':
+  #      for subnode2 in subnode.childNodes:
+  #        if subnode2.nodeType == subnode.ELEMENT_NODE and subnode2.nodeName == 'Data':
+  #         return int(subnode2.childNodes[0].data)
+  #  return None
 
   def getStatusCommand(self, xml):
     """
@@ -333,6 +457,7 @@
     client_body = first_node.childNodes[3]
     if client_body.nodeName != "SyncBody":
       LOG('XMLSyncUtils.getAlertCode',0,"This is not a SyncML Body")
+      raise ValueError, "Sorry, This is not a SyncML Body"
     alert = 0
     for subnode in client_body.childNodes:
       if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName=='Alert':
@@ -341,9 +466,25 @@
             return int(subnode1.childNodes[0].data)
     return None
 
+  def checkCred(self, xml_stream):
+    """
+      Check if there's a Cred section in the xml_stream
+    """
+    first_node = xml_stream.childNodes[0]
+    # Get informations from the header
+    xml_header = first_node.childNodes[1]
+    if xml_header.nodeName != "SyncHdr":
+      LOG('PubSyncModif',0,'This is not a SyncML Header')
+      raise ValueError, "Sorry, This is not a SyncML Header"
+    cred = 0
+    for subnode in xml_header.childNodes:
+      if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Cred":
+        cred=1
+    return cred
+
   def checkAlert(self, xml_stream):
     """
-      Check if there's an Alert section in the xml_xtream
+      Check if there's an Alert section in the xml_stream
     """
     first_node = xml_stream.childNodes[0]
     client_body = first_node.childNodes[3]
@@ -363,6 +504,7 @@
     client_body = first_node.childNodes[3]
     if client_body.nodeName != "SyncBody":
       LOG('checkSync',0,"This is not a SyncML Body")
+      raise ValueError, "Sorry, This is not a SyncML Body"
     for subnode in client_body.childNodes:
       if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Sync":
         return 1
@@ -420,6 +562,7 @@
     client_body = first_node.childNodes[3]
     if client_body.nodeName != "SyncBody":
       LOG('getNextSyncBodyStatus',0,"This is not a SyncML Body")
+      raise ValueError, "Sorry, This is not a SyncML Body"
     next_status = None
     found = None
     for subnode in client_body.childNodes:
@@ -463,7 +606,7 @@
                 #  data = subnode3.data
                 #  data = data[data.find('<!--')+4:data.rfind('-->')]
                 xml = subnode3.data
-                if type(xml) is type(u'a'):
+		if isinstance(xml, unicode):
                   xml = xml.encode('utf-8')
                 return xml
 
@@ -936,6 +1079,7 @@
     xml_header = first_node.childNodes[1]
     if xml_header.nodeName != "SyncHdr":
       LOG('PubSyncModif',0,'This is not a SyncML Header')
+      raise ValueError, "Sorry, This is not a SyncML Header"
       return
 
     subscriber = domain # If we are the client, this is fine
@@ -944,14 +1088,17 @@
       simulate = 1
       for subnode in xml_header.childNodes:
         if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Source":
-          subscription_url = str(subnode.childNodes[0].data)
+	  for subnode2 in subnode.childNodes:
+	    if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'LocURI':
+	      subscription_url = str(subnode2.childNodes[0].data)
       subscriber = domain.getSubscriber(subscription_url)
 
     # We have to check if this message was not already, this can be dangerous
     # to update two times the same object
-    session_id = self.getSessionId(remote_xml)
-    correct_session = subscriber.checkCorrectRemoteSessionId(session_id)
-    if not correct_session: # We need to send again the message
+    message_id = self.getMessageId(remote_xml)
+    correct_message = subscriber.checkCorrectRemoteMessageId(message_id)
+    if not correct_message: # We need to send again the message
+      LOG('SyncModif, no correct message:',0,"sending again...")
       last_xml = subscriber.getLastSentMessage()
       if last_xml != '':
         has_response = 1
@@ -974,7 +1121,7 @@
     conduit_name = subscriber.getConduit()
     conduit_module = __import__('.'.join([Conduit.__name__, conduit_name]), globals(), locals(), [''])
     conduit = getattr(conduit_module, conduit_name)()
-    LOG('SyncModif, subscriber: ',0,subscriber)
+    LOG('SyncModif, subscriber:',0,subscriber)
     # Then apply the list of actions
     (xml_confirmation,has_next_action,cmd_id) = self.applyActionList(cmd_id=cmd_id,
                                          domain=domain,
@@ -984,16 +1131,17 @@
                                          conduit=conduit, simulate=simulate)
     LOG('SyncModif, has_next_action:',0,has_next_action)
 
-    xml = ""
-    xml += '<SyncML>\n'
-
+    xml_list = []
+    xml = xml_list.append
+    xml('<SyncML>\n')
+    
     # syncml header
     if domain.domain_type == self.PUB:
-      xml += self.SyncMLHeader(subscriber.getSessionId(), "1",
-          subscriber.getSubscriptionUrl(), domain.getPublicationUrl())
+      xml(self.SyncMLHeader(subscriber.getSessionId(), subscriber.incrementMessageId(),
+          subscriber.getSubscriptionUrl(), domain.getPublicationUrl()))
     elif domain.domain_type == self.SUB:
-      xml += self.SyncMLHeader(domain.getSessionId(), "1",
-        domain.getPublicationUrl(), domain.getSubscriptionUrl())
+      xml(self.SyncMLHeader(domain.getSessionId(), domain.incrementMessageId(),
+        domain.getPublicationUrl(), domain.getSubscriptionUrl()))
 
 
     cmd_id += 1
@@ -1010,47 +1158,51 @@
                                        conduit=conduit)
 
     # syncml body
-    xml += ' <SyncBody>\n'
+    xml(' <SyncBody>\n')
     destination_url = ''
     if domain.domain_type == self.PUB:
       subscriber.NewAnchor()
       destination_url = domain.getPublicationUrl()
-      xml += self.SyncMLStatus(cmd_id, subscriber.getSubscriptionUrl(),
+      xml(self.SyncMLStatus(cmd_id, subscriber.getSubscriptionUrl(),
                                domain.getDestinationPath(),
                                subscriber.getSynchronizationType(),
-                               subscriber.getNextAnchor())
+                               subscriber.getNextAnchor()))
     elif domain.domain_type == self.SUB:
       destination_url = domain.getPublicationUrl()
-      xml += self.SyncMLStatus(cmd_id, domain.getPublicationUrl(),
+      xml(self.SyncMLStatus(cmd_id, domain.getPublicationUrl(),
                                subscriber.getDestinationPath(),
                                subscriber.getSynchronizationType(),
-                               subscriber.getNextAnchor())
+                               subscriber.getNextAnchor()))
     # alert message if we want more data
     if destination_waiting_more_data == 1:
-      xml += self.SyncMLAlert(cmd_id, self.WAITING_DATA,
+      xml(self.SyncMLAlert(cmd_id, self.WAITING_DATA,
                               destination_url,
                               domain.getDestinationPath(),
-                              subscriber.getLastAnchor(), subscriber.getNextAnchor())
+                              subscriber.getLastAnchor(), 
+                              subscriber.getNextAnchor()))
     # Now we should send confirmations
-    xml += xml_confirmation
+    xml(xml_confirmation)
     if syncml_data != '':
-      xml += '  <Sync>\n'
-      xml += syncml_data
-      xml += '  </Sync>\n'
-    xml += '  <Final/>\n'
-    xml += ' </SyncBody>\n'
-    xml += '</SyncML>\n'
+      xml('  <Sync>\n')
+      xml(syncml_data)
+      xml('  </Sync>\n')
+    xml('  <Final/>\n')
+    xml(' </SyncBody>\n')
+    xml('</SyncML>\n')
+    xml_a = ''.join(xml_list)
     if domain.domain_type == self.PUB: # We always reply
-      subscriber.setLastSentMessage(xml)
-      self.sendResponse(from_url=domain.publication_url, to_url=subscriber.subscription_url,
-                sync_id=domain.getTitle(), xml=xml,domain=domain)
+      subscriber.setLastSentMessage(xml_a)
+      self.sendResponse(from_url=domain.publication_url, 
+          to_url=subscriber.subscription_url, sync_id=domain.getTitle(), 
+          xml=xml_a,domain=domain)
       has_response = 1
     elif domain.domain_type == self.SUB:
       if self.checkAlert(remote_xml) or \
          (xml_confirmation,syncml_data)!=('','') or \
           has_status_list:
-        subscriber.setLastSentMessage(xml)
-        self.sendResponse(from_url=domain.subscription_url, to_url=domain.publication_url,
-            sync_id=domain.getTitle(), xml=xml,domain=domain)
+        subscriber.setLastSentMessage(xml_a)
+        self.sendResponse(from_url=domain.subscription_url, 
+            to_url=domain.publication_url, sync_id=domain.getTitle(), 
+            xml=xml_a,domain=domain)
         has_response = 1
-    return {'has_response':has_response,'xml':xml}
+    return {'has_response':has_response,'xml':xml_a}




More information about the Erp5-report mailing list