From c3f5fd8fb410fc4eaa6209c339624de3d19d450e Mon Sep 17 00:00:00 2001 From: Sebastien Robin <seb@nexedi.com> Date: Mon, 14 May 2007 15:23:07 +0000 Subject: [PATCH] revert previous change until we have a nice rpm git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14482 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5SyncML/Conduit/ERP5Conduit.py | 93 ++--- .../ERP5SyncML/PublicationSynchronization.py | 5 +- .../ERP5SyncML/SubscriptionSynchronization.py | 6 +- product/ERP5SyncML/SynchronizationTool.py | 6 +- product/ERP5SyncML/XMLSyncUtils.py | 370 ++++++++++++------ 5 files changed, 289 insertions(+), 191 deletions(-) diff --git a/product/ERP5SyncML/Conduit/ERP5Conduit.py b/product/ERP5SyncML/Conduit/ERP5Conduit.py index 24cc80a2d1..3f52fcabdc 100644 --- a/product/ERP5SyncML/Conduit/ERP5Conduit.py +++ b/product/ERP5SyncML/Conduit/ERP5Conduit.py @@ -33,7 +33,8 @@ from Products.CMFCore.utils import getToolByName from Products.ERP5SyncML.XupdateUtils import XupdateUtils from Products.ERP5Type.Utils import convertToUpperCase from Products.ERP5Type.Accessor.TypeDefinition import list_types -from Ft.Xml import Parse +from xml.dom.ext.reader.Sax2 import FromXml +from xml.dom.minidom import parse, parseString from DateTime.DateTime import DateTime from email.MIMEBase import MIMEBase from email import Encoders @@ -43,12 +44,10 @@ from Products.ERP5Type import Permissions from Globals import PersistentMapping import pickle import string +from xml.dom.ext import PrettyPrint from cStringIO import StringIO from xml.sax.saxutils import escape, unescape import re, copy -import cStringIO -from Ft.Xml.Domlette import Print, PrettyPrint - from zLOG import LOG @@ -133,8 +132,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return {'conflict_list':conflict_list, 'object':sub_object} LOG('addNode',0,'xml_reconstitued: %s' % str(xml)) # In the case where this new node is a object to add - if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and \ - self.getSubObjectDepth(xml)==0: + if xml.nodeName in self.XUPDATE_INSERT_OR_ADD and self.getSubObjectDepth(xml)==0: if self.isHistoryAdd(xml)!=-1: # bad hack XXX to be removed for element in self.getXupdateElementList(xml): xml = self.getElementFromXupdate(element) @@ -162,8 +160,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): portal_type = self.getObjectType(xml) elif xml.nodeName in self.XUPDATE_INSERT_OR_ADD: # Deprecated ??? portal_type = self.getXupdateObjectType(xml) # Deprecated ??? - sub_object = self.constructContent(object, object_id, docid, - portal_type) + sub_object = self.constructContent(object, object_id, docid, portal_type) self.newObject( object=sub_object, xml=xml, @@ -277,9 +274,9 @@ class ERP5Conduit(XMLSyncUtilsMixin): LOG('updateNode, force: ',0,force) # we have an xupdate xml if xml.nodeName == 'xupdate:modifications': - conflict_list += self.applyXupdate(object=object, xupdate=xml, - conduit=self,previous_xml=previous_xml, force=force, - simulate=simulate, **kw) + conflict_list += self.applyXupdate(object=object,xupdate=xml,conduit=self, + previous_xml=previous_xml, force=force, simulate=simulate, + **kw) # we may have only the part of an xupdate else: args = {} @@ -345,8 +342,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): # - current_data : the data actually on this box isConflict = 0 if (previous_xml is not None) and (not force): # if no previous_xml, no conflict - old_data = self.getObjectProperty(keyword, previous_xml, - data_type=data_type) + old_data = self.getObjectProperty(keyword,previous_xml,data_type=data_type) #current_data = object.getProperty(keyword) current_data = self.getProperty(object, keyword) LOG('updateNode',0,'Conflict data: %s' % str(data)) @@ -387,7 +383,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): if keyword == 'object': # This is the case where we have to call addNode LOG('updateNode',0,'we will add sub-object') - conflict_list += self.addNode(xml=xml, object=object, force=force, simulate=simulate, **kw)['conflict_list'] + conflict_list += self.addNode(xml=xml,object=object,force=force, + simulate=simulate, **kw)['conflict_list'] elif keyword == self.history_tag and not simulate: # This is the case where we have to call addNode LOG('updateNode',0,'we will add history') @@ -400,8 +397,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): #roles = self.convertXmlValue(data,data_type='tokens') #object.manage_setLocalRoles(user,roles) xml = self.getElementFromXupdate(xml) - conflict_list += self.addNode(xml=xml, object=object, force=force, - simulate=simulate,**kw)['conflict_list'] + conflict_list += self.addNode(xml=xml,object=object,force=force, + simulate=simulate,**kw)['conflict_list'] elif self.isSubObjectModification(xml): # We should find the object corresponding to # this update, so we have to look in the previous_xml @@ -424,8 +421,8 @@ class ERP5Conduit(XMLSyncUtilsMixin): sub_xml = self.getSubObjectXupdate(xml) LOG('updateNode',0,'sub_xml: %s' % str(sub_xml)) # Then do the udpate - conflict_list += self.updateNode(xml=sub_xml, object=sub_object, force=force, - previous_xml=sub_previous_xml, simulate=simulate, **kw) + conflict_list += self.updateNode(xml=sub_xml,object=sub_object, force=force, + previous_xml=sub_previous_xml,simulate=simulate, **kw) elif previous_xml is None and xml is not None and sub_object_id is not None: sub_object = None try: @@ -441,8 +438,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): **kw) return conflict_list - security.declareProtected(Permissions.AccessContentsInformation, - 'getFormatedArgs') + security.declareProtected(Permissions.AccessContentsInformation,'getFormatedArgs') def getFormatedArgs(self, args=None): """ This lookd inside the args dictionnary and then @@ -488,21 +484,19 @@ class ERP5Conduit(XMLSyncUtilsMixin): return 0 return 1 - security.declareProtected(Permissions.AccessContentsInformation, - 'getSubObjectXupdate') + security.declareProtected(Permissions.AccessContentsInformation,'getSubObjectXupdate') def getSubObjectXupdate(self, xml): """ This will change the xml in order to change the update from the object to the subobject """ - xml_copy = xml.cloneNode(True) #make a deepcopy of the node xml - for subnode in self.getAttributeNodeList(xml_copy): + xml = copy.deepcopy(xml) + for subnode in self.getAttributeNodeList(xml): if subnode.nodeName=='select': subnode.nodeValue = self.getSubObjectSelect(subnode.nodeValue) - return xml_copy + return xml - security.declareProtected(Permissions.AccessContentsInformation, - 'isHistoryAdd') + security.declareProtected(Permissions.AccessContentsInformation,'isHistoryAdd') def isHistoryAdd(self, xml): bad_list = (self.history_exp,) for subnode in self.getAttributeNodeList(xml): @@ -516,8 +510,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return -1 return 0 - security.declareProtected(Permissions.AccessContentsInformation, - 'isSubObjectModification') + security.declareProtected(Permissions.AccessContentsInformation,'isSubObjectModification') def isSubObjectModification(self, xml): """ Check if it is a modification from an subobject @@ -531,8 +524,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return 1 return 0 - security.declareProtected(Permissions.AccessContentsInformation, - 'getSubObjectDepth') + security.declareProtected(Permissions.AccessContentsInformation,'getSubObjectDepth') def getSubObjectDepth(self, xml): """ Give the Depth of a subobject modification @@ -563,8 +555,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return (1 - i) return 0 - security.declareProtected(Permissions.AccessContentsInformation, - 'getSubObjectSelect') + security.declareProtected(Permissions.AccessContentsInformation,'getSubObjectSelect') def getSubObjectSelect(self, select): """ Return a string wich is the selection for the subobject @@ -580,8 +571,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): select = new_value return select - security.declareProtected(Permissions.AccessContentsInformation, - 'getSubObjectId') + security.declareProtected(Permissions.AccessContentsInformation,'getSubObjectId') def getSubObjectId(self, xml): """ Return the id of the subobject in an xupdate modification @@ -597,8 +587,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return object_id return object_id - security.declareProtected(Permissions.AccessContentsInformation, - 'getHistoryIdFromSelect') + security.declareProtected(Permissions.AccessContentsInformation,'getHistoryIdFromSelect') def getHistoryIdFromSelect(self, xml): """ Return the id of the subobject in an xupdate modification @@ -615,8 +604,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): return object_id return object_id - security.declareProtected(Permissions.AccessContentsInformation, - 'getSubObjectXml') + security.declareProtected(Permissions.AccessContentsInformation,'getSubObjectXml') def getSubObjectXml(self, object_id, xml): """ Return the xml of the subobject which as the id object_id @@ -636,7 +624,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ for attribute in self.getAttributeNodeList(xml): if attribute.nodeName == param: - data = attribute.value + data = attribute.childNodes[0].data return self.convertXmlValue(data,data_type='string') return None @@ -647,7 +635,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ for subnode in self.getElementNodeList(xml): if subnode.nodeName == 'docid': - data = subnode.childNodes[0].value + data = subnode.childNodes[0].data return self.convertXmlValue(data) return None @@ -681,7 +669,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): LOG('Conduit.convertToXml xml',0,repr(xml)) if type(xml) is type(u'a'): xml = xml.encode('utf-8') - xml = Parse(xml) + xml = parseString(xml) LOG('Conduit.convertToXml not failed',0,'ok') xml = xml.childNodes[0] # Because we just created a new xml # If we have the xml from the node erp5, we just take the subnode @@ -823,8 +811,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): #PrettyPrint(xml,xml_string) #xml_string = xml_string.getvalue() #xml_string = unicode(xml_string,encoding='utf-8') - xml_string = self.nodeToString(xml) - #xml_string = xml.toxml(encoding='utf-8') + xml_string = xml.toxml(encoding='utf-8') xml_string = unicode(xml_string,encoding='utf-8') #if type(xml_string) is type (u'a'): # xml_string = xml_string.encode('utf-8') @@ -858,7 +845,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): #PrettyPrint(xml,xml_string) #xml_string = xml_string.getvalue() #xml_string = unicode(xml_string,encoding='utf-8') - xml_string = self.nodeToString(xml) + xml_string = xml.toxml(encoding='utf-8') xml_string = unicode(xml_string,encoding='utf-8') maxi = xml_string.find('>')+1 result += xml_string[maxi:xml_string.find('</%s>' % xml.nodeName)] @@ -942,7 +929,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): """ conflict_list = [] if type(xupdate) in (type('a'),type(u'a')): - xupdate = Parse(xupdate) + xupdate = parseString(xupdate) #When xupdate mix different object, (like object and his subobject) we need to treat them separatly if self.isMixedXupdate(xupdate): #return to updateNode with only one line @@ -980,7 +967,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): nb_sub = len(subnode_list) comp = 0 for subnode in subnode_list: - value = self.getAttribute(subnode, 'select') + value = subnode.getAttribute('select') if re.search(self.object_exp, value): comp += 1 if nb_sub == comp: @@ -1056,7 +1043,7 @@ class ERP5Conduit(XMLSyncUtilsMixin): if wf_id is None: # History added by xupdate wf_id = self.getHistoryIdFromSelect(xml) LOG('addNode, workflow_history id:',0,wf_id) - #LOG('addNode, workflow_history xml:',0,xml.toxml())#toxml isn't in 4Suite + LOG('addNode, workflow_history xml:',0,xml.toxml()) LOG('addNode, workflow_history xml.getElmentNodeList:',0,self.getElementNodeList(xml)) xml = self.getElementNodeList(xml)[0] LOG('addNode, workflow_history id:',0,wf_id) @@ -1165,13 +1152,3 @@ class ERP5Conduit(XMLSyncUtilsMixin): # conflict.setRemoteValue(status) # conflict_list += [conflict] # return conflict_list - - def nodeToString(self, node): - """ - return an xml string corresponding to the node - """ - buf = cStringIO.StringIO() - Print(node, stream=buf, encoding='utf-8') - xml_string = buf.getvalue() - buf.close() - return xml_string diff --git a/product/ERP5SyncML/PublicationSynchronization.py b/product/ERP5SyncML/PublicationSynchronization.py index 5b66f11a71..444d420031 100644 --- a/product/ERP5SyncML/PublicationSynchronization.py +++ b/product/ERP5SyncML/PublicationSynchronization.py @@ -29,7 +29,8 @@ import smtplib # to send emails from Publication import Publication,Subscriber from Subscription import Signature -from Ft.Xml import Parse +from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString from XMLSyncUtils import XMLSyncUtils from Conduit.ERP5Conduit import ERP5Conduit from Products.CMFCore.utils import getToolByName @@ -220,7 +221,7 @@ class PublicationSynchronization(XMLSyncUtils): if xml_client is not None: if isinstance(xml_client, str) or isinstance(xml_client, unicode): - xml_client = Parse(xml_client) + xml_client = parseString(xml_client) first_node = xml_client.childNodes[0] if first_node.nodeName != "SyncML": diff --git a/product/ERP5SyncML/SubscriptionSynchronization.py b/product/ERP5SyncML/SubscriptionSynchronization.py index fac14b4bb4..ae05fc9c99 100644 --- a/product/ERP5SyncML/SubscriptionSynchronization.py +++ b/product/ERP5SyncML/SubscriptionSynchronization.py @@ -28,7 +28,9 @@ import smtplib # to send emails from Subscription import Subscription,Signature -from Ft.Xml import Parse +from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString +from xml.dom.ext import PrettyPrint from XMLSyncUtils import XMLSyncUtils import commands from Conduit.ERP5Conduit import ERP5Conduit @@ -97,7 +99,7 @@ class SubscriptionSynchronization(XMLSyncUtils): else: xml_client = msg if isinstance(xml_client, str) or isinstance(xml_client, unicode): - xml_client = Parse(xml_client) + xml_client = parseString(xml_client) next_status = self.getNextSyncBodyStatus(xml_client, None) #LOG('readResponse, next status :',0,next_status) if next_status is not None: diff --git a/product/ERP5SyncML/SynchronizationTool.py b/product/ERP5SyncML/SynchronizationTool.py index 6960e87596..6bb230a57d 100644 --- a/product/ERP5SyncML/SynchronizationTool.py +++ b/product/ERP5SyncML/SynchronizationTool.py @@ -40,7 +40,8 @@ from Products.ERP5SyncML import Conduit from Publication import Publication,Subscriber from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Subscription import Subscription,Signature -from Ft.Xml import Parse +from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml +from xml.dom.minidom import parse, parseString from Products.ERP5Type import Permissions from PublicationSynchronization import PublicationSynchronization from SubscriptionSynchronization import SubscriptionSynchronization @@ -49,6 +50,7 @@ from AccessControl.SecurityManagement import newSecurityManager from AccessControl.SecurityManagement import noSecurityManager from AccessControl.User import UnrestrictedUser from Acquisition import aq_base +from xml.parsers.expat import ExpatError # parseString error import urllib import urllib2 import socket @@ -972,7 +974,7 @@ class SynchronizationTool( SubscriptionSynchronization, commands.getstatusoutput('rm -f /tmp/%s.gz.gpg' % filename) # Get the target and then find the corresponding publication or # Subscription - xml = Parse(text) + xml = parseString(text) #XXX this function is not very optimized and should be improved url = self.getTarget(xml) for publication in self.getPublicationList(): diff --git a/product/ERP5SyncML/XMLSyncUtils.py b/product/ERP5SyncML/XMLSyncUtils.py index 185985de6b..bad3c0ff67 100644 --- a/product/ERP5SyncML/XMLSyncUtils.py +++ b/product/ERP5SyncML/XMLSyncUtils.py @@ -29,7 +29,8 @@ import smtplib from Products.ERP5SyncML.SyncCode import SyncCode from Products.ERP5SyncML.Subscription import Signature -from Ft.Xml import Parse +from xml.dom.ext.reader.Sax2 import FromXml +from xml.dom.minidom import parse, parseString from DateTime import DateTime from cStringIO import StringIO from xml.dom.ext import PrettyPrint @@ -300,17 +301,28 @@ class XMLSyncUtilsMixin(SyncCode): We will retrieve the session id of the message """ session_id = 0 - session_id = xml.xpath('string(/SyncML/SyncHdr/SessionID)') - session_id = int(session_id) + 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 == '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 - message_id = xml.xpath('string(/SyncML/SyncHdr/MsgID)') - message_id = int(message_id) + 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): @@ -318,10 +330,18 @@ class XMLSyncUtilsMixin(SyncCode): return the target in the SyncHdr section """ url = '' - url = xml.xpath('string(/SyncML/SyncHdr/Target/LocURI)') - url = url.encode('utf-8') + 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): """ Return the value of the last anchor, in the @@ -331,8 +351,23 @@ class XMLSyncUtilsMixin(SyncCode): # Get informations from the body client_body = first_node.childNodes[3] - last_anchor = client_body.xpath('string(/Alert/Item/Meta/Anchor/Last)') - last_anchor = last_anchor.encode('utf-8') + for subnode in client_body.childNodes: + 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": + 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": + for subnode5 in subnode4.childNodes: + # Get the last time we had a synchronization + if subnode5.nodeType == subnode5.ELEMENT_NODE and \ + subnode5.nodeName == "Last": + last_anchor = subnode5.childNodes[0].data return last_anchor def getAlertNextAnchor(self, xml_stream): @@ -346,33 +381,61 @@ class XMLSyncUtilsMixin(SyncCode): # Get informations from the body client_body = first_node.childNodes[3] - next_anchor = client_body.xpath('string(/Alert/Item/Meta/Anchor/Next)') - next_anchor = next_anchor.encode('utf-8') - return next_anchor + 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": + for subnode2 in subnode.childNodes: + 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": + for subnode5 in subnode4.childNodes: + # Get the last time we had a synchronization + if subnode5.nodeType == subnode5.ELEMENT_NODE and \ + subnode5.nodeName == "Next": + next_anchor = subnode5.childNodes[0].data + return next_anchor def getStatusTarget(self, xml): """ Return the value of the alert code inside the xml_stream """ - return xml.xpath('string(TargetRef)') + # Get informations from the body + if xml.nodeName=='Status': + for subnode in xml.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and \ + subnode.nodeName == 'TargetRef': + return subnode.childNodes[0].data + return None def getStatusCode(self, xml): """ Return the value of the alert code inside the xml_stream """ - status_code = xml.xpath('string(Data)') - if status_code not in ('', None, []): - return int(status_code) + # Get informations from the body + if xml.nodeName=='Status': + for subnode in xml.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and \ + subnode.nodeName == 'Data': + return int(subnode.childNodes[0].data) return None def getStatusCommand(self, xml): """ Return the value of the command inside the xml_stream """ + # Get informations from the body if xml.nodeName=='Status': - return xml.xpath('string(//Status/Cmd)') - else: - return None + for subnode in xml.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Cmd': + return subnode.childNodes[0].data + return None def getCred(self, xml): """ @@ -381,61 +444,111 @@ class XMLSyncUtilsMixin(SyncCode): format='' type='' data='' + first_node = xml.childNodes[0] - format = first_node.xpath('string(/SyncML/SyncHdr/Cred/Meta/Format)') - type = first_node.xpath('string(/SyncML/SyncHdr/Cred/Meta/Type)') - data = first_node.xpath('string(/SyncML/SyncHdr/Cred/Data)') + if first_node.nodeName != "SyncML": + print "This is not a SyncML message" + # 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" - format = format.encode('utf-8') - type = type.encode('utf-8') - data = data.encode('utf-8') + for subnode in xml_header.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName=='Cred': + for subnode2 in subnode.childNodes: + if subnode2.nodeType == subnode2.ELEMENT_NODE and \ + subnode2.nodeName == 'Meta': + for subnode3 in subnode2.childNodes: + if subnode3.nodeType == subnode3.ELEMENT_NODE and \ + subnode3.nodeName == 'Format': + if len(subnode3.childNodes) > 0: + format=subnode3.childNodes[0].data + if subnode3.nodeType == subnode3.ELEMENT_NODE and \ + subnode3.nodeName == 'Type': + if len(subnode3.childNodes) > 0: + type=subnode3.childNodes[0].data + if subnode2.nodeType == subnode2.ELEMENT_NODE and \ + subnode2.nodeName == 'Data': + if len(subnode2.childNodes) > 0: + data=subnode2.childNodes[0].data return (format, type, data) def getAlertCode(self, xml_stream): """ Return the value of the alert code inside the full syncml message """ - alert_code = xml_stream.xpath('string(SyncML/SyncBody/Alert/Data)') - if alert_code not in (None, ''): - return int(alert_code) - else: - return None + # Get informations from the body + first_node = xml_stream.childNodes[0] + 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': + for subnode1 in subnode.childNodes: + if subnode1.nodeType == subnode1.ELEMENT_NODE and subnode1.nodeName == 'Data': + return int(subnode1.childNodes[0].data) + return None def checkCred(self, xml_stream): """ Check if there's a Cred section in the xml_stream """ - cred = False - if xml_stream.xpath('string(SyncML/SyncHdr/Cred)') not in ('', None, []): - cred = True + 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_stream """ - alert = False - if xml_stream.xpath('string(SyncML/SyncBody/Alert)') not in ('', None, []): - alert = True + first_node = xml_stream.childNodes[0] + client_body = first_node.childNodes[3] + if client_body.nodeName != "SyncBody": + print "This is not a SyncML Body" + alert = 0 + for subnode in client_body.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Alert": + alert = 1 return alert def checkSync(self, xml_stream): """ Check if there's an Sync section in the xml_xtream """ - sync = False - if xml_stream.xpath('string(SyncML/SyncBody/Sync)') not in ('', None, []): - sync = True - return sync + first_node = xml_stream.childNodes[0] + 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 + return 0 def CheckStatus(self, xml_stream): """ Check if there's a Status section in the xml_xtream """ - status = False - if xml_stream.xpath('string(SyncML/SyncBody/Status)') not in ('', None, []): - status = True + first_node = xml_stream.childNodes[0] + client_body = first_node.childNodes[3] + if client_body.nodeName != "SyncBody": + print "This is not a SyncML Body" + status = None + for subnode in client_body.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Status": + status = "1" return status def getNextSyncAction(self, xml_stream, last_action): @@ -450,22 +563,18 @@ class XMLSyncUtilsMixin(SyncCode): print "This is not a SyncML Body" next_action = None for subnode in client_body.childNodes: - if subnode.nodeType == subnode.ELEMENT_NODE and \ - subnode.nodeName == "Sync": + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Sync": # if we didn't use this method before if last_action == None and len(subnode.childNodes) > 1: next_action = subnode.childNodes[1] else: found = None for subnode2 in subnode.childNodes: - if subnode2.nodeType == subnode.ELEMENT_NODE and \ - subnode2 != last_action and found is None: + if subnode2.nodeType == subnode.ELEMENT_NODE and subnode2 != last_action and found is None: pass - elif subnode2.nodeType == subnode.ELEMENT_NODE and \ - subnode2 == last_action and found is None: + elif subnode2.nodeType == subnode.ELEMENT_NODE and subnode2 == last_action and found is None: found = 1 - elif subnode2.nodeType == subnode.ELEMENT_NODE and \ - found is not None: + elif subnode2.nodeType == subnode.ELEMENT_NODE and found is not None: next_action = subnode2 break return next_action @@ -484,8 +593,7 @@ class XMLSyncUtilsMixin(SyncCode): next_status = None found = None for subnode in client_body.childNodes: - if subnode.nodeType == subnode.ELEMENT_NODE and \ - subnode.nodeName == "Status": + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == "Status": # if we didn't use this method before if last_status == None: next_status = subnode @@ -501,11 +609,9 @@ class XMLSyncUtilsMixin(SyncCode): Return the node starting with <object....> of the action """ for subnode in action.childNodes: - if subnode.nodeType == subnode.ELEMENT_NODE and \ - subnode.nodeName == 'Item': + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item': for subnode2 in subnode.childNodes: - if subnode2.nodeType == subnode2.ELEMENT_NODE and \ - subnode2.nodeName == 'Data': + if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Data': for subnode3 in subnode2.childNodes: #if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'object': if subnode3.nodeType == subnode3.ELEMENT_NODE: @@ -516,11 +622,9 @@ class XMLSyncUtilsMixin(SyncCode): Return the node starting with <object....> of the action """ for subnode in action.childNodes: - if subnode.nodeType == subnode.ELEMENT_NODE and \ - subnode.nodeName == 'Item': + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item': for subnode2 in subnode.childNodes: - if subnode2.nodeType == subnode2.ELEMENT_NODE and \ - subnode2.nodeName == 'Data': + if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Data': for subnode3 in subnode2.childNodes: #if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'object': if subnode3.nodeType == subnode3.COMMENT_NODE: @@ -535,40 +639,60 @@ class XMLSyncUtilsMixin(SyncCode): return None + + def getAttributeNodeList(self, node): + """ + Return attributesNodes that are ElementNode XXX may be not needed at all + """ + subnode_list = [] + for subnode in node.attributes: + if subnode.nodeType == subnode.ATTRIBUTE_NODE: + subnode_list += [subnode] + return subnode_list + def getActionId(self, action): """ Return the rid of the object described by the action """ for subnode in action.childNodes: - if subnode.nodeType == subnode.ELEMENT_NODE and \ - subnode.nodeName == 'Item': + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item': for subnode2 in subnode.childNodes: - if subnode2.nodeType == subnode2.ELEMENT_NODE and \ - subnode2.nodeName == 'Source': + if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Source': for subnode3 in subnode2.childNodes: - if subnode3.nodeType == subnode3.ELEMENT_NODE and \ - subnode3.nodeName == 'LocURI': + if subnode3.nodeType == subnode3.ELEMENT_NODE and subnode3.nodeName == 'LocURI': return str(subnode3.childNodes[0].data) def checkActionMoreData(self, action): """ Return the rid of the object described by the action """ - if action.xpath('Item/MoreData'): - return True - return False + for subnode in action.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Item': + for subnode2 in subnode.childNodes: + if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'MoreData': + return 1 + return 0 def getActionType(self, action): """ Return the type of the object described by the action """ - return action.xpath('string(Meta/Type)') + for subnode in action.childNodes: + if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Meta': + for subnode2 in subnode.childNodes: + if subnode2.nodeType == subnode2.ELEMENT_NODE and subnode2.nodeName == 'Type': + return str(subnode2.childNodes[0].data) def getElementNodeList(self, node): """ Return childNodes that are ElementNode """ - return node.xpath('*') + #return node.getElementsByTagName('*') + subnode_list = [] + for subnode in node.childNodes or []: + if subnode.nodeType == subnode.ELEMENT_NODE: + subnode_list += [subnode] + return subnode_list def getTextNodeList(self, node): """ @@ -579,12 +703,16 @@ class XMLSyncUtilsMixin(SyncCode): if subnode.nodeType == subnode.TEXT_NODE: subnode_list += [subnode] return subnode_list - + def getAttributeNodeList(self, node): """ Return childNodes that are ElementNode """ - return node.xpath('@*') + attribute_list = [] + for subnode in node.attributes.values() or []: + if subnode.nodeType == subnode.ATTRIBUTE_NODE: + attribute_list += [subnode] + return attribute_list def getSyncMLData(self, domain=None,remote_xml=None,cmd_id=0, subscriber=None,destination_path=None, @@ -637,8 +765,7 @@ class XMLSyncUtilsMixin(SyncCode): #if gid_generator is not None: # object_gid = gid_generator() force = 0 - if syncml_data.count('\n') < self.MAX_LINES and not \ - object.id.startswith('.'): # If not we have to cut + if syncml_data.count('\n') < self.MAX_LINES and not object.id.startswith('.'): # If not we have to cut #LOG('getSyncMLData',0,'xml_mapping: %s' % str(domain.xml_mapping)) #LOG('getSyncMLData',0,'code: %s' % str(self.getAlertCode(remote_xml))) #LOG('getSyncMLData',0,'gid_list: %s' % str(local_gid_list)) @@ -654,13 +781,11 @@ class XMLSyncUtilsMixin(SyncCode): # For the case it was never synchronized, we have to send everything if signature is not None and signature.getXMLMapping()==None: pass - elif signature == None or (signature.getXML() == None and \ - signature.getStatus() != self.PARTIAL) or \ - self.getAlertCode(remote_xml) == self.SLOW_SYNC: + elif signature==None or (signature.getXML()==None and signature.getStatus()!=self.PARTIAL) or \ + self.getAlertCode(remote_xml)==self.SLOW_SYNC: #LOG('PubSyncModif',0,'Current object.getPath: %s' % object.getPath()) LOG('getSyncMLData',0,'no signature for gid: %s' % object_gid) - xml_object = self.getXMLObject(object=object, - xml_mapping=domain.xml_mapping) + xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping) xml_string = xml_object signature = Signature(gid=object_gid,id=object.getId(),object=object) signature.setTempXML(xml_object) @@ -681,15 +806,14 @@ class XMLSyncUtilsMixin(SyncCode): status =self.PARTIAL signature.setAction('Add') xml_string = '<!--' + short_string + '-->' - syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object, - gid=object_gid, xml_string=xml_string, more_data=more_data) + syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object,gid=object_gid, + xml_string=xml_string, more_data=more_data) cmd_id += 1 signature.setStatus(status) subscriber.addSignature(signature) elif signature.getStatus()==self.NOT_SYNCHRONIZED \ or signature.getStatus()==self.PUB_CONFLICT_MERGE: # We don't have synchronized this object yet - xml_object = self.getXMLObject(object=object, - xml_mapping=domain.xml_mapping) + xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping) #LOG('getSyncMLData',0,'checkMD5: %s' % str(signature.checkMD5(xml_object))) #LOG('getSyncMLData',0,'getStatus: %s' % str(signature.getStatus())) if signature.getStatus()==self.PUB_CONFLICT_MERGE: @@ -718,8 +842,8 @@ class XMLSyncUtilsMixin(SyncCode): signature.setAction('Replace') xml_string = '<!--' + short_string + '-->' signature.setStatus(status) - syncml_data += self.replaceXMLObject(cmd_id=cmd_id, object=object, - gid=object_gid, xml_string=xml_string, more_data=more_data) + syncml_data += self.replaceXMLObject(cmd_id=cmd_id,object=object,gid=object_gid, + xml_string=xml_string, more_data=more_data) cmd_id += 1 signature.setTempXML(xml_object) # Now we can apply the xupdate from the subscriber @@ -727,11 +851,10 @@ class XMLSyncUtilsMixin(SyncCode): #LOG('getSyncMLData subscriber_xupdate',0,subscriber_xupdate) if subscriber_xupdate is not None: old_xml = signature.getXML() - conduit.updateNode(xml=subscriber_xupdate, object=object, - previous_xml=old_xml, force=(domain.getDomainType==self.SUB), - simulate=0) - xml_object = self.getXMLObject(object=object, - xml_mapping=domain.xml_mapping) + conduit.updateNode(xml=subscriber_xupdate, object=object, + previous_xml=old_xml,force=(domain.getDomainType==self.SUB), + simulate=0) + xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping) signature.setTempXML(xml_object) if set_synchronized: # We have to do that after this previous update # We should not have this case when we are in CONFLICT_MERGE @@ -767,11 +890,11 @@ class XMLSyncUtilsMixin(SyncCode): xml_string = '<!--' + xml_string + '-->' signature.setStatus(status) if signature.getAction()=='Replace': - syncml_data += self.replaceXMLObject(cmd_id=cmd_id, object=object, - gid=object_gid, xml_string=xml_string, more_data=more_data) + syncml_data += self.replaceXMLObject(cmd_id=cmd_id,object=object,gid=object_gid, + xml_string=xml_string, more_data=more_data) elif signature.getAction()=='Add': - syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object, - gid=object_gid, xml_string=xml_string, more_data=more_data) + syncml_data += self.addXMLObject(cmd_id=cmd_id, object=object,gid=object_gid, + xml_string=xml_string, more_data=more_data) return (syncml_data,xml_confirmation,cmd_id) def applyActionList(self, domain=None, subscriber=None,destination_path=None, @@ -795,8 +918,7 @@ class XMLSyncUtilsMixin(SyncCode): object = domain.getObjectFromGid(object_gid) if signature == None: LOG('applyActionList, signature is None',0,signature) - signature = Signature(gid=object_gid, status=self.NOT_SYNCHRONIZED, - object=object).__of__(subscriber) + signature = Signature(gid=object_gid,status=self.NOT_SYNCHRONIZED,object=object).__of__(subscriber) subscriber.addSignature(signature) force = signature.getForce() LOG('applyActionList',0,'object: %s' % repr(object)) @@ -810,7 +932,7 @@ class XMLSyncUtilsMixin(SyncCode): data_subnode = partial_data LOG('SyncModif',0,'data_subnode: %s' % data_subnode) #data_subnode = FromXml(data_subnode) - data_subnode = Parse(data_subnode) + data_subnode = parseString(data_subnode) data_subnode = data_subnode.childNodes[0] # Because we just created a new xml # document, with childNodes[0] a DocumentType and childNodes[1] the Element Node else: @@ -820,13 +942,12 @@ class XMLSyncUtilsMixin(SyncCode): if object is None: object_id = domain.generateNewIdWithGenerator(object=destination_path,gid=object_gid) #if object_id is not None: - add_data = conduit.addNode(xml=data_subnode, - object=destination_path, object_id=object_id) + add_data = conduit.addNode(xml=data_subnode, object=destination_path, + object_id=object_id) conflict_list += add_data['conflict_list'] # Retrieve directly the object from addNode object = add_data['object'] LOG('XMLSyncUtils, in ADD add_data',0,add_data) - signature.setPath(object.getPhysicalPath()) LOG('applyActionList',0,'object after add: %s' % repr(object)) else: #Object was retrieve but need to be updated without recreated @@ -891,11 +1012,11 @@ class XMLSyncUtilsMixin(SyncCode): elif next_action.nodeName == 'Delete': object_id = signature.getId() - conduit.deleteNode(xml=self.getDataSubNode(next_action), - object=destination_path, object_id=object_id) + conduit.deleteNode(xml=self.getDataSubNode(next_action), object=destination_path, + object_id=object_id) subscriber.delSignature(object_gid) - xml_confirmation += self.SyncMLConfirmation(cmd_id, - object_gid,status_code,'Delete') + xml_confirmation += self.SyncMLConfirmation(cmd_id, + object_gid,status_code,'Delete') else: # We want to retrieve more data signature.setStatus(self.PARTIAL) #LOG('SyncModif',0,'setPartialXML: %s' % str(previous_partial)) @@ -905,8 +1026,8 @@ class XMLSyncUtilsMixin(SyncCode): signature.setPartialXML(previous_partial) #LOG('SyncModif',0,'previous_partial: %s' % str(previous_partial)) LOG('SyncModif',0,'waiting more data for :%s' % signature.getId()) - xml_confirmation += self.SyncMLConfirmation(cmd_id, object_gid, - self.WAITING_DATA, next_action.nodeName) + xml_confirmation += self.SyncMLConfirmation(cmd_id,object_gid, + self.WAITING_DATA,next_action.nodeName) if conflict_list != [] and signature is not None: # We had a conflict signature.setStatus(self.CONFLICT) @@ -1000,13 +1121,11 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if domain.domain_type == self.PUB: simulate = 1 for subnode in xml_header.childNodes: - 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) - subscriber = domain.getSubscriber(subscription_url) + 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) + 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 @@ -1023,8 +1142,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): xml=last_xml,domain=domain) elif domain.domain_type == self.SUB: self.sendResponse(from_url=domain.subscription_url, - to_url=domain.publication_url, sync_id=domain.getTitle(), - xml=last_xml, domain=domain) + to_url=domain.publication_url, sync_id=domain.getTitle(), xml=last_xml,domain=domain) return {'has_response':has_response,'xml':last_xml} subscriber.setLastSentMessage('') @@ -1046,8 +1164,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin): globals(), locals(), ['']) conduit = getattr(conduit_module, conduit_name)() # Then apply the list of actions - (xml_confirmation,has_next_action,cmd_id) = self.applyActionList( - cmd_id=cmd_id, + (xml_confirmation,has_next_action,cmd_id) = self.applyActionList(cmd_id=cmd_id, domain=domain, destination_path=destination_path, subscriber=subscriber, @@ -1061,9 +1178,8 @@ class XMLSyncUtils(XMLSyncUtilsMixin): # syncml header if domain.domain_type == self.PUB: - xml(self.SyncMLHeader(subscriber.getSessionId(), - subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(), - domain.getPublicationUrl())) + xml(self.SyncMLHeader(subscriber.getSessionId(), subscriber.incrementMessageId(), + subscriber.getSubscriptionUrl(), domain.getPublicationUrl())) elif domain.domain_type == self.SUB: xml(self.SyncMLHeader(domain.getSessionId(), domain.incrementMessageId(), domain.getPublicationUrl(), domain.getSubscriptionUrl())) @@ -1076,11 +1192,11 @@ class XMLSyncUtils(XMLSyncUtilsMixin): if has_next_action == 0 and not \ (domain.domain_type==self.SUB and alert_code==self.SLOW_SYNC): (syncml_data,xml_confirmation,cmd_id) = self.getSyncMLData(domain=domain, - remote_xml=remote_xml, - subscriber=subscriber, - destination_path=destination_path, - cmd_id=cmd_id,xml_confirmation=xml_confirmation, - conduit=conduit) + remote_xml=remote_xml, + subscriber=subscriber, + destination_path=destination_path, + cmd_id=cmd_id,xml_confirmation=xml_confirmation, + conduit=conduit) # syncml body xml(' <SyncBody>\n') -- 2.30.9