Commit c69b4e86 authored by Sebastien Robin's avatar Sebastien Robin

fabien finished to implement authentication, and he added tests for it

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14439 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 999e908f
......@@ -129,11 +129,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
xml = self.convertToXml(xml)
LOG('addNode',0,'xml_reconstitued: %s' % str(xml))
# In the case where this new node is a object to add
LOG('addNode',0,'object.id: %s' % object.getId())
LOG('addNode',0,'xml.nodeName: %s' % xml.nodeName)
LOG('addNode',0,'getSubObjectDepth: %i' % self.getSubObjectDepth(xml))
LOG('addNode',0,'isHistoryAdd: %i' % self.isHistoryAdd(xml))
LOG('addNode xml',0,repr(xml.toxml()))
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):
......@@ -216,7 +211,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
object_id = self.getAttribute(xml,'id')
elif self.getSubObjectDepth(xml)==1:
object_id = self.getSubObjectId(xml)
#LOG('ERP5Conduit',0,'deleteNode, SubObjectDepth: %i' % self.getSubObjectDepth(xml))
elif self.getSubObjectDepth(xml)==2:
# we have to call delete node on a subsubobject
sub_object_id = self.getSubObjectId(xml)
......@@ -706,14 +700,11 @@ class ERP5Conduit(XMLSyncUtilsMixin):
for subnode in self.getElementNodeList(xml):
if not(subnode.nodeName in self.NOT_EDITABLE_PROPERTY):
keyword_type = self.getPropertyType(subnode)
LOG('newObject',0,str(subnode.childNodes))
# This is the case where the property is a list
keyword=str(subnode.nodeName)
if len(subnode.childNodes) > 0: # We check that this tag is not empty
data = subnode.childNodes[0].data
args[keyword]=data
LOG('newObject',0,'keyword: %s' % str(keyword))
LOG('newObject',0,'keywordtype: %s' % str(keyword_type))
#if args.has_key(keyword):
# LOG('newObject',0,'data: %s' % str(args[keyword]))
if args.has_key(keyword):
......@@ -722,8 +713,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
self.addNode(object=object,xml=subnode, force=1)
# We should first edit the object
args = self.getFormatedArgs(args=args)
LOG('newObject',0,"object.getphyspath: %s" % str(object.getPhysicalPath()))
LOG('newObject',0,"args: %s" % str(args))
# edit the object with a dictionnary of arguments,
# like {"telephone_number":"02-5648"}
#object._edit(**args)
......@@ -885,7 +874,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
dict_list = map(lambda x:x.split(':'),data[1:-1].split(','))
data = map(lambda (x,y):(x.replace(' ','').replace("'",''),int(y)),dict_list)
data = dict(data)
LOG('convertXmlValue',0,'data: %s' % str(data))
return data
# XXX is it the right place ? It should be in XupdateUtils, but here we
......@@ -997,7 +985,6 @@ class ERP5Conduit(XMLSyncUtilsMixin):
add_action = self.isWorkflowActionAddable(object=object,
status=status,wf_tool=wf_tool,
wf_id=wf_id,xml=xml)
#LOG('addNode, workflow_history wf_conflict_list:',0,wf_conflict_list)
LOG('addNode, workflow_history add_action:',0,add_action)
if add_action and not simulate:
LOG('addNode, setting status:',0,'ok')
......
......@@ -152,7 +152,9 @@ class Publication(Subscription):
constructors = (addPublication,)
# Constructor
def __init__(self, id, title, publication_url, destination_path, query, xml_mapping, conduit, gpg_key):
def __init__(self, id, title, publication_url, destination_path,
query, xml_mapping, conduit, gpg_key, auth_required=False,
authentication_format='', authentication_type=''):
"""
constructor
"""
......@@ -169,6 +171,9 @@ class Publication(Subscription):
self.setConduit(conduit)
Folder.__init__(self, id)
self.title = title
self.auth_required = auth_required
self.authentication_format = authentication_format
self.authentication_type = authentication_type
def getPublicationUrl(self):
"""
......@@ -189,6 +194,42 @@ class Publication(Subscription):
"""
self.publication_url = publication_url
def isAuthenticationRequired(self):
"""
return False if authentication not required, True else
"""
return getattr(self, 'auth_required', False)
def setAuthentication(self, auth):
"""
set the value of the authentication requirement
"""
self.auth_required = auth
def getAuthenticationFormat(self):
"""
return the format of authentication
"""
return getattr(self, 'authentication_format', '')
def getAuthenticationType(self):
"""
return the type of authentication
"""
return getattr(self, 'authentication_type', '')
def setAuthenticationFormat(self, authentication_format):
"""
set the format of authentication
"""
self.authentication_format = authentication_format
def setAuthenticationType(self, authentication_type):
"""
set the type of authentication
"""
self.authentication_type = authentication_type
def addSubscriber(self, subscriber):
"""
Add a new subscriber to the publication
......
......@@ -34,6 +34,10 @@ from xml.dom.minidom import parse, parseString
from XMLSyncUtils import XMLSyncUtils
from Conduit.ERP5Conduit import ERP5Conduit
from Products.CMFCore.utils import getToolByName
from Products.ERP5Security.ERP5UserManager import ERP5UserManager
from Products.PluggableAuthService.interfaces.plugins import\
IAuthenticationPlugin
from AccessControl.SecurityManagement import newSecurityManager
import commands
from zLOG import LOG
......@@ -43,7 +47,7 @@ class PublicationSynchronization(XMLSyncUtils):
"""
def PubSyncInit(self, publication=None, xml_client=None, subscriber=None,
sync_type=None, auth_required=0):
sync_type=None):
"""
Read the client xml message
Send the first XML message from the server
......@@ -52,8 +56,10 @@ class PublicationSynchronization(XMLSyncUtils):
#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()
#same for the message id
subscriber.setMessageId(self.getMessageId(xml_client))
#at the begining of the synchronization the subscriber is not authenticated
subscriber.setAuthenticated(False)
#the last_message_id is 1 because the message that
#we are about to send is the message 1
subscriber.initLastMessageId(1)
......@@ -67,7 +73,8 @@ class PublicationSynchronization(XMLSyncUtils):
alert_code = self.getAlertCode(xml_client)
cred = self.checkCred(xml_client)
#XXX this is in developement, it's just for tests
if not cred and auth_required:
if publication.isAuthenticationRequired():
if not cred:
LOG('PubSyncInit',0,'authentication required')
# Prepare the xml message for the Sync initialization package
cmd_id = 1 # specifies a SyncML message-unique command identifier
......@@ -76,14 +83,15 @@ class PublicationSynchronization(XMLSyncUtils):
xml('<SyncML>\n')
# syncml header
xml(self.SyncMLHeader(subscriber.getSessionId(),
subscriber.incrementMessageId(), subscriber.getSubscriptionUrl(),
subscriber.getMessageId(), 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))
xml(self.SyncMLChal(cmd_id, "SyncHdr",
publication.getPublicationUrl(), subscriber.getSubscriptionUrl(),
publication.getAuthenticationFormat(),
publication.getAuthenticationType(), self.AUTH_REQUIRED))
cmd_id += 1
xml(' </SyncBody>\n')
......@@ -92,8 +100,56 @@ class PublicationSynchronization(XMLSyncUtils):
xml_a = ''.join(xml_list)
self.sendResponse(from_url=publication.getPublicationUrl(),
to_url=subscriber.getSubscriptionUrl(),sync_id=publication.getTitle(),
xml=xml_a,domain=publication)
to_url=subscriber.getSubscriptionUrl(),
sync_id=publication.getTitle(), xml=xml_a, domain=publication)
else:#(if the subscriber begin the session with a cred) -> to be tested
(authentication_format, authentication_type, data) = self.getCred(xml_client)
#at the begining, the code is initialised at UNAUTHORIZED
auth_code=self.UNAUTHORIZED
if authentication_format == publication.getAuthenticationFormat():
if authentication_type == publication.getAuthenticationType():
decoded = subscriber.decode(authentication_format, data)
if decoded not in ('', None) and decoded.__contains__(':'):
(login, password) = decoded.split(':')
uf = self.getPortalObject().acl_users
for plugin_name, plugin in uf._getOb('plugins').listPlugins(
IAuthenticationPlugin ):
if plugin.authenticateCredentials(
{'login':login, 'password':password}) is not None:
subscriber.setAuthenticated(True)
auth_code=self.AUTH_ACCEPTED
#here we must log in with the user authenticated :
user = uf.getUserById(login).__of__(uf)
newSecurityManager(None, user)
subscriber.setUser(login)
break
#in all others cases, the auth_code is set to UNAUTHORIZED
# 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.getMessageId(),
subscriber.getSubscriptionUrl(),
publication.getPublicationUrl()))
# syncml body
xml(' <SyncBody>\n')
xml(self.SyncMLStatus(cmd_id, subscriber.getSubscriptionUrl(),
publication.getPublicationUrl(), auth_code))
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:
......@@ -103,8 +159,7 @@ class PublicationSynchronization(XMLSyncUtils):
# 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)
\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:
......@@ -112,8 +167,8 @@ class PublicationSynchronization(XMLSyncUtils):
LOG('PubSyncInit',0,'anchor null')
raise ValueError, "Sorry, the anchor was null"
else:
message = "bad anchors in PubSyncInit! " + subscriber.getNextAnchor() + \
" and " + last_anchor
message = "bad anchors in PubSyncInit! " + \
subscriber.getNextAnchor() + " and " + last_anchor
LOG('PubSyncInit',0,message)
else:
subscriber.setNextAnchor(next_anchor)
......@@ -123,8 +178,7 @@ class PublicationSynchronization(XMLSyncUtils):
# We have started the sync from the server (may be for a conflict resolution)
pass
if alert is not None and auth_required==0:
#if 1:
if alert is not None and not publication.isAuthenticationRequired():
# Prepare the xml message for the Sync initialization package
cmd_id = 1 # specifies a SyncML message-unique command identifier
xml_list = []
......@@ -202,6 +256,14 @@ class PublicationSynchronization(XMLSyncUtils):
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:
#we log the user authenticated to do the synchronization with him
if publication.isAuthenticationRequired():
if subscriber.isAuthenticated():
uf = self.getPortalObject().acl_users
user = uf.getUserById(subscriber.getUser()).__of__(uf)
newSecurityManager(None, user)
result = self.PubSyncModif(publication, xml_client)
else:
result = self.PubSyncModif(publication, xml_client)
elif subscriber is not None:
......
......@@ -41,6 +41,11 @@ from zLOG import LOG
import md5
try:
from base64 import b64encode, b64decode
except ImportError:
from base64 import encodestring as b64encode, decodestring as b64decode
#class Conflict(SyncCode, Implicit):
class Conflict(SyncCode, Base):
"""
......@@ -53,8 +58,8 @@ class Conflict(SyncCode, Base):
isIndexable = 0
isPortalContent = 0 # Make sure RAD generated accessors at the class level
def __init__(self, object_path=None, keyword=None, xupdate=None, publisher_value=None,\
subscriber_value=None, subscriber=None):
def __init__(self, object_path=None, keyword=None, xupdate=None,
publisher_value=None, subscriber_value=None, subscriber=None):
self.object_path=object_path
self.keyword = keyword
self.setLocalValue(publisher_value)
......@@ -614,8 +619,8 @@ class Subscription(Folder, SyncCode):
isPortalContent = 1
isRADContent = 1
icon = None
isIndexable = 0
user = None
# Declarative properties
property_sheets = ( PropertySheet.Base
......@@ -635,7 +640,8 @@ class Subscription(Folder, SyncCode):
)
# Constructor
def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, conduit, gpg_key):
def __init__(self, id, title, publication_url, subscription_url, destination_path, query, xml_mapping, conduit, gpg_key, login, password,
authentication_format='', authentication_type=''):
"""
We need to create a dictionnary of
signatures of documents which belong to the synchronisation
......@@ -652,6 +658,10 @@ class Subscription(Folder, SyncCode):
#self.signatures = PersistentMapping()
self.last_anchor = '00000000T000000Z'
self.next_anchor = '00000000T000000Z'
self.login=login
self.password=password
self.authentication_format=authentication_format
self.authentication_type=authentication_type
self.domain_type = self.SUB
self.gpg_key = gpg_key
self.setGidGenerator(None)
......@@ -714,28 +724,28 @@ class Subscription(Folder, SyncCode):
We will see if the last session id was the same
wich means that the same message was sent again
return 1 if the session id was not seen, 0 if already seen
return True if the session id was not seen, False if already seen
"""
last_session_id = getattr(self,'last_session_id',None)
if last_session_id == session_id:
return 0
return False
self.last_session_id = session_id
return 1
return True
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
return True if the message id was not seen, False if already seen
"""
last_message_id = getattr(self,'last_message_id',None)
# LOG('checkCorrectRemoteMessageId last_message_id =',0,last_message_id)
# LOG('checkCorrectRemoteMessageId message_id =',0,message_id)
if last_message_id == message_id:
return 0
return False
self.last_message_id = message_id
return 1
return True
def initLastMessageId(self, last_message_id=None):
"""
......@@ -872,25 +882,74 @@ class Subscription(Folder, SyncCode):
"""
return self.gid_generator
def getLogin(self):
"""
This method return the login of this subscription
"""
return getattr(self, 'login', '')
def setLogin(self, new_login):
"""
set the login at new_login
"""
self.login=new_login
def getPassword(self):
"""
This method return the password of this subscription
"""
return getattr(self, 'password', '')
def setPassword(self, new_password):
"""
set the password at new_password
"""
self.password=new_password
def setAuthentication(self, auth):
"""
set the value of the authentication requirement
"""
self.auth_required = auth
def getAuthenticationFormat(self):
"""
return the format of authentication
"""
return getattr(self, 'authentication_format', '')
def getAuthenticationType(self):
"""
return the type of authentication
"""
return getattr(self, 'authentication_type', '')
def setAuthenticationFormat(self, authentication_format):
"""
set the format of authentication
"""
self.authentication_format = authentication_format
def setAuthenticationType(self, authentication_type):
"""
set the type of authentication
"""
self.authentication_type = authentication_type
def getGidFromObject(self, object):
"""
"""
o_base = aq_base(object)
o_gid = None
# LOG('getGidFromObject',0,'gidgenerator : _%s_' % repr(self.getGidGenerator()))
gid_gen = self.getGidGenerator()
if callable(gid_gen):
# LOG('getGidFromObject gid_generator',0,'is callable')
o_gid=gid_gen(object)
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
elif getattr(o_base, gid_gen, None) is not None:
# LOG('getGidFromObject',0,'there is the gid generator on o_base')
generator = getattr(object, gid_gen)
o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
elif gid_gen is not None:
# It might be a script python
# LOG('getGidFromObject',0,'there is the gid generator')
generator = getattr(object,gid_gen)
o_gid = generator() # XXX - used to be o_gid = generator(object=object) which is redundant
# LOG('getGidFromObject',0,'o_gid: %s' % repr(o_gid))
......@@ -911,7 +970,6 @@ class Subscription(Folder, SyncCode):
# LOG('getObjectFromGid oject_list',0,object_list)
if signature is not None and signature.getId() is not None:
o_id = signature.getId()
# LOG('getObjectFromGid o_id',0,o_id)
o = None
try:
o = destination._getOb(o_id)
......@@ -920,7 +978,6 @@ class Subscription(Folder, SyncCode):
if o is not None and o in object_list:
return o
for o in object_list:
# LOG('getObjectFromGid',0,'working on : %s' % repr(o))
o_gid = self.getGidFromObject(o)
if o_gid == gid:
return o
......@@ -1074,6 +1131,12 @@ class Subscription(Folder, SyncCode):
"""
self.message_id = 0
def setMessageId(self, message_id):
"""
set the message id to message_id
"""
self.message_id = message_id
def getLastAnchor(self):
"""
return the id of the last synchronisation
......@@ -1230,3 +1293,67 @@ class Subscription(Folder, SyncCode):
o.setTempXML(None)
self.setRemainingObjectPathList(None)
def isAuthenticated(self):
"""
return True if the subscriber is authenticated for this session, False
in other case
"""
return self.is_authenticated
def setAuthenticated(self, value):
"""
set at True or False the value of is_authenticated is the subscriber
is authenticated for this session or not
"""
self.is_authenticated = value
def encode(self, format, string_to_encode):
"""
return the string_to_encode encoded with format format
"""
if format in ('', None):
return string_to_encode
if format == 'b64':
return b64encode(string_to_encode)
#elif format is .... put here the other formats
else:#if there is no format corresponding with format, raise an error
LOG('encode : unknown or not implemented format :', 0, format)
raise ValueError, "Sorry, the format %s is unknow or not implemented" % format
def decode(self, format, string_to_decode):
"""
return the string_to_decode decoded with format format
"""
string_to_decode = string_to_decode.encode('utf-8')
if format in ('', None):
return string_to_decode
if format == 'b64':
return b64decode(string_to_decode)
#elif format is .... put here the other formats
else:#if there is no format corresponding with format, raise an error
LOG('decode : unknown or not implemented format :', 0, format)
raise ValueError, "Sorry, the format %s is unknow or not implemented" % format
def isDecodeEncodeTheSame(self, string_encoded, string_decoded, format):
"""
return True if the string_encoded is equal to string_decoded encoded
in format
"""
isTheSame=False
if self.encode(format, string_decoded) == string_encoded:
isTheSame=True
return isTheSame
def setUser(self, user):
"""
save the user logged in to log him on each transaction
"""
self.user=user
def getUser(self):
"""
retrun the user logged in
"""
return self.user
......@@ -44,6 +44,8 @@ class SubscriptionSynchronization(XMLSyncUtils):
"""
LOG('SubSyncInit',0,'starting....')
cmd_id = 1 # specifies a SyncML message-unique command identifier
subscription.NewAnchor()
subscription.initLastMessageId()
xml_list = []
xml = xml_list.append
xml('<SyncML>\n')
......@@ -54,8 +56,6 @@ class SubscriptionSynchronization(XMLSyncUtils):
# syncml body
xml(' <SyncBody>\n')
subscription.NewAnchor()
subscription.initLastMessageId()
# We have to set every object as NOT_SYNCHRONIZED
subscription.startSynchronization()
......@@ -100,7 +100,21 @@ class SubscriptionSynchronization(XMLSyncUtils):
xml_client = msg
if isinstance(xml_client, str) or isinstance(xml_client, unicode):
xml_client = parseString(xml_client)
response = self.SubSyncModif(self.getSubscription(id),xml_client)
next_status = self.getNextSyncBodyStatus(xml_client, None)
#LOG('readResponse, next status :',0,next_status)
if next_status is not None:
status_code = self.getStatusCode(next_status)
#LOG('readResponse status code :',0,status_code)
if status_code == self.AUTH_REQUIRED:
#LOG('readResponse', 0, 'Authentication required')
response = self.SubSyncCred(id, xml_client)
elif status_code == self.UNAUTHORIZED:
#LOG('readResponse', 0, 'Bad authentication')
return {'has_response':0,'xml':xml_client}
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
else:
response = self.SubSyncModif(self.getSubscription(id), xml_client)
if RESPONSE is not None:
......@@ -108,6 +122,53 @@ class SubscriptionSynchronization(XMLSyncUtils):
else:
return response
def SubSyncCred (self, id, msg=None, RESPONSE=None):
"""
This method send crendentials
"""
LOG('SubSyncCred',0,'starting... id: %s' % str(id))
LOG('SubSyncCred',0,'starting... msg: %s' % str(msg))
cmd_id = 1 # specifies a SyncML message-unique command identifier
subscription = self.getSubscription(id)
xml_list = []
xml = xml_list.append
xml('<SyncML>\n')
# syncml header
data = "%s:%s" % (subscription.getLogin(), subscription.getPassword())
data=subscription.encode(subscription.getAuthenticationFormat(), data)
xml(self.SyncMLHeader(subscription.getSessionId(),
subscription.incrementMessageId(), subscription.getPublicationUrl(),
subscription.getSubscriptionUrl(), dataCred=data,
authentication_format=subscription.getAuthenticationFormat(),
authentication_type=subscription.getAuthenticationType()))
# syncml body
xml(' <SyncBody>\n')
# alert message
xml(self.SyncMLAlert(cmd_id, subscription.getSynchronizationType(),
subscription.getPublicationUrl(),
subscription.getDestinationPath(),
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('</SyncML>\n')
xml_a = ''.join(xml_list)
self.sendResponse(from_url=subscription.subscription_url,
to_url=subscription.publication_url, sync_id=subscription.getTitle(),
xml=xml_a,domain=subscription)
return {'has_response':1,'xml':xml_a}
def SubSyncModif(self, subscription, xml_client):
"""
Send the client modification, this happens after the Synchronization
......
This diff is collapsed.
......@@ -47,7 +47,8 @@ from zLOG import LOG
class XMLSyncUtilsMixin(SyncCode):
def SyncMLHeader(self, session_id, msg_id, target, source, target_name=None,
source_name=None):
source_name=None, dataCred=None, authentication_format='b64',
authentication_type='syncml:auth-basic'):
"""
Since the Header is always almost the same, this is the
way to set one quickly.
......@@ -61,14 +62,22 @@ class XMLSyncUtilsMixin(SyncCode):
xml(' <MsgID>%s</MsgID>\n' % msg_id)
xml(' <Target>\n')
xml(' <LocURI>%s</LocURI>\n' % target)
if target_name is not None:
if target_name not in (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:
if source_name not in (None, ''):
xml(' <LocName>%s</LocName>\n' % source_name)
xml(' </Source>\n')
if dataCred not in (None, ''):
xml(' <Cred>\n')
xml(' <Meta>\n')
xml(' <Format>%s</Format>\n' % authentication_format)
xml(' <Type>%s</Type>\n' % authentication_type)
xml(' </Meta>\n')
xml(' <Data>%s</Data>\n' % dataCred)
xml(' </Cred>\n')
xml(' </SyncHdr>\n')
xml_a = ''.join(xml_list)
return xml_a
......@@ -103,7 +112,7 @@ class XMLSyncUtilsMixin(SyncCode):
return xml_a
def SyncMLStatus(self, cmd_id, target_ref, source_ref, sync_code,
next_anchor):
next_anchor=None):
"""
Since the Status section is always almost the same, this is the
way to set one quickly.
......@@ -115,6 +124,7 @@ class XMLSyncUtilsMixin(SyncCode):
xml(' <TargetRef>%s</TargetRef>\n' % target_ref)
xml(' <SourceRef>%s</SourceRef>\n' % source_ref)
xml(' <Data>%s</Data>\n' % sync_code)
if next_anchor is not None:
xml(' <Item>\n')
xml(' <Data>\n')
xml(' <Anchor xmlns=\'syncml:metinf\'>\n')
......@@ -416,27 +426,6 @@ class XMLSyncUtilsMixin(SyncCode):
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):
"""
Return the value of the command inside the xml_stream
......@@ -448,6 +437,44 @@ class XMLSyncUtilsMixin(SyncCode):
return subnode.childNodes[0].data
return None
def getCred(self, xml):
"""
return the credential information : type, format and data
"""
format=''
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"
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
......@@ -739,13 +766,13 @@ class XMLSyncUtilsMixin(SyncCode):
# 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
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))
LOG('getSyncMLData',0,'hasSignature: %s' % str(subscriber.hasSignature(object_gid)))
LOG('getSyncMLData',0,'alert_code == slowsync: %s' % str(self.getAlertCode(remote_xml)==self.SLOW_SYNC))
#LOG('getSyncMLData',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))
#LOG('getSyncMLData',0,'hasSignature: %s' % str(subscriber.hasSignature(object_gid)))
#LOG('getSyncMLData',0,'alert_code == slowsync: %s' % str(self.getAlertCode(remote_xml)==self.SLOW_SYNC))
signature = subscriber.getSignature(object_gid)
LOG('getSyncMLData',0,'current object: %s' % str(object.getId()))
#LOG('getSyncMLData',0,'current object: %s' % str(object.getId()))
# Here we first check if the object was modified or not by looking at dates
if signature is not None:
signature.checkSynchronizationNeeded(object)
......@@ -774,7 +801,7 @@ class XMLSyncUtilsMixin(SyncCode):
rest_string = xml_string[len(short_string):]
#LOG('XMLSyncUtils',0,'rest_string: %s' % str(rest_string))
i += 1
LOG('getSyncMLData',0,'setPartialXML with: %s' % str(rest_string))
#LOG('getSyncMLData',0,'setPartialXML with: %s' % str(rest_string))
signature.setPartialXML(rest_string)
status =self.PARTIAL
signature.setAction('Add')
......@@ -787,8 +814,8 @@ class XMLSyncUtilsMixin(SyncCode):
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)
LOG('getSyncMLData',0,'checkMD5: %s' % str(signature.checkMD5(xml_object)))
LOG('getSyncMLData',0,'getStatus: %s' % str(signature.getStatus()))
#LOG('getSyncMLData',0,'checkMD5: %s' % str(signature.checkMD5(xml_object)))
#LOG('getSyncMLData',0,'getStatus: %s' % str(signature.getStatus()))
if signature.getStatus()==self.PUB_CONFLICT_MERGE:
xml_confirmation += self.SyncMLConfirmation(cmd_id,object.id,
self.CONFLICT_MERGE,'Replace')
......@@ -821,7 +848,7 @@ class XMLSyncUtilsMixin(SyncCode):
signature.setTempXML(xml_object)
# Now we can apply the xupdate from the subscriber
subscriber_xupdate = signature.getSubscriberXupdate()
LOG('getSyncMLData subscriber_xupdate',0,subscriber_xupdate)
#LOG('getSyncMLData subscriber_xupdate',0,subscriber_xupdate)
if subscriber_xupdate is not None:
old_xml = signature.getXML()
conduit.updateNode(xml=subscriber_xupdate, object=object,
......@@ -1080,7 +1107,6 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
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
simulate = 0 # used by applyActionList, should be 0 for client
......@@ -1103,11 +1129,12 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
if last_xml != '':
has_response = 1
if domain.domain_type == self.PUB: # We always reply
self.sendResponse(from_url=domain.publication_url, to_url=subscriber.subscription_url,
sync_id=domain.getTitle(), xml=last_xml,domain=domain)
self.sendResponse(from_url=domain.publication_url,
to_url=subscriber.subscription_url, sync_id=domain.getTitle(),
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)
self.sendResponse(from_url=domain.subscription_url,
to_url=domain.publication_url, sync_id=domain.getTitle(), xml=last_xml,domain=domain)
return {'has_response':has_response,'xml':last_xml}
subscriber.setLastSentMessage('')
......@@ -1135,7 +1162,7 @@ class XMLSyncUtils(XMLSyncUtilsMixin):
subscriber=subscriber,
remote_xml=remote_xml,
conduit=conduit, simulate=simulate)
LOG('SyncModif, has_next_action:',0,has_next_action)
#LOG('SyncModif, has_next_action:',0,has_next_action)
xml_list = []
xml = xml_list.append
......
......@@ -127,6 +127,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Authentication Required
</label></div>
</td>
<td align="left" valign="top">
<input type="checkbox" name="auth_required" value="1" <dtml-if expr="isAuthenticationRequired()">CHECKED</dtml-if>>
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" value="<dtml-var getAuthenticationFormat>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" value="<dtml-var getAuthenticationType>" size="40" />
</td>
</tr>
</table>
<table>
<tr>
......
......@@ -137,6 +137,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" value="<dtml-var getGidGenerator>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Login
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="login" value="<dtml-var getLogin>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Password
</label></div>
</td>
<td align="left" valign="top">
<input type="password" name="password" value="<dtml-var getPassword>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" value="<dtml-var getAuthenticationFormat>" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" value="<dtml-var getAuthenticationType>" size="40" />
</td>
</tr>
</table>
<table>
<tr>
......
......@@ -123,6 +123,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Authentication Required
</label></div>
</td>
<td align="left" valign="top">
<input type="checkbox" name="auth_required" value="1">
</td>
</tr>
<tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" size="40" />
</td>
</tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
......
......@@ -133,6 +133,45 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
<input type="text" name="gid_generator" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Login
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="login" size="40" /> </td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Password
</label></div>
</td>
<td align="left" valign="top">
<input type="password" name="password" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Format authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_format" size="40" />
</td>
</tr>
<td align="left" valign="top">
<div class="form-label">
Type authentication
</label></div>
</td>
<td align="left" valign="top">
<input type="text" name="authentication_type" size="40" />
</td>
</tr>
<tr>
<tr>
<td align="left" valign="top">
</td>
......
This diff is collapsed.
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