diff --git a/product/ERP5Subversion/SubversionClient.py b/product/ERP5Subversion/SubversionClient.py
index 770247c5001a3c752b8616133f02562a5d0fe9e0..59c836751d206021a0129dcc7c715fa9b7fe96d4 100644
--- a/product/ERP5Subversion/SubversionClient.py
+++ b/product/ERP5Subversion/SubversionClient.py
@@ -34,6 +34,7 @@ from MethodObject import Method
 from Globals import InitializeClass
 from AccessControl import ClassSecurityInfo
 from Products.ERP5Type import Permissions
+from zLOG import LOG
 
 try:
   import pysvn
@@ -229,7 +230,11 @@ try:
     def diff(self, path):
       self._getPreferences()
       os.system('mkdir -p /tmp/tmp-svn/')
-      return self.client.diff('/tmp/tmp-svn',path)
+      return self.client.diff(tmp_path='/tmp/tmp-svn/', url_or_path=path, recurse=False)
+    
+    def revert(self, path):
+      self._getPreferences()
+      return self.client.revert(path)
 
   def newSubversionClient(container, **kw):
     return SubversionClient(**kw).__of__(container)
diff --git a/product/ERP5Subversion/Tool/SubversionTool.py b/product/ERP5Subversion/Tool/SubversionTool.py
index aa3989610de4968a2125161dd77ed04bbaa440f1..1a4d8485d39b218f52fb6fb8dad99ab7045ccb9c 100644
--- a/product/ERP5Subversion/Tool/SubversionTool.py
+++ b/product/ERP5Subversion/Tool/SubversionTool.py
@@ -34,7 +34,7 @@ from Products.ERP5Type import Permissions
 from Products.ERP5Subversion import _dtmldir
 from zLOG import LOG, WARNING, INFO
 from Products.ERP5Subversion.SubversionClient import newSubversionClient
-import os
+import os, re
 from DateTime import DateTime
 from cPickle import dumps, loads
 from App.config import getConfiguration
@@ -73,6 +73,221 @@ class Dir :
       if d.name == name:
         return d
 ## End of Dir Class
