Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/URLFilter.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/URLFilter.java	(revision 39009)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/core/URLFilter.java	(revision 39010)
@@ -66,4 +66,5 @@
   protected static final String BROWSE_PATH = "browse";
   protected static final String SEARCH_PATH = "search";
+  protected static final String ASSOC_PATH = "assoc";
   protected static final ArrayList<String> _keywords;
 
@@ -147,5 +148,5 @@
       // so they are not a true link to a file. We remove the
       // 'library' then forward the request to the new url.
-      securityCheckAssocFiles(url, hRequest, response);
+      securityCheckAssocFiles(url, hRequest, response, null);
       return;
     }
@@ -200,4 +201,6 @@
 	    url = url.substring(0, index);
 	  }
+
+        // OK, here we split into segments and process bit by bit.
 	String[] segments = url.split("/");
 	for (int i = 0; i < segments.length; i++)
@@ -248,5 +251,11 @@
 		  gRequest.setParameter("ed", "1");
 						  
-		}
+		} else if ((i+3) < segments.length && segments[i+2].equals("assoc")) {
+                  url = generateFileURL(context, url, gRequest.getParameter(GSParams.COLLECTION), gRequest.getParameter(GSParams.DOCUMENT), segments[i+3]);
+                                    
+                  securityCheckAssocFiles(url, hRequest, response, gRequest.getParameter(GSParams.DOCUMENT));
+                  return;
+                }
+                
 					
 	      }
@@ -429,6 +438,26 @@
   }
 
-
-    private void securityCheckAssocFiles(String url, HttpServletRequest request, ServletResponse response) throws IOException, ServletException {
+  private String generateFileURL(ServletContext context, String url, String collection, String document, String filename) {
+
+    String library_name = url.replaceFirst(context.getContextPath()+"/", "");
+    library_name = library_name.substring(0, library_name.indexOf("/"));
+
+    MessageRouter gsRouter = (MessageRouter) context.getAttribute(library_name+"Router");
+    String site_name = gsRouter.getSiteName();
+    String context_path = context.getContextPath();
+    String assocfilepath = queryMRforMetadata(gsRouter, collection, document, "assocfilepath");
+
+    if (assocfilepath == null) {
+      return null;
+    }
+    return context_path +"/"+ library_name+"/"+
+      "sites/"+ site_name+"/"+
+      "collect/"+collection+"/"+
+      "index/assoc/"+assocfilepath+"/"+filename;
+    
+  }
+
+  private void securityCheckAssocFiles(String url, HttpServletRequest request, ServletResponse response, String document) throws IOException, ServletException {
+
 	HttpSession session = request.getSession();
 	String session_id = session.getId();
@@ -494,4 +523,5 @@
 	}
 
+        if (document == null) {
 	// Query the MR with a request for the contains metadata for node "dir" - where dir is the assocfilepath
 	// In the jdbm db, have entries like
@@ -499,9 +529,10 @@
 	// <contains>HASH1552e3sdlkjf7sdfsdfk
 	// mapping assocfilepath to doc id
-	String document = queryMRforDOCID(gsRouter, collection, dir);
-	if (document == null) {
-	  response.getWriter().println("ERROR: Couldn't find the document associated with assocfilepath: "+dir);
-	  return;
-	}
+          document = queryMRforDOCID(gsRouter, collection, dir);
+          if (document == null) {
+            response.getWriter().println("ERROR: Couldn't find the document associated with assocfilepath: "+dir);
+            return;
+          }
+        }
 	
 	//Query the MR for the security info for this document
@@ -668,4 +699,12 @@
 
   private String queryMRforDOCID(MessageRouter gsRouter, String collection, String assocfiledir) {
+    return queryMRforMetadata(gsRouter, collection, assocfiledir, "contains");
+  }
+
+  // set node_id to be a document_id, and metadata_name to be 'assocfilepath' to
+  // get the assocfilepath for a particular doc
+  // set node_id to be the assocfilepath, and metadata_name to be 'contains' to
+  // get the doc_id for a particular assocfilepath
+  private String queryMRforMetadata(MessageRouter gsRouter, String collection, String node_id, String metadata_name) {
     Document gsDoc = XMLConverter.newDOM();
 
@@ -679,5 +718,5 @@
     Element param = gsDoc.createElement(GSXML.PARAM_ELEM);    
     param.setAttribute(GSXML.NAME_ATT, "metadata");
-    param.setAttribute(GSXML.VALUE_ATT, "contains");
+    param.setAttribute(GSXML.VALUE_ATT, metadata_name);
     paramList.appendChild(param);
 
@@ -686,5 +725,5 @@
 
     Element doc = gsDoc.createElement(GSXML.DOC_NODE_ELEM);
-    doc.setAttribute(GSXML.NODE_ID_ATT, assocfiledir);
+    doc.setAttribute(GSXML.NODE_ID_ATT, node_id);
     docList.appendChild(doc);
     
@@ -694,14 +733,14 @@
     if (metadataList.getLength() == 0) {
       
-      logger.error("Could not find the document ID related to this url");
+      logger.error("Could not find the metadata '"+metadata_name+"' for node '"+node_id+"'");
       return null;
     }
       
     Element metadata = (Element) metadataList.item(0);
-    String document = metadata.getTextContent();
-    if (document != null && document.equals("")) {
-      document = null;
-    }
-    return document;
+    String meta_value = metadata.getTextContent();
+    if (meta_value != null && meta_value.equals("")) {
+      meta_value = null;
+    }
+    return meta_value;
       
  
