Index: /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
===================================================================
--- /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java	(revision 1044)
+++ /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java	(working copy)
@@ -28,9 +28,16 @@
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.io.IOException;
+import java.util.List;
 
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.plugin.XWikiPluginManager;
+import com.xpn.xwiki.doc.XWikiAttachment;
+import com.xpn.xwiki.doc.XWikiDocument;
+import org.apache.velocity.VelocityContext;
 
 public class XWikiServletURLFactory extends XWikiDefaultURLFactory {
     protected URL serverURL;
@@ -96,11 +103,11 @@
     private URL getServerURL(String xwikidb, XWikiContext context) throws MalformedURLException {
         if (context.getRequest()!=null){      // necessary to the tests
             final String host = context.getRequest().getHeader("x-forwarded-host"); // apache modproxy host
-            if (host!=null) {            	
-            	int comaind = host.indexOf(',');
-            	final String host1 = comaind>0 ? host.substring(0, comaind) : host;
-            	if (!host1.equals(""))
-            		return new URL("http://"+host1);
+            if (host!=null) {
+                int comaind = host.indexOf(',');
+                final String host1 = comaind>0 ? host.substring(0, comaind) : host;
+                if (!host1.equals(""))
+                    return new URL("http://"+host1);
             }
         }
         if (xwikidb==null)
@@ -113,7 +120,7 @@
             if (url==null)
              return serverURL;
             else
-             return url; 
+             return url;
         }
     }
 
@@ -237,17 +244,78 @@
         addSpace(newpath, web, action, context);
         addName(newpath, name, action, context);
         addFileName(newpath, filename, context);
+
+        String equalslink = null;
+        XWikiAttachment attachment = null;
+        String lastver = null;
+        String page = null;
+
         if ((querystring!=null)&&(!querystring.equals(""))) {
             newpath.append("?");
             newpath.append(querystring);
+            equalslink = newpath.substring(newpath.indexOf(action)+action.length(),newpath.indexOf("?"));
+        }else{
+            equalslink = newpath.substring(newpath.indexOf(action)+action.length());
         }
 
-        try {
+        if(context.getAction().equals("view")){
+             try{
+               attachment = findAttachmentForDocRevision(context.getDoc(),context.getDoc().getVersion(),filename,equalslink,context);
+            }catch(XWikiException e){
+                page = Utils.getPage(context.getRequest(), "exception");
+                attachment = null;
+                if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_HIBERNATE_LOADING_ATTACHMENT){
+                 context.put("message","documentfailattachment");
+               }else if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_ATTACHMENT_ARCHIVEFORMAT){
+                 context.put("message","documentfailattachmentrev");
+               }else{
+                 context.put("message","errornotdefine");
+                 VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+                 vcontext.put("exp",e);
+               }
+            }
+        }
+
+        if(context.getAction().equals("viewrev")){
+            String revdoc = context.get("rev").toString();
+
+            try{
+               lastver = context.getWiki().getDocument(context.getDoc(),revdoc,context).getAttachment(filename).getVersion();
+               attachment = findAttachmentForDocRevision(context.getDoc(),revdoc,filename,equalslink,context);
+            }catch(XWikiException e){
+                page = Utils.getPage(context.getRequest(), "exception");
+                attachment = null;
+                if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_HIBERNATE_LOADING_ATTACHMENT){
+                 context.put("message","historyattachdoesnotexist");
+               }else if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_ATTACHMENT_ARCHIVEFORMAT){
+                 context.put("message","historyattachrevdoesnotexist");
+               }else{
+                 context.put("message","errornotdefine");
+                 VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+                 vcontext.put("exp",e);
+               }
+            }
+
+        }
+
+        try{
+            Object revatt = context.get("revattach") ;
+            if(attachment == null && page != null){
+                Utils.parseTemplate(page, context);
+            } else
+            if(revatt != null && !revatt.equals(lastver)){
+                return createAttachmentRevisionURL(filename,web,name,revatt.toString(),querystring,xwikidb,context);
+            }
+
             return new URL(getServerURL(xwikidb, context), newpath.toString());
-        } catch (MalformedURLException e) {
-            // This should not happen
+
+        }
+        catch(Exception e){
             return null;
         }
+
+
+
     }
 
     public URL createAttachmentRevisionURL(String filename, String web, String name, String revision, String querystring, String xwikidb, XWikiContext context) {
@@ -305,15 +373,46 @@
             return "";
         }
     }
