Index: main/trunk/greenstone2/runtime-src/src/recpt/cgiwrapper.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/recpt/cgiwrapper.cpp	(revision 27161)
+++ main/trunk/greenstone2/runtime-src/src/recpt/cgiwrapper.cpp	(revision 27172)
@@ -544,4 +544,5 @@
 
   queryaction *aqueryaction = new queryaction();
+  aqueryaction->set_userdb(udb);
   aqueryaction->set_receptionist (&recpt);
   recpt.add_action (aqueryaction);
Index: main/trunk/greenstone2/runtime-src/src/recpt/queryaction.cpp
===================================================================
--- main/trunk/greenstone2/runtime-src/src/recpt/queryaction.cpp	(revision 27161)
+++ main/trunk/greenstone2/runtime-src/src/recpt/queryaction.cpp	(revision 27172)
@@ -831,4 +831,88 @@
 }
 
+bool queryaction::user_groups_match(const text_t &collection_groups, const text_t &user_groups) {
+
+      text_tset splitgrps;
+      text_t::const_iterator split_here = collection_groups.begin();
+      text_t::const_iterator split_end = collection_groups.end();
+
+      splitchar(split_here,split_end,',',splitgrps);
+
+	 text_t::const_iterator ugroup_here = user_groups.begin();
+	 text_t::const_iterator ugroup_end = user_groups.end();
+	 text_t thisugroup;
+	while (ugroup_here != ugroup_end) {
+	   ugroup_here = getdelimitstr (ugroup_here, ugroup_end, ',', thisugroup);
+	   if (splitgrps.find(thisugroup) != splitgrps.end() )
+	     { // we have permission!
+	       return true;
+	     }
+	}
+	return false;
+}
+
+// If we are currently authenticated to be in this collection, then check all
+// collections in the list against the groups of the current user - if there is an overlap of groups, then add the collection into ccs list
+// If there had been no authentication needed to get to this collection, then
+// we'll ignore any collections that have collection level authentication
+void queryaction::validate_ccs_collection_list(cgiargsclass &args, recptprotolistclass *protos, ostream &logout) {
+
+  text_tarray collections;
+  text_t arg_cc = args["cc"];
+  text_t arg_c = args["c"];
+  decode_cgi_arg (arg_cc);
+  splitchar (arg_cc.begin(), arg_cc.end(), ',', collections);
+  bool currently_authenticated = false;
+  if (!args["uan"].empty()) {
+    // uan=1 means needs authentication. We'll only get here if we have passed authentication, otherwise the page would have been redirected to login page
+    currently_authenticated = true;
+  }
+  args["cc"] = ""; // we will add colls in one by one if they are valid
+  text_tarray::iterator col_here = collections.begin();
+  text_tarray::iterator col_end = collections.end();
+  bool first = true;
+  text_t current_user_name = args["un"];
+  userinfo_t thisuser;
+  if (currently_authenticated) {
+    int status = user_database->get_user_info (current_user_name, thisuser);
+    if (status != ERRNO_SUCCEED) { // something has gone wrong, so assume not
+      // authenticated
+      currently_authenticated = false;
+    }
+  }
+  
+  while (col_here != col_end) {
+    bool include_coll = false;
+    if (*col_here == arg_c) {
+      // current collection must be accessible otherwise we wouldn't be here.
+      include_coll = true;
+    } else {
+      recptproto *collectproto = protos->getrecptproto (*col_here, logout);
+      if (collectproto != NULL) {
+	ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr (collectproto, *col_here, logout);
+	text_t authenticate = cinfo->authenticate;
+	if (authenticate == "collection") {
+	  if (currently_authenticated) {
+	    text_t collection_groups = cinfo->auth_group;
+	    if (user_groups_match(collection_groups, thisuser.groups)) {
+	      include_coll = true;
+	    }
+	  } // else we'll not include it
+	} else { // not authenticated, or document level authentication - can include in the list
+	  include_coll = true;
+	}
+      }
+    }
+    if (include_coll) {
+      if (!first) args["cc"].push_back (',');
+      args["cc"] += *col_here;
+      first = false;
+    }
+        
+    ++col_here;
+  }
+
+}
+
 bool queryaction::do_action (cgiargsclass &args, recptprotolistclass *protos, 
 			     browsermapclass *browsers, displayclass &disp, 
@@ -845,4 +929,5 @@
   if (args["ccs"] == "1") {
     if (!args["cc"].empty()) {
+      validate_ccs_collection_list(args, protos, logout); // include only those which current user has access to
       // query the selected collections
       text_t::const_iterator b = args["cc"].begin();
Index: main/trunk/greenstone2/runtime-src/src/recpt/queryaction.h
===================================================================
--- main/trunk/greenstone2/runtime-src/src/recpt/queryaction.h	(revision 27161)
+++ main/trunk/greenstone2/runtime-src/src/recpt/queryaction.h	(revision 27172)
@@ -30,4 +30,5 @@
 #include "gsdlconf.h"
 #include "basequeryaction.h"
+#include "userdb.h"
 #include "receptionist.h"
 
@@ -41,4 +42,5 @@
   int num_phrases;
 
+  userdbclass *user_database; // for checking user groups in ccs
   virtual text_t query_filter_name () {return "QueryFilter";}
 
@@ -91,5 +93,6 @@
   virtual bool save_search_history(cgiargsclass &args, int numdocs, 
 				   isapprox isApprox);
-
+  bool user_groups_match(const text_t &collection_groups, const text_t &user_groups);
+  void validate_ccs_collection_list(cgiargsclass &args, recptprotolistclass *protos, ostream &logout);
 public:
   queryaction ();
@@ -99,9 +102,9 @@
   bool init (ostream &logout);
   
+  void set_userdb(userdbclass *udb) {user_database = udb;}
   virtual text_t get_action_name () {return "q";}
   
   virtual bool check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
 			      recptprotolistclass *protos, ostream &logout);
-
   virtual void define_internal_macros (displayclass &disp, cgiargsclass &args, 
 			       recptprotolistclass *protos, ostream &logout);