+
+class DiffFile:
+  # Members :
+  # - path : path of the modified file
+  # - children : sub codes modified
+  # - old_revision
+  # - new_revision
+
+  def __init__(this, raw_diff):
+    this.header = raw_diff.split('@@')[0][:-1]
+    # Getting file path in header
+    this.path = this.header.split('====')[0][:-1].strip()
+    # Getting revisions in header
+    for line in this.header.split('\n'):
+      if line.startswith('--- '):
+        tmp = re.search('\\([\w\s]+\\)$', line)
+        this.old_revision = tmp.string[tmp.start():tmp.end()][1:-1].strip()
+      if line.startswith('+++ '):
+        tmp = re.search('\\([\w\s]+\\)$', line)
+        this.new_revision = tmp.string[tmp.start():tmp.end()][1:-1].strip()
+    # Splitting the body from the header
+    this.body = '\n'.join(raw_diff.strip().split('\n')[4:])
+    # Now splitting modifications
+    this.children = []
+    first = True
+    tmp = []
+    for line in this.body.split('\n'):
+      if line:
+        if line.startswith('@@') and not first:
+          this.children.append(CodeBlock('\n'.join(tmp)))
+          tmp = [line,]
+        else:
+          first = False
+          tmp.append(line)
+    this.children.append(CodeBlock('\n'.join(tmp)))
+    
+
+  def _escape(this, data):
+    """
+      Escape &, <, and > in a string of data.
+      This is a copy of the xml.sax.saxutils.escape function.
+    """
+    # must do ampersand first
+    if data:
+      #data = data.replace("&", "&amp;")
+      data = data.replace(">", "&gt;")
+      data = data.replace("<", "&lt;")
+      return data
+    
+  def toHTML(this):
+    # Adding header of the table
+    html = '''<font color='black'><b>%s</b><br>
+    <hr><br>
+    <table style="text-align: left; width: 100%%;" border="0" cellpadding="0" cellspacing="0">
+  <tbody>
+    <tr height="18px">
+      <td style="background-color: grey"><b><center>%s</center></b></td>
+      <td style="background-color: grey"><b><center>%s</center></b></td>
+    </tr>'''%(this.path, this.old_revision, this.new_revision)
+    First = True
+    for child in this.children:
+      # Adding line number of the modification
+      if First:
+        html += '''<tr height="18px"><td style="background-color: grey">&nbsp;</td><td style="background-color: grey">&nbsp;</td></tr>    <tr>
+        <td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
+        <td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
+      </tr>'''%(child.old_line, child.new_line)
+        First = False
+      else:
+        html += '''<tr height="18px"><td style="background-color: white">&nbsp;</td><td style="background-color: white">&nbsp;</td></tr>    <tr>
+        <td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
+        <td style="background-color: rgb(68, 132, 255);"><b>Line %s</b></td>
+      </tr>'''%(child.old_line, child.new_line) 
+      # Adding diff of the modification
+      old_code_list = child.getOldCodeList()
+      new_code_list = child.getNewCodeList()
+      i=0
+      for old_line_tuple in old_code_list:
+        new_line_tuple = new_code_list[i]
+        if new_line_tuple[0]:
+          new_line = new_line_tuple[0]
+        else:
+          new_line = ' '
+        if old_line_tuple[0]:
+          old_line = old_line_tuple[0]
+        else:
+          old_line = ' '
+        i+=1
+        html += '''    <tr height="18px">
+      <td style="background-color: %s">%s</td>
+      <td style="background-color: %s">%s</td>
+    </tr>'''%(old_line_tuple[1], this._escape(old_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'), new_line_tuple[1], this._escape(new_line).replace(' ', '&nbsp;').replace('\t', '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'))
+    html += '''  </tbody>
+</table></font><br><br>'''
+    return html
+      
+
+# A code block contains several SubCodeBlocks
+class CodeBlock:
+  # Members :
+  # - old_line : line in old code (before modif)
+  # - new line : line in new code (after modif)
+  #
+  # Methods :
+  # - getOldCodeList() : return code before modif
+  # - getNewCodeList() : return code after modif
+  # Note: the code returned is a list of tuples (code line, background color)
+
+  def __init__(this, raw_diff):
+    # Splitting body and header
+    this.body = '\n'.join(raw_diff.split('\n')[1:])
+    this.header = raw_diff.split('\n')[0]
+    # Getting modifications lines
+    tmp = re.search('^@@ -\d+', this.header)
+    this.old_line = tmp.string[tmp.start():tmp.end()][4:]
+    tmp = re.search('\+\d+,', this.header)
+    this.new_line = tmp.string[tmp.start():tmp.end()][1:-1]
+    # Splitting modifications in SubCodeBlocks
+    in_modif = False
+    this.children = []
+    tmp=[]
+    for line in this.body.split('\n'):
+      if line:
+        if (line.startswith('+') or line.startswith('-')):
+          if in_modif:
+            tmp.append(line)
+          else:
+            this.children.append(SubCodeBlock('\n'.join(tmp)))
+            tmp = [line,]
+            in_modif = True
+        else:
+            if in_modif:
+              this.children.append(SubCodeBlock('\n'.join(tmp)))
+              tmp = [line,]
+              in_modif = False
+            else:
+              tmp.append(line)
+    this.children.append(SubCodeBlock('\n'.join(tmp)))
+    
+  # Return code before modification
+  def getOldCodeList(this):
+    tmp = []
+    for child in this.children:
+      tmp.extend(child.getOldCodeList())
+    return tmp
+    
+  # Return code after modification
+  def getNewCodeList(this):
+    tmp = []
+    for child in this.children:
+      tmp.extend(child.getNewCodeList())
+    return tmp
+    
+# a SubCodeBlock contain 0 or 1 modification (not more)
+class SubCodeBlock:
+  def __init__(this, code):
+    this.body=code
+    this.modification=this._getModif()
+    # Choosing background color
+    if this.modification == 'none':
+      this.color = 'white'
+    elif this.modification == 'change':
+      this.color = 'rgb(253, 228, 6);'#light orange
+    elif this.modification == 'deletion':
+      this.color = 'rgb(253, 117, 74);'#light red
+    else:
+      this.color = 'rgb(83, 253, 74);'#light green
+    
+  def _getModif(this):
+    nb_plus = 0
+    nb_minus = 0
+    for line in this.body.split('\n'):
+      if line.startswith("-"):
+        nb_minus-=1
+      elif line.startswith("+"):
+        nb_plus+=1
+    if (nb_plus!=0 and nb_minus==0):
+      return 'addition'
+    if (nb_plus==0 and nb_minus!=0):
+      return 'deletion'
+    if (nb_plus==0 and nb_minus==0):
+      return 'none'
+    return 'change'
+      
+  # Return code before modification
+  def getOldCodeList(this):
+    if this.modification=='none':
+      return [(x, 'white') for x in this.body.split('\n')]
+    elif this.modification=='change':
+      return [this._getOldCodeList(x) for x in this.body.split('\n') if this._getOldCodeList(x)[0]]
+    else: # deletion or addition
+      return [this._getOldCodeList(x) for x in this.body.split('\n')]
+  
+  def _getOldCodeList(this, line):
+    if line.startswith('+'):
+      return (None, this.color)
+    if line.startswith('-'):
+      return (' '+line[1:], this.color)
+    return (line, this.color)
+  
+  # Return code after modification
+  def getNewCodeList(this):
+    if this.modification=='none':
+      return [(x, 'white') for x in this.body.split('\n')]
+    elif this.modification=='change':
+      return [this._getNewCodeList(x) for x in this.body.split('\n') if this._getNewCodeList(x)[0]]
+    else: # deletion or addition
+      return [this._getNewCodeList(x) for x in this.body.split('\n')]
+  
+  def _getNewCodeList(this, line):
+    if line.startswith('-'):
+      return (None, this.color)
+    if line.startswith('+'):
+      return (' '+line[1:], this.color)
+    return (line, this.color)
   
 class SubversionTool(UniqueObject, Folder):
   """The SubversionTool provides a Subversion interface to ERP5.
@@ -192,6 +407,10 @@ class SubversionTool(UniqueObject, Folder):
     # Decode login information.
     trust_item_list, permanent = loads(b64decode(login))
     return dict(trust_item_list), permanent
+  
+  def diffHTML(self, file_path):
+    raw_diff = self.diff(file_path)
+    return DiffFile(raw_diff).toHTML()
     
   security.declareProtected(Permissions.ManagePortal, 'acceptSSLServer')
   def acceptSSLServer(self, trust_dict, permanent=False):