<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 <NAME>, <EMAIL>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "img_websearch.h"
#include "img_sort_rank.h"
#include "websearch.h" // websearch plugin.
#include "sort_rank.h"
#include "errlog.h"
#include "cgi.h"
#include "cgisimple.h"
#include "miscutil.h"
#include "json_renderer.h"
#include "static_renderer.h"
#include "seeks_proxy.h"

#include <unistd.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <assert.h>

using namespace sp;

namespace seeks_plugins
{
   img_websearch_configuration* img_websearch::_iwconfig = NULL;
   hash_map<uint32_t,query_context*,id_hash_uint> img_websearch::_active_img_qcontexts
     = hash_map<uint32_t,query_context*,id_hash_uint>();
   
   img_websearch::img_websearch()
     : plugin()
       {
	  _name = "img_websearch";
	  _version_major = "0";
	  _version_minor = "1";
	  
	  // config filename.
	  if (seeks_proxy::_datadir.empty())
	    _config_filename = plugin_manager::_plugin_repository + "img_websearch/img-websearch-config";
	  else _config_filename = seeks_proxy::_datadir + "/plugins/img_websearch/img-websearch-config";
	  
#ifdef SEEKS_CONFIGDIR
	  struct stat stFileInfo;
	  if (!stat(_config_filename.c_str(), &stFileInfo)  == 0)
	    {
	       _config_filename = SEEKS_CONFIGDIR "/img-websearch-config";
	    }
#endif
	  
	  if (img_websearch::_iwconfig == NULL)
	    img_websearch::_iwconfig = new img_websearch_configuration(_config_filename);
	  _configuration = img_websearch::_iwconfig;
	  
	  // cgi dispatchers.
	  _cgi_dispatchers.reserve(2);
	  
	  cgi_dispatcher *cgid_wb_seeks_img_search_css
	    = new cgi_dispatcher("seeks_img_search.css", &img_websearch::cgi_img_websearch_search_css, NULL, TRUE);
	  _cgi_dispatchers.push_back(cgid_wb_seeks_img_search_css);
	  
	  cgi_dispatcher *cgid_img_wb_search
	    = new cgi_dispatcher("search_img", &img_websearch::cgi_img_websearch_search, NULL, TRUE);
	  _cgi_dispatchers.push_back(cgid_img_wb_search);
       }
   
   img_websearch::~img_websearch()
     {
     }
      