-    public URL getRequestURL(XWikiContext context) {    	
-    	final URL url = super.getRequestURL(context);
-		try {
-			final URL servurl = getServerURL(context); // if use apache mod_proxy we needed to know external host address
-			return new URL(url.getProtocol(), servurl.getHost(), servurl.getPort(), url.getFile());
-		} catch (MalformedURLException e) {
-			// This should not happen
-			e.printStackTrace();
-			return url;
-		}
+    public URL getRequestURL(XWikiContext context) {
+        final URL url = super.getRequestURL(context);
+        try {
+            final URL servurl = getServerURL(context); // if use apache mod_proxy we needed to know external host address
+            return new URL(url.getProtocol(), servurl.getHost(), servurl.getPort(), url.getFile());
+        } catch (MalformedURLException e) {
+            // This should not happen
+            e.printStackTrace();
+            return url;
+        }
     }
+    public XWikiAttachment findAttachmentForDocRevision(XWikiDocument doc, String revdoc ,String filename,String equalslink,XWikiContext context ) throws XWikiException{
+        XWikiAttachment attachment = null;
+        XWikiDocument rdoc = context.getWiki().getDocument(doc,revdoc,context);
+        String content = rdoc.getContent();
+
+        if(content.indexOf(equalslink) != -1){
+            attachment = rdoc.getAttachment(filename);
+        }
+
+        String revatt = null;
+        if(content.indexOf(equalslink+"?rev=") != -1){
+            int index =  content.indexOf(equalslink)+equalslink.length()+5;
+
+            if(content.indexOf("&",index) != -1)
+                revatt = content.substring(index,content.indexOf("?",index));
+            else
+                revatt = content.substring(index,content.indexOf("\">",index)).trim();
+
+        }
+        // check attachment exist in databse . throws exception if not exist in database
+        if(attachment != null){
+            attachment.getContent(context);
+        }
+        // check revision of attachment exist in database
+        if(revatt != null ){
+            context.put("revattach",revatt);
+            attachment = attachment.getAttachmentRevision(revatt,context);
+        }
+
+        return attachment ;
+    }
 }
Index: /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
===================================================================
--- /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java	(revision 1044)
+++ /home/exo/java/projects/xwiki/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java	(working copy)
@@ -28,9 +28,16 @@
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.io.IOException;
+import java.util.List;
 
 import com.xpn.xwiki.XWikiContext;
 import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.plugin.XWikiPluginManager;
+import com.xpn.xwiki.doc.XWikiAttachment;
+import com.xpn.xwiki.doc.XWikiDocument;
+import org.apache.velocity.VelocityContext;
 
 public class XWikiServletURLFactory extends XWikiDefaultURLFactory {
     protected URL serverURL;
@@ -96,11 +103,11 @@
     private URL getServerURL(String xwikidb, XWikiContext context) throws MalformedURLException {
         if (context.getRequest()!=null){      // necessary to the tests
             final String host = context.getRequest().getHeader("x-forwarded-host"); // apache modproxy host
-            if (host!=null) {            	
-            	int comaind = host.indexOf(',');
-            	final String host1 = comaind>0 ? host.substring(0, comaind) : host;
-            	if (!host1.equals(""))
-            		return new URL("http://"+host1);
+            if (host!=null) {
+                int comaind = host.indexOf(',');
+                final String host1 = comaind>0 ? host.substring(0, comaind) : host;
+                if (!host1.equals(""))
+                    return new URL("http://"+host1);
             }
         }
         if (xwikidb==null)
@@ -113,7 +120,7 @@
             if (url==null)
              return serverURL;
             else
-             return url; 
+             return url;
         }
     }
 
@@ -237,17 +244,78 @@
         addSpace(newpath, web, action, context);
         addName(newpath, name, action, context);
         addFileName(newpath, filename, context);
+
+        String equalslink = null;
+        XWikiAttachment attachment = null;
+        String lastver = null;
+        String page = null;
+
         if ((querystring!=null)&&(!querystring.equals(""))) {
             newpath.append("?");
             newpath.append(querystring);
+            equalslink = newpath.substring(newpath.indexOf(action)+action.length(),newpath.indexOf("?"));
+        }else{
+            equalslink = newpath.substring(newpath.indexOf(action)+action.length());
         }
 
-        try {
+        if(context.getAction().equals("view")){
+             try{
+               attachment = findAttachmentForDocRevision(context.getDoc(),context.getDoc().getVersion(),filename,equalslink,context);
+            }catch(XWikiException e){
+                page = Utils.getPage(context.getRequest(), "exception");
+                attachment = null;
+                if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_HIBERNATE_LOADING_ATTACHMENT){
+                 context.put("message","documentfailattachment");
+               }else if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_ATTACHMENT_ARCHIVEFORMAT){
+                 context.put("message","documentfailattachmentrev");
+               }else{
+                 context.put("message","errornotdefine");
+                 VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+                 vcontext.put("exp",e);
+               }
+            }
+        }
+
+        if(context.getAction().equals("viewrev")){
+            String revdoc = context.get("rev").toString();
+
+            try{
+               lastver = context.getWiki().getDocument(context.getDoc(),revdoc,context).getAttachment(filename).getVersion();
+               attachment = findAttachmentForDocRevision(context.getDoc(),revdoc,filename,equalslink,context);
+            }catch(XWikiException e){
+                page = Utils.getPage(context.getRequest(), "exception");
+                attachment = null;
+                if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_HIBERNATE_LOADING_ATTACHMENT){
+                 context.put("message","historyattachdoesnotexist");
+               }else if(e.getCode() == XWikiException.ERROR_XWIKI_STORE_ATTACHMENT_ARCHIVEFORMAT){
+                 context.put("message","historyattachrevdoesnotexist");
+               }else{
+                 context.put("message","errornotdefine");
+                 VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+                 vcontext.put("exp",e);
+               }
+            }
+
+        }
+
+        try{
+            Object revatt = context.get("revattach") ;
+            if(attachment == null && page != null){
+                Utils.parseTemplate(page, context);
+            } else
+            if(revatt != null && !revatt.equals(lastver)){
+                return createAttachmentRevisionURL(filename,web,name,revatt.toString(),querystring,xwikidb,context);
+            }
+
             return new URL(getServerURL(xwikidb, context), newpath.toString());
-        } catch (MalformedURLException e) {
-            // This should not happen
+
+        }
+        catch(Exception e){
             return null;
         }
+
+
+
     }
 
     public URL createAttachmentRevisionURL(String filename, String web, String name, String revision, String querystring, String xwikidb, XWikiContext context) {
@@ -305,15 +373,46 @@
             return "";
         }
     }
-    public URL getRequestURL(XWikiContext context) {    	
-    	final URL url = super.getRequestURL(context);
-		try {
-			final URL servurl = getServerURL(context); // if use apache mod_proxy we needed to know external host address
-			return new URL(url.getProtocol(), servurl.getHost(), servurl.getPort(), url.getFile());
-		} catch (MalformedURLException e) {
-			// This should not happen
-			e.printStackTrace();
-			return url;
-		}
+    public URL getRequestURL(XWikiContext context) {
+        final URL url = super.getRequestURL(context);
+        try {
+            final URL servurl = getServerURL(context); // if use apache mod_proxy we needed to know external host address
+            return new URL(url.getProtocol(), servurl.getHost(), servurl.getPort(), url.getFile());
+        } catch (MalformedURLException e) {
+            // This should not happen
+            e.printStackTrace();
+            return url;
+        }
     }
+    public XWikiAttachment findAttachmentForDocRevision(XWikiDocument doc, String revdoc ,String filename,String equalslink,XWikiContext context ) throws XWikiException{
+        XWikiAttachment attachment = null;
+        XWikiDocument rdoc = context.getWiki().getDocument(doc,revdoc,context);
+        String content = rdoc.getContent();
+
+        if(content.indexOf(equalslink) != -1){
+            attachment = rdoc.getAttachment(filename);
+        }
+
+        String revatt = null;
+        if(content.indexOf(equalslink+"?rev=") != -1){
+            int index =  content.indexOf(equalslink)+equalslink.length()+5;
+
+            if(content.indexOf("&",index) != -1)
+                revatt = content.substring(index,content.indexOf("?",index));
+            else
+                revatt = content.substring(index,content.indexOf("\">",index)).trim();
+
+        }
+        // check attachment exist in databse . throws exception if not exist in database
+        if(attachment != null){
+            attachment.getContent(context);
+        }
+        // check revision of attachment exist in database
+        if(revatt != null ){
+            context.put("revattach",revatt);
+            attachment = attachment.getAttachmentRevision(revatt,context);
+        }
+
+        return attachment ;
+    }
 }
