diff --git a/product/ERP5Form/FormulatorPatch.py b/product/ERP5Form/FormulatorPatch.py
new file mode 100755
index 0000000000000000000000000000000000000000..e36088b28169e2385e979e89e32f09aa71f3e5dc
--- /dev/null
+++ b/product/ERP5Form/FormulatorPatch.py
@@ -0,0 +1,183 @@
+##############################################################################
+#
+# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
+# Copyright (c) 2003 Nexedi SARL and Contributors. All Rights Reserved.
+#          Sebastien Robin <seb@nexedi.com>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+
+from Products.Formulator.Field import Field
+from AccessControl import ClassSecurityInfo
+
+class PatchedField:
+
+    security = ClassSecurityInfo()
+
+    security.declareProtected('Access contents information',
+                              'generate_field_key')
+    def generate_field_key(self, validation=0, key=None):
+        """Generate the key Silva uses to render the field in the form.
+        """
+        # Patched by JPS for ERP5 in order to
+        # dynamically change the name
+        if key is not None:
+          return 'field_%s' % key
+        if self.field_record is None:
+            return 'field_%s' % self.id
+        elif validation:
+            return self.id
+        elif isinstance(self.widget, MultiItemsWidget):
+            return "%s.%s:record:list" % (self.field_record, self.id)
+        else:
+            return '%s.%s:record' % (self.field_record, self.id)
+
+    security.declareProtected('View', 'render')
+    def render(self, value=None, REQUEST=None, key=None):
+        """Render the field widget.
+        value -- the value the field should have (for instance
+                 from validation).
+        REQUEST -- REQUEST can contain raw (unvalidated) field
+                 information. If value is None, REQUEST is searched
+                 for this value.
+        if value and REQUEST are both None, the 'default' property of
+        the field will be used for the value.
+        """
+        return self._render_helper(self.generate_field_key(key=key), value, REQUEST)
+
+Field.generate_field_key = PatchedField.generate_field_key
+Field.render = PatchedField.render
+
+from Products.Formulator.Validator import SelectionValidator
+from Products.Formulator.Validator import StringBaseValidator
+
+def SelectionValidator_validate(self, field, key, REQUEST):
+    value = StringBaseValidator.validate(self, field, key, REQUEST)
+
+    if value == "" and not field.get_value('required'):
+        return value
+
+    # get the text and the value from the list of items
+    # Patch by JPS for Listbox cell
+    for item in field.get_value('items', cell=getattr(REQUEST,'cell',None)):
+        try:
+            item_text, item_value = item
+        except ValueError:
+            item_text = item
+            item_value = item
+
+        # check if the value is equal to the string/unicode version of
+        # item_value; if that's the case, we can return the *original*
+        # value in the list (not the submitted value). This way, integers
+        # will remain integers.
+        # XXX it is impossible with the UI currently to fill in unicode
+        # items, but it's possible to do it with the TALES tab
+        if field.get_value('unicode') and type(item_value) == type(u''):
+            str_value = item_value.encode(field.get_form_encoding())
+        else:
+            str_value = str(item_value)
+
+        if str_value == value:
+            return item_value
+
+    # if we didn't find the value, return error
+    self.raise_error('unknown_selection', field)
+
+SelectionValidator.validate = SelectionValidator_validate
+
+from Products.Formulator.Validator import MultiSelectionValidator
+
+def MultiSelectionValidator_validate(self, field, key, REQUEST):
+    values = REQUEST.get(key, [])
+    # NOTE: a hack to deal with single item selections
+    if type(values) is not type([]):
+        # put whatever we got in a list
+        values = [values]
+    # if we selected nothing and entry is required, give error, otherwise
+    # give entry list
+    if len(values) == 0:
+        if field.get_value('required'):
+            self.raise_error('required_not_found', field)
+        else:
+            return values
+    # convert everything to unicode if necessary
+    if field.get_value('unicode'):
+        values = [unicode(value, field.get_form_encoding())
+                  for value in values]
+
+    # create a dictionary of possible values
+    value_dict = {}
+    for item in field.get_value('items', cell=getattr(REQUEST,'cell',None)): # Patch by JPS for Listbox
+        try:
+            item_text, item_value = item
+        except ValueError:
+            item_text = item
+            item_value = item
+        value_dict[item_value] = 0
+
+    # check whether all values are in dictionary
+    result = []
+    for value in values:
+        # FIXME: hack to accept int values as well
+        try:
+            int_value = int(value)
+        except ValueError:
+            int_value = None
+        if int_value is not None and value_dict.has_key(int_value):
+            result.append(int_value)
+            continue
+        if value_dict.has_key(value):
+            result.append(value)
+            continue
+        self.raise_error('unknown_selection', field)
+    # everything checks out
+    return result
+
+MultiSelectionValidator.validate = MultiSelectionValidator_validate
+
+from Products.Formulator.Validator import BooleanValidator
+
+def BooleanValidator_validate(self, field, key, REQUEST):
+    result = not not REQUEST.get(key, 0)
+    if result==True:
+       return 1
+    else:
+       return 0
+
+BooleanValidator.validate = BooleanValidator_validate 
+
+# Patch the render_view of a TextAreaWidget so that 
+# it is rendered as a nice box, it is using the tag 
+# readonly understood by most browsers for a text area
+
+from Products.Formulator.Widget import TextAreaWidget
+from Products.Formulator.Widget import render_element
+from DocumentTemplate.DT_Util import html_quote
+
+def TextAreaWidget_render_view(self, field, value):
+    width = field.get_value('width')
+    height = field.get_value('height')
+
+    return render_element("textarea",
+                          name='',
+                          css_class=field.get_value('css_class'),
+                          cols=width,
+                          rows=height,
+                          contents=html_quote(value),
+                          extra='readonly')
+
+TextAreaWidget.render_view = TextAreaWidget_render_view
+
diff --git a/product/ERP5SyncML/help/install.stx b/product/ERP5SyncML/help/install.stx
new file mode 100755
index 0000000000000000000000000000000000000000..d1ff44370720f4ee77b14b135b58089a4c7dc692
--- /dev/null
+++ b/product/ERP5SyncML/help/install.stx
@@ -0,0 +1,13 @@
+Setting up Synchronization
+
+  Installing packages
+
+    First install zope and all products you might need (CPS...)
+    Then install products ERP5Type, CMFActivity, ERP5SyncML.
+    available with the nexedi cvs.
+    And also CMFWiki, psyco, available from zope and python. You will
+    also need xml for python.
+
+    If you want the synchronization working with CPS, you will need
+    need the ERP5CPS products, available on the nexedi cvs.
+