   // CGI calls.
   sp_err img_websearch::cgi_img_websearch_search_css(client_state *csp,
						      http_response *rsp,
						      const hash_map<const char*, const char*, hash<const char*>, eqstr> *parameters)
     {
	assert(csp);
	assert(rsp);
	assert(parameters);
	
	std::string seeks_search_css_str = "img_websearch/templates/themes/"
	  + websearch::_wconfig->_ui_theme + "/css/seeks_img_search.css";
	hash_map<const char*,const char*,hash<const char*>,eqstr> *exports
	  = static_renderer::websearch_exports(csp);
	csp->_content_type = CT_CSS;
	sp_err err = cgi::template_fill_for_cgi_str(csp,seeks_search_css_str.c_str(),
						    (seeks_proxy::_datadir.empty() ? plugin_manager::_plugin_repository.c_str()
						     : std::string(seeks_proxy::_datadir + "plugins/").c_str()),
						    exports,rsp);
	if (err != SP_ERR_OK)
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "Could not load seeks_img_search.css");
	  }
	rsp->_is_static = 1;
	
	return SP_ERR_OK;
     }
      
   sp_err img_websearch::cgi_img_websearch_search(client_state *csp,
						  http_response *rsp,
						  const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
     {
	if (!parameters->empty())
	  {
	     const char *query = miscutil::lookup(parameters,"q"); // grab the query.
	     if (!query || strlen(query) == 0)
	       {
		  // return 400 error.
		  return cgi::cgi_error_bad_param(csp,rsp);
	       }
	     else se_handler::preprocess_parameters(parameters); // preprocess the query...
	     
	     // perform websearch or other requested action.
	     const char *action = miscutil::lookup(parameters,"action");
	     if (!action)
	       return cgi::cgi_error_bad_param(csp,rsp);
	     
	     sp_err err = SP_ERR_OK;
	     if (strcmp(action,"expand") == 0 || strcmp(action,"page") == 0)
	       err = img_websearch::perform_img_websearch(csp,rsp,parameters);
#ifdef FEATURE_OPENCV2
	     else if (strcmp(action,"similarity") == 0)
	       err = img_websearch::cgi_img_websearch_similarity(csp,rsp,parameters);
#endif
	     return err;
	  }
	else return cgi::cgi_error_bad_param(csp,rsp);
     }			  
   
#ifdef FEATURE_OPENCV2
   sp_err img_websearch::cgi_img_websearch_similarity(client_state *csp, http_response *rsp,
						      const hash_map<const char*, const char*, hash<const char*>, eqstr> *parameters)
     {
	std::string tmpl_name = "templates/themes/" + websearch::_wconfig->_ui_theme + "seeks_result_template.html";
	
	if (!parameters->empty())
	  {
	     img_query_context *qc = dynamic_cast<img_query_context*>(websearch::lookup_qc(parameters,csp,_active_img_qcontexts));
	     
	     if (!qc)
	       {
		  // no cache, (re)do the websearch first.
		  sp_err err = img_websearch::perform_img_websearch(csp,rsp,parameters,false);
		  if (err != SP_ERR_OK)
		    return err;
		  qc = dynamic_cast<img_query_context*>(websearch::lookup_qc(parameters,csp,_active_img_qcontexts));
		  if (!qc)
		    return SP_ERR_MEMORY;
	       }
	     const char *id = miscutil::lookup(parameters,"id");
	     if (!id)
	       return cgi::cgi_error_bad_param(csp,rsp);
	     
	     mutex_lock(&qc->_qc_mutex);
	     qc->_lock = true;
	     img_search_snippet *ref_sp = NULL;
	     
	     img_sort_rank::score_and_sort_by_similarity(qc,id,ref_sp,qc->_cached_snippets,parameters);
	     
	     if (!ref_sp)
	       {<commit_msg>fixed bad template path<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2010 <NAME>, <EMAIL>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "img_websearch.h"
#include "img_sort_rank.h"
#include "websearch.h" // websearch plugin.
#include "sort_rank.h"
#include "errlog.h"
#include "cgi.h"
#include "cgisimple.h"
#include "miscutil.h"
#include "json_renderer.h"
#include "static_renderer.h"
#include "seeks_proxy.h"

#include <unistd.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <assert.h>

using namespace sp;

namespace seeks_plugins
{
   img_websearch_configuration* img_websearch::_iwconfig = NULL;
   hash_map<uint32_t,query_context*,id_hash_uint> img_websearch::_active_img_qcontexts
     = hash_map<uint32_t,query_context*,id_hash_uint>();
   
   img_websearch::img_websearch()
     : plugin()
       {
	  _name = "img_websearch";
	  _version_major = "0";
	  _version_minor = "1";
	  
	  // config filename.
	  if (seeks_proxy::_datadir.empty())
	    _config_filename = plugin_manager::_plugin_repository + "img_websearch/img-websearch-config";
	  else _config_filename = seeks_proxy::_datadir + "/plugins/img_websearch/img-websearch-config";
	  
#ifdef SEEKS_CONFIGDIR
	  struct stat stFileInfo;
	  if (!stat(_config_filename.c_str(), &stFileInfo)  == 0)
	    {
	       _config_filename = SEEKS_CONFIGDIR "/img-websearch-config";
	    }
#endif
	  
	  if (img_websearch::_iwconfig == NULL)
	    img_websearch::_iwconfig = new img_websearch_configuration(_config_filename);
	  _configuration = img_websearch::_iwconfig;
	  
	  // cgi dispatchers.
	  _cgi_dispatchers.reserve(2);
	  
	  cgi_dispatcher *cgid_wb_seeks_img_search_css
	    = new cgi_dispatcher("seeks_img_search.css", &img_websearch::cgi_img_websearch_search_css, NULL, TRUE);
	  _cgi_dispatchers.push_back(cgid_wb_seeks_img_search_css);
	  
	  cgi_dispatcher *cgid_img_wb_search
	    = new cgi_dispatcher("search_img", &img_websearch::cgi_img_websearch_search, NULL, TRUE);
	  _cgi_dispatchers.push_back(cgid_img_wb_search);
       }
   
   img_websearch::~img_websearch()
     {
     }
      
   // CGI calls.
   sp_err img_websearch::cgi_img_websearch_search_css(client_state *csp,
						      http_response *rsp,
						      const hash_map<const char*, const char*, hash<const char*>, eqstr> *parameters)
     {
	assert(csp);
	assert(rsp);
	assert(parameters);
	
	std::string seeks_search_css_str = "img_websearch/templates/themes/"
	  + websearch::_wconfig->_ui_theme + "/css/seeks_img_search.css";
	hash_map<const char*,const char*,hash<const char*>,eqstr> *exports
	  = static_renderer::websearch_exports(csp);
	csp->_content_type = CT_CSS;
	sp_err err = cgi::template_fill_for_cgi_str(csp,seeks_search_css_str.c_str(),
						    (seeks_proxy::_datadir.empty() ? plugin_manager::_plugin_repository.c_str()
						     : std::string(seeks_proxy::_datadir + "plugins/").c_str()),
						    exports,rsp);
	if (err != SP_ERR_OK)
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "Could not load seeks_img_search.css");
	  }
	rsp->_is_static = 1;
	
	return SP_ERR_OK;
     }
      
   sp_err img_websearch::cgi_img_websearch_search(client_state *csp,
						  http_response *rsp,
						  const hash_map<const char*,const char*,hash<const char*>,eqstr> *parameters)
     {
	if (!parameters->empty())
	  {
	     const char *query = miscutil::lookup(parameters,"q"); // grab the query.
	     if (!query || strlen(query) == 0)
	       {
		  // return 400 error.
		  return cgi::cgi_error_bad_param(csp,rsp);
	       }
	     else se_handler::preprocess_parameters(parameters); // preprocess the query...
	     
	     // perform websearch or other requested action.
	     const char *action = miscutil::lookup(parameters,"action");
	     if (!action)
	       return cgi::cgi_error_bad_param(csp,rsp);
	     
	     sp_err err = SP_ERR_OK;
	     if (strcmp(action,"expand") == 0 || strcmp(action,"page") == 0)
	       err = img_websearch::perform_img_websearch(csp,rsp,parameters);
#ifdef FEATURE_OPENCV2
	     else if (strcmp(action,"similarity") == 0)
	       err = img_websearch::cgi_img_websearch_similarity(csp,rsp,parameters);
#endif
	     return err;
	  }
	else return cgi::cgi_error_bad_param(csp,rsp);
     }			  
   
#ifdef FEATURE_OPENCV2
   sp_err img_websearch::cgi_img_websearch_similarity(client_state *csp, http_response *rsp,
						      const hash_map<const char*, const char*, hash<const char*>, eqstr> *parameters)
     {
	std::string tmpl_name = "templates/themes/" + websearch::_wconfig->_ui_theme + "/seeks_result_template.html";
	
	if (!parameters->empty())
	  {
	     img_query_context *qc = dynamic_cast<img_query_context*>(websearch::lookup_qc(parameters,csp,_active_img_qcontexts));
	     
	     if (!qc)
	       {
		  // no cache, (re)do the websearch first.
		  sp_err err = img_websearch::perform_img_websearch(csp,rsp,parameters,false);
		  if (err != SP_ERR_OK)
		    return err;
		  qc = dynamic_cast<img_query_context*>(websearch::lookup_qc(parameters,csp,_active_img_qcontexts));
		  if (!qc)
		    return SP_ERR_MEMORY;
	       }
	     const char *id = miscutil::lookup(parameters,"id");
	     if (!id)
	       return cgi::cgi_error_bad_param(csp,rsp);
	     
	     mutex_lock(&qc->_qc_mutex);
	     qc->_lock = true;
	     img_search_snippet *ref_sp = NULL;
	     
	     img_sort_rank::score_and_sort_by_similarity(qc,id,ref_sp,qc->_cached_snippets,parameters);
	     
	     if (!ref_sp)
	       {
{'fraction_non_alphanumeric': 0.1176229171796766, 'fraction_numerical': 0.0037757530985799885, 'mean_word_length': 3.8483883804218064, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2129723', 'n_tokens_mistral': 4472, 'n_tokens_neox': 4127, 'n_words': 827}