Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nikola Balog
erp5
Commits
bf16fe93
Commit
bf16fe93
authored
Jan 26, 2024
by
Jérome Perrin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
syncml: python3 support
parent
4dee881e
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
159 additions
and
139 deletions
+159
-139
bt5/erp5_syncml/DocumentTemplateItem/portal_components/document.erp5.SyncMLSignature.py
...teItem/portal_components/document.erp5.SyncMLSignature.py
+10
-8
bt5/erp5_syncml/DocumentTemplateItem/portal_components/document.erp5.SyncMLSubscription.py
...tem/portal_components/document.erp5.SyncMLSubscription.py
+14
-13
bt5/erp5_syncml/MixinTemplateItem/portal_components/mixin.erp5.SyncMLEngineMixin.py
...ateItem/portal_components/mixin.erp5.SyncMLEngineMixin.py
+8
-4
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.ERP5Conduit.py
...TemplateItem/portal_components/module.erp5.ERP5Conduit.py
+25
-18
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLEngineAsynchronous.py
...portal_components/module.erp5.SyncMLEngineAsynchronous.py
+4
-4
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLEngineSynchronous.py
.../portal_components/module.erp5.SyncMLEngineSynchronous.py
+6
-5
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLMessage.py
...mplateItem/portal_components/module.erp5.SyncMLMessage.py
+12
-11
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLTransportFile.py
...Item/portal_components/module.erp5.SyncMLTransportFile.py
+2
-3
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLUtils.py
...TemplateItem/portal_components/module.erp5.SyncMLUtils.py
+14
-18
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.VCardConduit.py
...emplateItem/portal_components/module.erp5.VCardConduit.py
+11
-4
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.XMLSyncUtils.py
...emplateItem/portal_components/module.erp5.XMLSyncUtils.py
+8
-5
bt5/erp5_syncml/SkinTemplateItem/portal_skins/erp5_syncml/Person_exportAsVCard.py
...lateItem/portal_skins/erp5_syncml/Person_exportAsVCard.py
+0
-7
bt5/erp5_syncml/TestTemplateItem/portal_components/test.erp5.testERP5DocumentSyncML.py
...tem/portal_components/test.erp5.testERP5DocumentSyncML.py
+3
-3
bt5/erp5_syncml/TestTemplateItem/portal_components/test.erp5.testERP5SyncML.py
...emplateItem/portal_components/test.erp5.testERP5SyncML.py
+15
-20
bt5/erp5_syncml/ToolComponentTemplateItem/portal_components/tool.erp5.SynchronizationTool.py
...teItem/portal_components/tool.erp5.SynchronizationTool.py
+11
-9
bt5/erp5_syncml/bt/skip_coding_style_test
bt5/erp5_syncml/bt/skip_coding_style_test
+0
-1
product/ERP5Type/XMLExportImport/__init__.py
product/ERP5Type/XMLExportImport/__init__.py
+16
-6
No files found.
bt5/erp5_syncml/DocumentTemplateItem/portal_components/document.erp5.SyncMLSignature.py
View file @
bf16fe93
...
...
@@ -28,6 +28,7 @@
##############################################################################
from
hashlib
import
md5
import
six
from
AccessControl
import
ClassSecurityInfo
...
...
@@ -98,7 +99,8 @@ class SyncMLSignature(XMLObject):
Set the XML corresponding to the object
"""
if
value
:
# convert the string to Pdata
assert
isinstance
(
value
,
bytes
)
# convert the bytes to Pdata
pdata_wrapper
=
PdataHelper
(
self
.
getPortalObject
(),
value
)
self
.
_setData
(
pdata_wrapper
)
self
.
setTemporaryData
(
None
)
# We make sure that the data will not be erased
...
...
@@ -113,7 +115,7 @@ class SyncMLSignature(XMLObject):
Get the XML corresponding to the object
"""
if
self
.
hasData
():
return
str
(
self
.
_baseGetData
())
return
bytes
(
self
.
_baseGetData
())
elif
default
is
_MARKER
:
return
self
.
_baseGetData
()
else
:
...
...
@@ -139,7 +141,7 @@ class SyncMLSignature(XMLObject):
Return the temp xml as string
"""
if
self
.
hasTemporaryData
():
return
str
(
self
.
_baseGetTemporaryData
())
return
bytes
(
self
.
_baseGetTemporaryData
())
elif
default
is
_MARKER
:
return
self
.
_baseGetTemporaryData
()
else
:
...
...
@@ -153,7 +155,7 @@ class SyncMLSignature(XMLObject):
changed or not
Returns 1 if MD5 are equals, else it returns 0
"""
if
isinstance
(
xml_string
,
unicod
e
):
if
six
.
PY2
and
isinstance
(
xml_string
,
six
.
text_typ
e
):
xml_string
=
xml_string
.
encode
(
'utf-8'
)
return
md5
(
xml_string
).
hexdigest
()
==
self
.
getContentMd5
()
...
...
@@ -189,7 +191,7 @@ class SyncMLSignature(XMLObject):
Return the patial xml as string
"""
if
self
.
hasPartialData
():
return
str
(
self
.
_baseGetPartialData
())
return
bytes
(
self
.
_baseGetPartialData
())
elif
default
is
_MARKER
:
return
self
.
_baseGetPartialData
()
else
:
...
...
@@ -223,7 +225,7 @@ class SyncMLSignature(XMLObject):
rest_in_queue
=
partial_data
[
max_len
:]
if
rest_in_queue
is
not
None
:
self
.
setPartialData
(
rest_in_queue
)
return
str
(
chunk
)
return
bytes
(
chunk
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'setSubscriberXupdate'
)
...
...
@@ -244,7 +246,7 @@ class SyncMLSignature(XMLObject):
Return the patial xml as string
"""
if
self
.
hasSubscriberXupdate
():
return
str
(
self
.
_baseGetSubscriberXupdate
())
return
bytes
(
self
.
_baseGetSubscriberXupdate
())
elif
default
is
_MARKER
:
return
self
.
_baseGetSubscriberXupdate
()
else
:
...
...
@@ -269,7 +271,7 @@ class SyncMLSignature(XMLObject):
Return the partial xml as string
"""
if
self
.
hasPublisherXupdate
():
return
str
(
self
.
_baseGetPublisherXupdate
())
return
bytes
(
self
.
_baseGetPublisherXupdate
())
elif
default
is
_MARKER
:
return
self
.
_baseGetPublisherXupdate
()
else
:
...
...
bt5/erp5_syncml/DocumentTemplateItem/portal_components/document.erp5.SyncMLSubscription.py
View file @
bf16fe93
...
...
@@ -32,7 +32,7 @@ from logging import getLogger
from
six.moves.urllib.parse
import
urlparse
from
lxml
import
etree
from
copy
import
deepcopy
from
six
import
string_types
as
basestring
import
six
from
AccessControl
import
ClassSecurityInfo
from
AccessControl.SecurityManagement
import
newSecurityManager
...
...
@@ -207,7 +207,7 @@ class SyncMLSubscription(XMLObject):
Return the path of the subscription that will be used in sql table
_ char must be escaped because of the LIKE behaviour
"""
return
"%s/%%"
%
(
self
.
getSourceValue
().
getPath
().
replace
(
"_"
,
"
\
_
"
),) # pylint: disable=anomalous-backslash-in-string
return
"%s/%%"
%
(
self
.
getSourceValue
().
getPath
().
replace
(
"_"
,
r"\
_
"),)
security.declarePrivate('sendSyncCommand')
def sendSyncCommand(self, min_gid, max_gid, message_id, activate_kw):
...
...
@@ -227,7 +227,7 @@ class SyncMLSubscription(XMLObject):
# transport failure
# activate_kw["
group_method_id
"] = None
# activate_kw["
group_method_cost
"] = .05
self.activate(**activate_kw).sendMessage(xml=
str
(syncml_response))
self.activate(**activate_kw).sendMessage(xml=
bytes
(syncml_response))
security.declarePrivate('applySyncCommand')
def applySyncCommand(self, response_message_id, activate_kw, **kw):
...
...
@@ -252,7 +252,7 @@ class SyncMLSubscription(XMLObject):
self.activate(activity="
SQLQueue
",
# group_method_id=None,
# group_method_cost=.05,
tag=activate_kw).sendMessage(xml=
str
(syncml_response))
tag=activate_kw).sendMessage(xml=
bytes
(syncml_response))
security.declarePrivate('getAndActivate')
...
...
@@ -533,7 +533,7 @@ class SyncMLSubscription(XMLObject):
domain=self))
xml_document = incoming_data
if not isinstance(xml_document, b
asestring
):
if not isinstance(xml_document, b
ytes
):
# XXX using deepcopy to remove parent link - must be done elsewhere
xml_document = deepcopy(xml_document)
# Remove useless namespace
...
...
@@ -541,7 +541,7 @@ class SyncMLSubscription(XMLObject):
xml_document = etree.tostring(xml_document, encoding='utf-8',
pretty_print=True)
if isinstance(xml_document, unicode):
if
six.PY2 and
isinstance(xml_document, unicode):
xml_document = xml_document.encode('utf-8')
# Link the signature to the document
if signature:
...
...
@@ -605,12 +605,12 @@ class SyncMLSubscription(XMLObject):
signature.changeToConflict()
# Register the data received which generated the diff
# XXX Why ?
if not isinstance(incoming_data, b
asestring
):
if not isinstance(incoming_data, b
ytes
):
incoming_data = etree.tostring(incoming_data,
encoding='utf-8')
signature.setPartialData(incoming_data)
else:
signature.setData(
str
(xml_document))
signature.setData(
bytes
(xml_document))
signature.synchronize()
syncml_logger.info("
change
state
of
signature
to
%
s
with
%
s
",
signature.getValidationState(), signature.getData())
...
...
@@ -669,7 +669,7 @@ class SyncMLSubscription(XMLObject):
}
syncml_logger.info("
Sending
final
message
for
modificationson
on
%
s
",
self.getRelativeUrl())
self.activate(**final_activate_kw).sendMessage(xml=
str
(syncml_response))
self.activate(**final_activate_kw).sendMessage(xml=
bytes
(syncml_response))
security.declarePrivate('getDeletedSyncMLData')
...
...
@@ -702,11 +702,10 @@ class SyncMLSubscription(XMLObject):
}
syncml_logger.info("
Sending
final
message
for
modificationson
on
%
s
",
self.getRelativeUrl())
self.activate(**final_activate_kw).sendMessage(xml=
str
(syncml_response))
self.activate(**final_activate_kw).sendMessage(xml=
bytes
(syncml_response))
def getSearchablePath(self):
return "
%
s
%%
" %(self.getPath().replace('_', '
\
_
'
),) # pylint: disable=anomalous-backslash-in-string
return "
%
s
%%
" %(self.getPath().replace('_', r'
\
_
'
),)
def _generateSyncCommand(self, action, signature, data_diff ,document_data, gid,
conduit, syncml_response):
...
...
@@ -975,10 +974,12 @@ class SyncMLSubscription(XMLObject):
# old way using the conduit
conduit = self.getConduit()
raw_gid = conduit.getGidFromObject(object)
if isinstance(raw_gid,
unicod
e):
if isinstance(raw_gid,
six.text_typ
e):
raw_gid = raw_gid.encode('ascii', 'ignore')
if encoded:
gid = b16encode(raw_gid)
if six.PY3:
gid = gid.decode()
else:
gid = raw_gid
return gid
...
...
bt5/erp5_syncml/MixinTemplateItem/portal_components/mixin.erp5.SyncMLEngineMixin.py
View file @
bf16fe93
...
...
@@ -25,6 +25,7 @@
#
##############################################################################
import
six
from
logging
import
getLogger
from
AccessControl
import
ClassSecurityInfo
,
getSecurityManager
...
...
@@ -337,8 +338,11 @@ class SyncMLEngineMixin(object):
if
syncml_request
.
credentials
[
'type'
]
==
publication
.
getAuthenticationType
():
decoded
=
decode
(
syncml_request
.
credentials
[
'format'
],
syncml_request
.
credentials
[
'data'
])
if
decoded
and
':'
in
decoded
:
login
,
password
=
decoded
.
split
(
':'
)
if
decoded
and
b':'
in
decoded
:
login
,
password
=
decoded
.
split
(
b':'
)
if
six
.
PY3
:
login
=
login
.
decode
()
password
=
password
.
decode
()
# TODO: make it work for users existing anywhere
user_folder
=
publication
.
getPortalObject
().
acl_users
for
_
,
plugin
in
user_folder
.
_getOb
(
'plugins'
)
\
...
...
@@ -463,8 +467,8 @@ class SyncMLEngineMixin(object):
# Wait for all reset to be done
# before starting sync
priority
=
ACTIVITY_PRIORITY
,
tag
=
publication
.
getRelativeUrl
()).
sendMessage
(
xml
=
str
(
syncml_response
))
tag
=
publication
.
getRelativeUrl
()).
sendMessage
(
xml
=
bytes
(
syncml_response
))
else
:
subscriber
.
sendMessage
(
xml
=
str
(
syncml_response
))
subscriber
.
sendMessage
(
xml
=
bytes
(
syncml_response
))
return
syncml_response
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.ERP5Conduit.py
View file @
bf16fe93
...
...
@@ -233,8 +233,8 @@ class ERP5Conduit(XMLSyncUtilsMixin):
def deleteWorkflowNode():
for wf_id, wf_history_tuple in six.iteritems(object.workflow_history):
for wf_history_index, wf_history in enumerate(wf_history_tuple):
if sha1(wf_id + str(wf_history['
time
']) +
wf_history['
actor
']).hexdigest() == wf_action_id:
if sha1(
(
wf_id + str(wf_history['
time
']) +
wf_history['
actor
']).
encode('
utf
-
8
')).
hexdigest() == wf_action_id:
object.workflow_history[wf_id] = (
object.workflow_history[wf_id][:wf_history_index] +
object.workflow_history[wf_id][wf_history_index + 1:])
...
...
@@ -428,21 +428,21 @@ class ERP5Conduit(XMLSyncUtilsMixin):
def getFormatedArgs(self, args=None):
"""
This lookd inside the args dictionnary and then
convert any unicode string to string
convert any unicode string to string
( on python 2 )
"""
new_args = {}
for keyword in args.keys():
data = args[keyword]
if
isinstance(keyword, unicod
e):
if
six.PY2 and isinstance(keyword, six.text_typ
e):
keyword = keyword.encode(self.getEncoding())
if isinstance(data, (tuple, list)):
new_data = []
for item in data:
if
isinstance(item, unicod
e):
if
six.PY2 and isinstance(item, six.text_typ
e):
item = item.encode(self.getEncoding())
new_data.append(item)
data = new_data
if
isinstance(data, unicod
e):
if
six.PY2 and isinstance(data, six.text_typ
e):
data = data.encode(self.getEncoding())
new_args[keyword] = data
return new_args
...
...
@@ -563,7 +563,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
XXX
name
of
method
is
not
good
,
because
content
is
not
necessarily
XML
return
a
xml
with
id
replaced
by
a
new
id
"""
if isinstance(xml,
str
):
if isinstance(xml,
bytes
):
xml = etree.XML(xml, parser=parser)
else:
# copy of xml object for modification
...
...
@@ -625,9 +625,10 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
if
xml
is
a
string
,
convert
it
to
a
node
"""
if xml is None: return None
if isinstance(xml, (str, unicode)):
if isinstance(xml, unicode):
if xml is None:
return None
if isinstance(xml, six.string_types + (bytes, )):
if six.PY2 and isinstance(xml, six.text_type):
xml = xml.encode('utf-8')
xml = etree.XML(xml, parser=parser)
# If we have the xml from the node erp5, we just take the subnode
...
...
@@ -780,7 +781,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
if data_type == NONE_TYPE:
return None
data = node.text
if data is not None and
isinstance(data, unicod
e):
if data is not None and
six.PY2 and isinstance(data, six.text_typ
e):
data = data.encode('utf-8')
elif data is None and data_type in TEXT_TYPE_LIST:
return ''
...
...
@@ -799,7 +800,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
elif data_type in DATA_TYPE_LIST:
if data is None:
# data is splitted inside block_data nodes
data = ''.join([standard_b64decode(block.text) for
\
data =
b
''.join([standard_b64decode(block.text) for
\
block in node.iterchildren()])
elif data_type == DATE_TYPE:
data = DateTime(data)
...
...
@@ -814,7 +815,7 @@ class ERP5Conduit(XMLSyncUtilsMixin):
Parse
the
xupdate
and
then
it
will
call
the
conduit
"""
conflict_list = []
if isinstance(xupdate,
(str, unicode
)):
if isinstance(xupdate,
six.string_types + (bytes,
)):
xupdate = etree.XML(xupdate, parser=parser)
#LOG("applyXupdate", INFO, etree.tostring(xupdate, pretty_print=True))
xupdate_builded = False
...
...
@@ -837,9 +838,11 @@ class ERP5Conduit(XMLSyncUtilsMixin):
break
# TODO add support of etree objects for xuproc to avoid
# serializing tree into string
if not isinstance(previous_xml, str):
previous_xml = etree.tostring(previous_xml)
xupdated_tree = xuproc.applyXUpdate(xml_xu_string=etree.tostring(xupdate),
if isinstance(previous_xml, bytes):
previous_xml = previous_xml.decode('utf-8')
if not isinstance(previous_xml, six.text_type):
previous_xml = etree.tostring(previous_xml, encoding='unicode')
xupdated_tree = xuproc.applyXUpdate(xml_xu_string=etree.tostring(xupdate, encoding='unicode'),
xml_doc_string=previous_xml)
if MARSHALLER_NAMESPACE_URI in subnode.nsmap.values():
xpath_expression = original_xpath_expression
...
...
@@ -1102,8 +1105,12 @@ class ERP5Conduit(XMLSyncUtilsMixin):
"""
# XXX xuproc does not support passing
# etree objetcs
if not isinstance(diff, basestring):
diff = etree.tostring(diff)
if isinstance(diff, bytes):
diff = diff.decode('utf-8')
elif not isinstance(diff, basestring):
diff = etree.tostring(diff, encoding='unicode')
if not isinstance(original_data, six.text_type):
original_data = six.text_type(original_data, 'utf-8')
return etree.tostring(xuproc.applyXUpdate(xml_xu_string=diff,
xml_doc_string=original_data),
encoding='utf-8')
...
...
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLEngineAsynchronous.py
View file @
bf16fe93
...
...
@@ -114,7 +114,7 @@ class SyncMLAsynchronousEngine(SyncMLEngineMixin):
(
subscription
.
getPath
(),
'applySyncCommand'
),
after_tag
=
tag
,).
sendMessage
(
xml
=
str
(
syncml_response
))
xml
=
bytes
(
syncml_response
))
# Synchronization process is now finished
syncml_logger
.
info
(
"
\
t
Client finished processing messages from server"
)
subscription
.
finish
()
...
...
@@ -138,7 +138,7 @@ class SyncMLAsynchronousEngine(SyncMLEngineMixin):
# transport failure
syncml_logger
.
info
(
"....client sending message...."
)
subscription
.
activate
(
activity
=
"SQLQueue"
).
sendMessage
(
xml
=
str
(
syncml_response
))
xml
=
bytes
(
syncml_response
))
def
processServerSynchronization
(
self
,
subscriber
,
syncml_request
):
...
...
@@ -242,7 +242,7 @@ class SyncMLAsynchronousEngine(SyncMLEngineMixin):
subscriber
.
activate
(
activity
=
"SQLQueue"
,
after_method_id
=
after_method_id
,
after_tag
=
tag
).
sendMessage
(
xml
=
str
(
syncml_response
))
xml
=
bytes
(
syncml_response
))
def
runGetAndActivate
(
self
,
subscription
,
tag
,
after_method_id
=
None
):
"""
...
...
@@ -295,7 +295,7 @@ class SyncMLAsynchronousEngine(SyncMLEngineMixin):
subscription
.
activate
(
activity
=
"SQLQueue"
,
priority
=
ACTIVITY_PRIORITY
,
tag
=
subscription
.
getRelativeUrl
()).
sendMessage
(
xml
=
str
(
syncml_response
))
tag
=
subscription
.
getRelativeUrl
()).
sendMessage
(
xml
=
bytes
(
syncml_response
))
else
:
# XXX For now always split by one
activate
=
subscription
.
activate
...
...
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLEngineSynchronous.py
View file @
bf16fe93
...
...
@@ -123,8 +123,9 @@ class SyncMLSynchronousEngine(SyncMLEngineMixin):
subscription
.
_edit
(
authenticated_user
=
None
)
# Send the message
subscription
.
sendMessage
(
xml
=
str
(
syncml_response
))
return
str
(
syncml_response
)
subscription
.
sendMessage
(
xml
=
bytes
(
syncml_response
))
return
bytes
(
syncml_response
)
def
processServerSynchronization
(
self
,
subscriber
,
syncml_request
):
...
...
@@ -222,10 +223,10 @@ class SyncMLSynchronousEngine(SyncMLEngineMixin):
subscriber
.
logout
()
subscriber
.
_edit
(
authenticated_user
=
None
,
remaining_object_path_list
=
None
)
syncml_response
=
""
# XXX This is expected by unit test only
syncml_response
=
b
""
# XXX This is expected by unit test only
# Body must be sent even when there is no data to notify client
subscriber
.
sendMessage
(
xml
=
str
(
syncml_response
))
subscriber
.
sendMessage
(
xml
=
bytes
(
syncml_response
))
# Return message for unit test purpose
return
str
(
syncml_response
)
return
bytes
(
syncml_response
)
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLMessage.py
View file @
bf16fe93
...
...
@@ -28,7 +28,7 @@
from
lxml.builder
import
ElementMaker
from
lxml.etree
import
Element
from
lxml
import
etree
from
six
import
string_types
as
basestring
import
six
from
erp5.component.module.XMLSyncUtils
import
resolveSyncmlStatusCode
,
\
encode
,
resolveSyncmlAlertCode
...
...
@@ -61,13 +61,13 @@ class SyncMLResponse(object):
def
__len__
(
self
):
# To check if it has to be done on whole message or only the body
return
len
(
etree
.
tostring
(
self
.
body
,
encoding
=
'utf-8'
,
xml_declaration
=
True
,
pretty_print
=
True
))
return
len
(
bytes
(
self
))
def
__
str
__
(
self
):
def
__
bytes
__
(
self
):
return
etree
.
tostring
(
self
.
data
,
encoding
=
'utf-8'
,
xml_declaration
=
True
,
pretty_print
=
True
)
if
six
.
PY2
:
__str__
=
__bytes__
def
_getNextCommandId
(
self
):
"""
...
...
@@ -118,7 +118,7 @@ class SyncMLResponse(object):
if
authentication_type
==
'syncml:auth-basic'
:
# base64 formating of "userid:password"
credential
=
"%s:%s"
%
(
user_id
,
password
)
credential
=
encode
(
authentication_format
,
credential
)
credential
=
encode
(
authentication_format
,
credential
)
.
decode
()
elif
authentication_type
==
"syncml:auth-md5"
:
# base64 coded md5 for user "XXX", password "XXX", nonce "XXX"
raise
NotImplementedError
(
"MD5 authentication not supported"
)
...
...
@@ -346,7 +346,7 @@ class SyncMLResponse(object):
data_node
=
E
.
Data
()
# XXX to be remove later to use only CDATA
if
media_type
==
'text/xml'
:
if
isinstance
(
data
,
b
asestring
):
if
isinstance
(
data
,
b
ytes
):
data_node
.
append
(
etree
.
XML
(
data
,
parser
=
parser
))
elif
isinstance
(
data
,
etree
.
CDATA
):
# data could be Data element if partial XML
...
...
@@ -422,7 +422,7 @@ class SyncMLRequest(object):
""" SyncMLRequest represent a message received by the client or server"""
def
__init__
(
self
,
xml
):
if
isinstance
(
xml
,
b
asestring
):
if
isinstance
(
xml
,
b
ytes
):
self
.
data
=
etree
.
XML
(
xml
,
parser
=
parser
)
else
:
raise
ValueError
(
"Do not know how to initialize message with data %r"
...
...
@@ -436,9 +436,11 @@ class SyncMLRequest(object):
self
.
isFinal
=
False
self
.
parse
()
def
__
str
__
(
self
):
def
__
bytes
__
(
self
):
return
etree
.
tostring
(
self
.
data
,
encoding
=
'utf-8'
,
xml_declaration
=
True
,
pretty_print
=
True
)
if
six
.
PY2
:
__str__
=
__bytes__
def
parse
(
self
):
"""
...
...
@@ -591,7 +593,6 @@ class SyncMLRequest(object):
parser_
=
etree
.
XMLParser
(
strip_cdata
=
False
)
cdata
=
etree
.
XML
(
data
,
parser_
)
data
=
cdata
.
text
# XXX this is unicode and can be a problem for activity
sync_command_kw
[
"raw_data"
]
=
data
sync_command_kw
[
"raw_data"
]
=
data
.
encode
()
append
(
sync_command_kw
)
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLTransportFile.py
View file @
bf16fe93
...
...
@@ -32,8 +32,7 @@ class FileTransport:
def
send
(
self
,
to_url
,
data
,
sync_id
,
content_type
):
filename
=
to_url
[
len
(
'file:/'
):]
try
:
stream
=
open
(
filename
,
'w'
)
stream
.
write
(
data
)
stream
.
close
()
with
open
(
filename
,
'wb'
)
as
stream
:
stream
.
write
(
data
)
except
IOError
:
raise
ConnectionError
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.SyncMLUtils.py
View file @
bf16fe93
...
...
@@ -38,7 +38,7 @@ from hashlib import md5
from
ZPublisher.HTTPRequest
import
FileUpload
from
OFS.Image
import
Pdata
from
six.moves
import
cStringIO
as
String
IO
from
io
import
Bytes
IO
import
transaction
class
PdataHelper
(
persistent
.
Persistent
):
...
...
@@ -68,14 +68,14 @@ class PdataHelper(persistent.Persistent):
n
=
self
.
_max_len
if
isinstance
(
value
,
(
str
,
unicode
)):
if
isinstance
(
value
,
unicod
e
):
if
isinstance
(
value
,
six
.
string_types
+
(
six
.
binary_type
,
)):
if
not
isinstance
(
value
,
six
.
binary_typ
e
):
value
=
value
.
encode
(
'utf-8'
)
size
=
len
(
value
)
size
=
len
(
value
)
if
size
<
n
:
return
Pdata
(
value
),
size
# Big
string
: cut it into smaller chunks
value
=
String
IO
(
value
)
# Big
data
: cut it into smaller chunks
value
=
Bytes
IO
(
value
)
if
isinstance
(
value
,
FileUpload
)
and
not
value
:
raise
ValueError
(
'File not specified'
)
...
...
@@ -161,11 +161,13 @@ class PdataHelper(persistent.Persistent):
"""
return
self
.
size
def
__
str
__
(
self
):
def
__
bytes
__
(
self
):
"""Return string concatenation
of all Pdata parts
"""
return
str
(
self
.
_data
)
return
bytes
(
self
.
_data
)
if
six
.
PY2
:
__str__
=
__bytes__
def
getContentMd5
(
self
):
"""
...
...
@@ -176,26 +178,20 @@ class PdataHelper(persistent.Persistent):
self
.
md5sum
=
md5sum
return
md5sum
def
__get
slice__
(
self
,
i
,
j
):
def
__get
item__
(
self
,
i
):
"""XXX Could be improved to avoid loading
into memory all Pdata objects
"""
return
self
.
__
str__
()[
i
:
j
]
return
self
.
__
bytes__
()[
i
]
def
getLastPdata
(
self
):
"""return the last Pdata element
of a Pdata chains
"""
pdata
=
self
.
_data
if
six
.
PY2
:
next_
=
pdata
.
next
else
:
next_
=
pdata
.
__next__
next_
=
pdata
.
next
while
next_
is
not
None
:
pdata
=
next_
if
six
.
PY2
:
next_
=
pdata
.
next
else
:
next_
=
pdata
.
__next__
next_
=
pdata
.
next
return
pdata
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.VCardConduit.py
View file @
bf16fe93
...
...
@@ -31,6 +31,7 @@ from erp5.component.module.ERP5Conduit import ERP5Conduit
from
AccessControl
import
ClassSecurityInfo
from
Products.ERP5Type
import
Permissions
import
difflib
import
six
from
zLOG
import
LOG
...
...
@@ -56,7 +57,7 @@ class VCardConduit(ERP5Conduit):
"""
#LOG('VCardConduit',0,'addNode, object=%s, object_id=%s, sub_object:%s, \
#xml:\n%s' % (str(object), str(object_id), str(sub_object), xml))
if
not
isinstance
(
xml
,
str
):
if
not
isinstance
(
xml
,
bytes
):
xml
=
self
.
nodeToString
(
xml
)
portal_type
=
'Person'
#the VCard can just use Person
if
sub_object
is
None
:
...
...
@@ -161,7 +162,9 @@ class VCardConduit(ERP5Conduit):
convert_dict
[
'N'
]
=
'last_name'
convert_dict
[
'TEL'
]
=
'default_telephone_text'
edit_dict
=
{}
vcard_list
=
vcard
.
split
(
'
\
n
'
)
if
isinstance
(
vcard
,
bytes
):
vcard
=
vcard
.
decode
(
'utf-8'
)
vcard_list
=
vcard
.
splitlines
()
for
vcard_line
in
vcard_list
:
if
':'
in
vcard_line
:
property_
,
property_value
=
vcard_line
.
split
(
':'
)
...
...
@@ -192,12 +195,12 @@ class VCardConduit(ERP5Conduit):
else
:
property_name
=
property_
if
isinstance
(
property_name
,
unicod
e
):
if
six
.
PY2
and
isinstance
(
property_name
,
six
.
text_typ
e
):
property_name
=
property_name
.
encode
(
'utf-8'
)
tmp
=
[]
for
property_value
in
property_value_list
:
if
isinstance
(
property_value
,
unicod
e
):
if
six
.
PY2
and
isinstance
(
property_value
,
six
.
text_typ
e
):
property_value
=
property_value
.
encode
(
'utf-8'
)
tmp
.
append
(
property_value
)
property_value_list
=
tmp
...
...
@@ -226,6 +229,10 @@ class VCardConduit(ERP5Conduit):
def
generateDiff
(
self
,
new_data
,
former_data
):
"""return unified diff for plain-text documents
"""
if
isinstance
(
new_data
,
bytes
):
new_data
=
new_data
.
decode
(
'utf-8'
)
if
isinstance
(
former_data
,
bytes
):
former_data
=
former_data
.
decode
(
'utf-8'
)
diff
=
'
\
n
'
.
join
(
difflib
.
unified_diff
(
new_data
.
splitlines
(),
former_data
.
splitlines
()))
return
diff
...
...
bt5/erp5_syncml/ModuleComponentTemplateItem/portal_components/module.erp5.XMLSyncUtils.py
View file @
bf16fe93
...
...
@@ -29,6 +29,7 @@
import
smtplib
import
os
import
six
from
base64
import
b64encode
,
b64decode
from
lxml
import
etree
from
lxml.builder
import
ElementMaker
...
...
@@ -58,7 +59,10 @@ def encode(format, string_to_encode): # pylint: disable=redefined-builtin
if
not
format
:
return
string_to_encode
if
format
==
'b64'
:
return
b64encode
(
string_to_encode
)
if
not
isinstance
(
string_to_encode
,
six
.
binary_type
):
string_to_encode
=
string_to_encode
.
encode
()
encoded
=
b64encode
(
string_to_encode
)
return
encoded
#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 : '
,
INFO
,
format
)
...
...
@@ -180,11 +184,10 @@ def getXupdateObject(object_xml=None, old_xml=None):
"""
erp5diff
=
ERP5Diff
()
erp5diff
.
compare
(
old_xml
,
object_xml
)
#Upper version of ERP5Diff produce valid XML.
if
erp5diff
.
_getResultRoot
():
xupdate
=
erp5diff
.
output
String
(
)
#omit xml declaration
xupdate
=
xupdate
[
xupdate
.
find
(
'<xupdate:modifications'
):]
xupdate
=
erp5diff
.
output
Bytes
(
encoding
=
"utf-8"
)
#
omit xml declaration
xupdate
=
xupdate
[
xupdate
.
find
(
b
'<xupdate:modifications'
):]
return
xupdate
def
cutXML
(
xml_string
,
length
=
None
):
...
...
bt5/erp5_syncml/SkinTemplateItem/portal_skins/erp5_syncml/Person_exportAsVCard.py
View file @
bf16fe93
...
...
@@ -3,13 +3,6 @@ first_name = context.getFirstName()
last_name
=
context
.
getLastName
()
tel
=
context
.
getDefaultTelephoneTelephoneNumber
()
if
same_type
(
first_name
,
u'a'
):
first_name
=
first_name
.
encode
(
'utf-8'
)
if
same_type
(
last_name
,
u'a'
):
last_name
=
last_name
.
encode
(
'utf-8'
)
if
same_type
(
tel
,
u'a'
)
:
tel
=
tel
.
encode
(
'utf-8'
)
parameters_FN
=
''
parameters_N
=
''
...
...
bt5/erp5_syncml/TestTemplateItem/portal_components/test.erp5.testERP5DocumentSyncML.py
View file @
bf16fe93
...
...
@@ -55,9 +55,9 @@ class TestERP5DocumentSyncMLMixin(TestERP5SyncMLMixin):
nb_objects
=
10
#for objects
ids
=
range
(
1
,
nb_objects
+
1
)
ids
=
list
(
range
(
1
,
nb_objects
+
1
)
)
#id_max_text : number of document text
id_max_text
=
nb_objects
/
2
id_max_text
=
nb_objects
//
2
id1
=
'2'
id2
=
'3'
#for documents (encoding in unicode for utf-8)
...
...
@@ -644,7 +644,7 @@ class TestERP5DocumentSyncML(TestERP5DocumentSyncMLMixin):
publication
=
portal_sync
[
self
.
pub_id
]
self
.
assertEqual
(
len
(
publication
[
'1'
]),
nb_document
)
gid
=
self
.
reference1
+
'-'
+
self
.
version1
+
'-'
+
self
.
language1
# ie the title ''
gid
=
b16encode
(
gid
)
gid
=
b16encode
(
gid
.
encode
()).
decode
(
)
document_c1
=
subscription1
.
getDocumentFromGid
(
gid
)
document_s
=
publication
.
getSubscriber
(
self
.
subscription_url
[
'two_way'
]).
getDocumentFromGid
(
gid
)
id_s
=
document_s
.
getId
()
...
...
bt5/erp5_syncml/TestTemplateItem/portal_components/test.erp5.testERP5SyncML.py
View file @
bf16fe93
...
...
@@ -1097,7 +1097,7 @@ return [context[%r]]
publication
=
portal_sync
[
self
.
pub_id
]
self
.
assertEqual
(
len
(
publication
.
getDocumentList
()),
nb_person
)
gid
=
self
.
first_name1
+
' '
+
self
.
last_name1
# ie the title 'Sebastien Robin'
gid
=
b16encode
(
gid
)
gid
=
b16encode
(
gid
.
encode
()).
decode
(
)
person_c1
=
subscription1
.
getDocumentFromGid
(
gid
)
person_s
=
publication
.
getSubscriber
(
self
.
subscription_url1
).
getDocumentFromGid
(
gid
)
id_s
=
person_s
.
getId
()
...
...
@@ -1689,31 +1689,26 @@ return [context[%r]]
self
.
test_08_FirstSynchronization
()
#define some strings :
python
=
'www.python.org'
awaited_result_python
=
"d3d3LnB5dGhvbi5vcmc="
long_string
=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
\
PQRSTUVWXYZéèçà@^~µ&²0123456789!@#0^&*();:<>,. []{}
\
xc3
\
xa7
sdf__
\
sdf
\
xc3
\
xa7
\
xc3
\
xa7
\
xc3
\
xa7
_df___&&
\
xc3
\
xa9
]]]
\
xc2
\
xb0
\
xc2
\
xb0
\
xc2
\
\
xb0
\
xc2
\
xb0
\
xc2
\
xb0
\
xc2
\
xb0
"
#= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZéèçà@^~µ&²012345
#6789!@#0^&*();:<>,. []{}çsdf__sdfççç_df___&&é]]]°°°°°°'"
awaited_result_long_string
=
"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZH
\
SElKS0xNTk9QUVJTVFVWV1hZWsOpw6jDp8OgQF5+wrUmwrIwMTIzNDU2Nzg5IUAjMF4mKigpOzo8Pi
\
wuIFtde33Dp3NkZl9fc2Rmw6fDp8OnX2RmX19fJibDqV1dXcKwwrDCsMKwwrDCsA=="
python
=
b'www.python.org'
awaited_result_python
=
b"d3d3LnB5dGhvbi5vcmc="
long_string
=
u"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZéèçà@^~µ&²0123456789"
\
u"!@#0^&*();:<>,. []{}çsdf__sdfççç_df___&&é]]]°°°°°°'"
.
encode
(
'utf-8'
)
awaited_result_long_string
=
b'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUZH'
\
b'SElKS0xNTk9QUVJTVFVWV1hZWsOpw6jDp8OgQF5+wrUmwrIwMTIzNDU2Nzg5IUAjMF4mKigpO'
\
b'zo8PiwuIFtde33Dp3NkZl9fc2Rmw6fDp8OnX2RmX19fJibDqV1dXcKwwrDCsMKwwrDCsCc='
#test just b64encode
self
.
assertEqual
(
b64encode
(
python
),
awaited_result_python
)
self
.
assertEqual
(
b64encode
(
""
),
""
)
self
.
assertEqual
(
b64encode
(
b""
),
b
""
)
self
.
assertEqual
(
b64encode
(
long_string
),
awaited_result_long_string
)
self
.
assertEqual
(
b64decode
(
awaited_result_python
),
python
)
self
.
assertEqual
(
b64decode
(
""
),
""
)
self
.
assertEqual
(
b64decode
(
b""
),
b
""
)
self
.
assertEqual
(
b64decode
(
awaited_result_long_string
),
long_string
)
# test with the ERP5 functions
string_encoded
=
encode
(
'b64'
,
python
)
self
.
assertEqual
(
string_encoded
,
awaited_result_python
)
string_decoded
=
decode
(
'b64'
,
awaited_result_python
)
string_decoded
=
decode
(
'b64'
,
awaited_result_python
.
decode
()
)
self
.
assertEqual
(
string_decoded
,
python
)
self
.
assertTrue
(
isDecodeEncodeTheSame
(
string_encoded
,
python
,
'b64'
))
...
...
@@ -1722,17 +1717,17 @@ wuIFtde33Dp3NkZl9fc2Rmw6fDp8OnX2RmX19fJibDqV1dXcKwwrDCsMKwwrDCsA=="
string_encoded
=
encode
(
'b64'
,
long_string
)
self
.
assertEqual
(
string_encoded
,
awaited_result_long_string
)
string_decoded
=
decode
(
'b64'
,
awaited_result_long_string
)
string_decoded
=
decode
(
'b64'
,
awaited_result_long_string
.
decode
()
)
self
.
assertEqual
(
string_decoded
,
long_string
)
self
.
assertTrue
(
isDecodeEncodeTheSame
(
string_encoded
,
long_string
,
'b64'
))
self
.
assertTrue
(
isDecodeEncodeTheSame
(
string_encoded
,
string_decoded
,
'b64'
))
self
.
assertEqual
(
encode
(
'b64'
,
''
),
''
)
self
.
assertEqual
(
decode
(
'b64'
,
''
),
''
)
self
.
assertEqual
(
encode
(
'b64'
,
b''
),
b
''
)
self
.
assertEqual
(
decode
(
'b64'
,
''
),
b
''
)
self
.
assertTrue
(
isDecodeEncodeTheSame
(
encode
(
'b64'
,
''
),
''
,
'b64'
))
encode
(
'b64'
,
''
),
b
''
,
'b64'
))
def
test_35_authentication
(
self
):
"""
...
...
bt5/erp5_syncml/ToolComponentTemplateItem/portal_components/tool.erp5.SynchronizationTool.py
View file @
bf16fe93
...
...
@@ -26,7 +26,7 @@
##############################################################################
from
logging
import
getLogger
from
six
import
string_types
as
basestring
import
six
from
AccessControl
import
ClassSecurityInfo
...
...
@@ -185,8 +185,7 @@ class SynchronizationTool(BaseTool):
#
security
.
declarePublic
(
'readResponse'
)
def
readResponse
(
self
,
text
=
''
,
sync_id
=
None
,
from_url
=
None
):
"""
We will look at the url and we will see if we need to send mail, http
"""We will look at the url and we will see if we need to send mail, http
response, or just copy to a file.
"""
syncml_logger
.
info
(
'readResponse sync_id %s, text %s'
,
sync_id
,
text
)
...
...
@@ -194,6 +193,9 @@ class SynchronizationTool(BaseTool):
# we are still anonymous at this time, use unrestrictedSearchResults
# to fetch the Subcribers
catalog_tool
=
self
.
getPortalObject
().
portal_catalog
.
unrestrictedSearchResults
if
isinstance
(
text
,
six
.
text_type
):
text
=
text
.
encode
(
'utf-8'
)
syncml_request
=
SyncMLRequest
(
text
)
# It is assumed that client & server does not share the same database ID
...
...
@@ -234,12 +236,12 @@ class SynchronizationTool(BaseTool):
%
(
sync_id
,
syncml_request
.
header
[
'target'
]))
# we use from only if we have a file
elif
isinstance
(
from_url
,
basestring
):
elif
isinstance
(
from_url
,
six
.
string_types
):
if
from_url
.
startswith
(
'file:'
):
filename
=
from_url
[
len
(
'file:'
):]
xml
=
None
try
:
stream
=
open
(
filename
,
'r'
)
stream
=
open
(
filename
,
'r
b
'
)
except
IOError
:
# XXX-Aurel : Why raising here make unit tests to fail ?
# raise ValueError("Impossible to read file %s, error is %s"
...
...
@@ -314,7 +316,7 @@ class SynchronizationTool(BaseTool):
raise
NotImplementedError
(
"Starting sync process from server is forbidden"
)
# Return message for unit test purpose
return
str
(
syncml_response
)
return
bytes
(
syncml_response
)
#
# Following methods are related to client (subscription)
...
...
@@ -363,10 +365,10 @@ class SynchronizationTool(BaseTool):
'getAndIndex'
,
'SQLCatalog_indexSyncMLDocumentList'
),
priority
=
ACTIVITY_PRIORITY
,
tag
=
subscription
.
getRelativeUrl
()).
sendMessage
(
str
(
syncml_response
))
tag
=
subscription
.
getRelativeUrl
()).
sendMessage
(
bytes
(
syncml_response
))
else
:
subscription
.
sendMessage
(
str
(
syncml_response
))
subscription
.
sendMessage
(
bytes
(
syncml_response
))
return
str
(
syncml_response
)
return
bytes
(
syncml_response
)
InitializeClass
(
SynchronizationTool
)
bt5/erp5_syncml/bt/skip_coding_style_test
deleted
100644 → 0
View file @
4dee881e
1
\ No newline at end of file
product/ERP5Type/XMLExportImport/__init__.py
View file @
bf16fe93
...
...
@@ -125,7 +125,7 @@ def Base_asXML(object, root=None):
# Create blocks to represent data
# <data><block>ZERD</block><block>OEJJM</block></data>
size_block
=
60
if
isinstance
(
value
,
str
):
if
isinstance
(
value
,
bytes
):
for
index
in
xrange
(
0
,
len
(
value
),
size_block
):
content
=
value
[
index
:
index
+
size_block
]
data_encoded
=
standard_b64encode
(
content
)
...
...
@@ -138,7 +138,10 @@ def Base_asXML(object, root=None):
for
word
in
value
]
sub_object
.
append
(
marshaller
(
value
))
elif
prop_type
in
(
'text'
,
'string'
,):
sub_object
.
text
=
six
.
text_type
(
escape
(
value
),
'utf-8'
)
value
=
escape
(
value
)
if
six
.
PY2
:
value
=
six
.
text_type
(
value
,
'utf-8'
)
sub_object
.
text
=
value
elif
prop_type
!=
'None'
:
sub_object
.
text
=
str
(
value
)
...
...
@@ -162,15 +165,22 @@ def Base_asXML(object, root=None):
variable_node
=
SubElement
(
workflow_node
,
workflow_variable
,
attrib
=
dict
(
type
=
variable_type
))
if
variable_type
!=
'None'
:
variable_node
.
text
=
six
.
text_type
(
str
(
variable_node_text
),
'utf-8'
)
variable_node_text
=
str
(
variable_node_text
)
if
six
.
PY2
:
variable_node_text
=
six
.
text_type
(
str
(
variable_node_text
),
'utf-8'
)
variable_node
.
text
=
variable_node_text
if
workflow_variable
==
'time'
:
time
=
variable_node
.
text
elif
workflow_variable
==
'actor'
:
actor
=
variable_node
.
text
workflow_node
.
attrib
[
'id'
]
=
sha1
(
workflow_id
+
time
+
str
(
actor
.
encode
(
'utf-8'
))).
hexdigest
()
if
six
.
PY2
and
isinstance
(
actor
,
six
.
text_type
):
actor
=
actor
.
encode
(
'utf-8'
)
workflow_transition_id
=
workflow_id
+
time
+
actor
if
six
.
PY3
:
workflow_transition_id
=
workflow_transition_id
.
encode
()
workflow_node
.
attrib
[
'id'
]
=
sha1
(
workflow_transition_id
).
hexdigest
()
# We should now describe security settings
for
user_role
in
self
.
get_local_roles
():
...
...
@@ -179,7 +189,7 @@ def Base_asXML(object, root=None):
#convert local_roles in string because marshaller can't do it
role_list
=
[]
for
role
in
user_role
[
1
]:
if
isinstance
(
role
,
six
.
text_type
):
if
six
.
PY2
and
isinstance
(
role
,
six
.
text_type
):
role
=
role
.
encode
(
'utf-8'
)
role_list
.
append
(
role
)
local_role_node
.
append
(
marshaller
(
tuple
(
role_list
)))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment