Commit 9b22e41d authored by Sebastien Robin's avatar Sebastien Robin

by Fabien, use the library Ft.Xml instead of xml.dom.minidom in order to make...

by Fabien, use the library Ft.Xml instead of xml.dom.minidom in order to make synchronization faster, and use xpath exression, this make the code much more cleaner

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14478 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent c08f67d8
......@@ -33,8 +33,7 @@ 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 xml.dom.ext.reader.Sax2 import FromXml
from xml.dom.minidom import parse, parseString
from Ft.Xml import Parse
from DateTime.DateTime import DateTime
from email.MIMEBase import MIMEBase
from email import Encoders
......@@ -44,10 +43,12 @@ 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
......@@ -132,7 +133,8 @@ 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)
......@@ -160,7 +162,8 @@ 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,
......@@ -274,9 +277,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 = {}
......@@ -342,7 +345,8 @@ 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))
......@@ -383,8 +387,7 @@ 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')
......@@ -397,7 +400,7 @@ 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,
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
......@@ -421,8 +424,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:
......@@ -438,7 +441,8 @@ 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
......@@ -484,19 +488,21 @@ 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.deepcopy(xml)
for subnode in self.getAttributeNodeList(xml):
xml_copy = xml.cloneNode(True) #make a deepcopy of the node xml
for subnode in self.getAttributeNodeList(xml_copy):
if subnode.nodeName=='select':
subnode.nodeValue = self.getSubObjectSelect(subnode.nodeValue)
return xml
return xml_copy
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):
......@@ -510,7 +516,8 @@ 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
......@@ -524,7 +531,8 @@ 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
......@@ -555,7 +563,8 @@ 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
......@@ -571,7 +580,8 @@ 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
......@@ -587,7 +597,8 @@ 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
......@@ -604,7 +615,8 @@ 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
......@@ -624,7 +636,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
for attribute in self.getAttributeNodeList(xml):
if attribute.nodeName == param:
data = attribute.childNodes[0].data
data = attribute.value
return self.convertXmlValue(data,data_type='string')
return None
......@@ -635,7 +647,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
for subnode in self.getElementNodeList(xml):
if subnode.nodeName == 'docid':
data = subnode.childNodes[0].data
data = subnode.childNodes[0].value
return self.convertXmlValue(data)
return None
......@@ -669,7 +681,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
LOG('Conduit.convertToXml xml',0,repr(xml))
if type(xml) is type(u'a'):
xml = xml.encode('utf-8')
xml = parseString(xml)
xml = Parse(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
......@@ -811,7 +823,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#PrettyPrint(xml,xml_string)
#xml_string = xml_string.getvalue()
#xml_string = unicode(xml_string,encoding='utf-8')
xml_string = xml.toxml(encoding='utf-8')
xml_string = self.nodeToString(xml)
#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')
......@@ -845,7 +858,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
#PrettyPrint(xml,xml_string)
#xml_string = xml_string.getvalue()
#xml_string = unicode(xml_string,encoding='utf-8')
xml_string = xml.toxml(encoding='utf-8')
xml_string = self.nodeToString(xml)
xml_string = unicode(xml_string,encoding='utf-8')
maxi = xml_string.find('>')+1
result += xml_string[maxi:xml_string.find('</%s>' % xml.nodeName)]
......@@ -929,7 +942,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
conflict_list = []
if type(xupdate) in (type('a'),type(u'a')):
xupdate = parseString(xupdate)
xupdate = Parse(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
......@@ -967,7 +980,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
nb_sub = len(subnode_list)
comp = 0
for subnode in subnode_list:
value = subnode.getAttribute('select')
value = self.getAttribute(subnode, 'select')
if re.search(self.object_exp, value):
comp += 1
if nb_sub == comp:
......@@ -1043,7 +1056,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())
#LOG('addNode, workflow_history xml:',0,xml.toxml())#toxml isn't in 4Suite
LOG('addNode, workflow_history xml.getElmentNodeList:',0,self.getElementNodeList(xml))
xml = self.getElementNodeList(xml)[0]
LOG('addNode, workflow_history id:',0,wf_id)
......@@ -1152,3 +1165,13 @@ 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
......@@ -29,8 +29,7 @@
import smtplib # to send emails
from Publication import Publication,Subscriber
from Subscription import Signature
from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml
from xml.dom.minidom import parse, parseString
from Ft.Xml import Parse
from XMLSyncUtils import XMLSyncUtils
from Conduit.ERP5Conduit import ERP5Conduit
from Products.CMFCore.utils import getToolByName
......@@ -221,7 +220,7 @@ class PublicationSynchronization(XMLSyncUtils):
if xml_client is not None:
if isinstance(xml_client, str) or isinstance(xml_client, unicode):
xml_client = parseString(xml_client)
xml_client = Parse(xml_client)
first_node = xml_client.childNodes[0]
if first_node.nodeName != "SyncML":
......
......@@ -28,9 +28,7 @@
import smtplib # to send emails
from Subscription import Subscription,Signature
from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml
from xml.dom.minidom import parse, parseString
from xml.dom.ext import PrettyPrint
from Ft.Xml import Parse
from XMLSyncUtils import XMLSyncUtils
import commands
from Conduit.ERP5Conduit import ERP5Conduit
......@@ -99,7 +97,7 @@ class SubscriptionSynchronization(XMLSyncUtils):
else:
xml_client = msg
if isinstance(xml_client, str) or isinstance(xml_client, unicode):
xml_client = parseString(xml_client)
xml_client = Parse(xml_client)
next_status = self.getNextSyncBodyStatus(xml_client, None)
#LOG('readResponse, next status :',0,next_status)
if next_status is not None:
......
......@@ -40,8 +40,7 @@ from Products.ERP5SyncML import Conduit
from Publication import Publication,Subscriber
from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2
from Subscription import Subscription,Signature
from xml.dom.ext.reader.Sax2 import FromXmlStream, FromXml
from xml.dom.minidom import parse, parseString
from Ft.Xml import Parse
from Products.ERP5Type import Permissions
from PublicationSynchronization import PublicationSynchronization
from SubscriptionSynchronization import SubscriptionSynchronization
......@@ -50,7 +49,6 @@ 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
......@@ -974,7 +972,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 = parseString(text)
xml = Parse(text)
#XXX this function is not very optimized and should be improved
url = self.getTarget(xml)
for publication in self.getPublicationList():
......
......@@ -29,8 +29,7 @@
import smtplib
from Products.ERP5SyncML.SyncCode import SyncCode
from Products.ERP5SyncML.Subscription import Signature
from xml.dom.ext.reader.Sax2 import FromXml
from xml.dom.minidom import parse, parseString
from Ft.Xml import Parse
from DateTime import DateTime
from cStringIO import StringIO
from xml.dom.ext import PrettyPrint
......@@ -301,28 +300,17 @@ class XMLSyncUtilsMixin(SyncCode):
We will retrieve the session id of the message
"""
session_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 == 'SessionID':
session_id = int(subnode2.childNodes[0].data)
session_id = xml.xpath('string(/SyncML/SyncHdr/SessionID)')
session_id = int(session_id)
return session_id
def getMessageId(self, xml):
"""
We will retrieve the message id of the message
"""
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)
message_id = xml.xpath('string(/SyncML/SyncHdr/MsgID)')
message_id = int(message_id)
return message_id
def getTarget(self, xml):
......@@ -330,18 +318,10 @@ class XMLSyncUtilsMixin(SyncCode):
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
url = xml.xpath('string(/SyncML/SyncHdr/Target/LocURI)')
url = url.encode('utf-8')
return url
def getAlertLastAnchor(self, xml_stream):
"""
Return the value of the last anchor, in the
......@@ -351,23 +331,8 @@ class XMLSyncUtilsMixin(SyncCode):
# 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":
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
last_anchor = client_body.xpath('string(/Alert/Item/Meta/Anchor/Last)')
last_anchor = last_anchor.encode('utf-8')
return last_anchor
def getAlertNextAnchor(self, xml_stream):
......@@ -381,60 +346,32 @@ class XMLSyncUtilsMixin(SyncCode):
# Get informations from the body
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.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
next_anchor = client_body.xpath('string(/Alert/Item/Meta/Anchor/Next)')
next_anchor = next_anchor.encode('utf-8')
return next_anchor
def getStatusTarget(self, xml):
"""
Return the value of the alert code inside the xml_stream
"""
# 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
return xml.xpath('string(TargetRef)')
def getStatusCode(self, xml):
"""
Return the value of the alert code inside the xml_stream
"""
# 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)
status_code = xml.xpath('string(Data)')
if status_code not in ('', None, []):
return int(status_code)
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':
for subnode in xml.childNodes:
if subnode.nodeType == subnode.ELEMENT_NODE and subnode.nodeName == 'Cmd':
return subnode.childNodes[0].data
return xml.xpath('string(//Status/Cmd)')
else:
return None
def getCred(self, xml):
......@@ -445,110 +382,60 @@ class XMLSyncUtilsMixin(SyncCode):
type=''
data=''
first_node = xml.childNodes[0]
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 = 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)')
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
format = format.encode('utf-8')
type = type.encode('utf-8')
data = data.encode('utf-8')
return (format, type, data)
def getAlertCode(self, xml_stream):
"""
Return the value of the alert code inside the full syncml message
"""
# 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)
alert_code = xml_stream.xpath('string(SyncML/SyncBody/Alert/Data)')
if alert_code not in (None, ''):
return int(alert_code)
else:
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
cred = False
if xml_stream.xpath('string(SyncML/SyncHdr/Cred)') not in ('', None, []):
cred = True
return cred
def checkAlert(self, xml_stream):
"""
Check if there's an Alert section in the xml_stream
"""
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
alert = False
if xml_stream.xpath('string(SyncML/SyncBody/Alert)') not in ('', None, []):
alert = True
return alert
def checkSync(self, xml_stream):
"""
Check if there's an Sync section in the xml_xtream
"""
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
sync = False
if xml_stream.xpath('string(SyncML/SyncBody/Sync)') not in ('', None, []):
sync = True
return sync
def CheckStatus(self, xml_stream):
"""
Check if there's a Status section in the xml_xtream
"""
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"
status = False
if xml_stream.xpath('string(SyncML/SyncBody/Status)') not in ('', None, []):
status = True
return status
def getNextSyncAction(self, xml_stream, last_action):
......@@ -563,18 +450,22 @@ 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
......@@ -593,7 +484,8 @@ 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
......@@ -609,9 +501,11 @@ 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:
......@@ -622,9 +516,11 @@ 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:
......@@ -639,60 +535,40 @@ 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
"""
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
if action.xpath('Item/MoreData'):
return True
return False
def getActionType(self, action):
"""
Return the type of the object described by the action
"""
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)
return action.xpath('string(Meta/Type)')
def getElementNodeList(self, node):
"""
Return childNodes that are ElementNode
"""
#return node.getElementsByTagName('*')
subnode_list = []
for subnode in node.childNodes or []:
if subnode.nodeType == subnode.ELEMENT_NODE:
subnode_list += [subnode]
return subnode_list
return node.xpath('*')
def getTextNodeList(self, node):
"""
......@@ -708,11 +584,7 @@ class XMLSyncUtilsMixin(SyncCode):
"""
Return childNodes that are ElementNode
"""
attribute_list = []
for subnode in node.attributes.values() or []:
if subnode.nodeType == subnode.ATTRIBUTE_NODE:
attribute_list += [subnode]
return attribute_list
return node.xpath('@*')
def getSyncMLData(self, domain=None,remote_xml=None,cmd_id=0,
subscriber=None,destination_path=None,
......@@ -765,7 +637,8 @@ 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))
......@@ -781,11 +654,13 @@ 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)
......@@ -806,14 +681,15 @@ 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:
......@@ -842,8 +718,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
......@@ -852,9 +728,10 @@ class XMLSyncUtilsMixin(SyncCode):
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),
previous_xml=old_xml, force=(domain.getDomainType==self.SUB),
simulate=0)
xml_object = self.getXMLObject(object=object,xml_mapping=domain.xml_mapping)
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
......@@ -890,11 +767,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,
......@@ -918,7 +795,8 @@ 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))
......@@ -932,7 +810,7 @@ class XMLSyncUtilsMixin(SyncCode):
data_subnode = partial_data
LOG('SyncModif',0,'data_subnode: %s' % data_subnode)
#data_subnode = FromXml(data_subnode)
data_subnode = parseString(data_subnode)
data_subnode = Parse(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:
......@@ -942,12 +820,13 @@ 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
......@@ -1012,8 +891,8 @@ 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')
......@@ -1026,8 +905,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)
......@@ -1121,9 +1000,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":
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':
if subnode2.nodeType == subnode2.ELEMENT_NODE and \
subnode2.nodeName == 'LocURI':
subscription_url = str(subnode2.childNodes[0].data)
subscriber = domain.getSubscriber(subscription_url)
......@@ -1142,7 +1023,8 @@ 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('')
......@@ -1164,7 +1046,8 @@ 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,
......@@ -1178,8 +1061,9 @@ 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()))
......
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