/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


#include <sxpagesearch.h>
#include <dditemset.h>
#include <dditemlink.h>
#include <ddwebconnection.h>

/**
	Constructor.
*/

sxpagesearchbase::sxpagesearchbase( const ddstring& name, ddwebsite* site ) 
: sxpage( name, site, "search", "Profisuche" )
{			

} 




/**
	Das Formular & die Query vorbereiten.
*/

bool sxpagesearchbase::prepare_query()
{
	
	// Geil peinlicher Bug: nach dem die DB-Engine jetzt
	// auch mehrere Statements hintereinander verarbeiten
	// kann, ist die Parameteübergabe per CGI sperrangelweit 
	// offen für sql injection: 
	// Als Hotfix erstmal das ';' strippen
	
	ddwebcgi& cgi =  get_cgi();  
	ddstringmap::iterator pos = cgi.begin();
	for( ; pos != cgi.end(); ++pos )
		(*pos).second.trim_all_of( ";" );
	
	
	//	Neu: wir sparen uns das 'select count()' und machens wie google:
	//	Blockweise suchen mit jeweils max. 200 Ergebnissen und dann je nach
	//	Items_per_page im Block navigieren, also müssen wir zuerst den Block
	//	rausfinden.
	
	// Erstmal Formular & Listen saubermachen
	dditem& body = get_body()["sn_search"]["sn_subbody"];
	body.clear_children();
	
	dditem& optionsblock = get_item()["sn_main_right"]["sn_search_options"];
	optionsblock["sn_types"]["sn_check1"].from_string( "checked" );
	
	// Bei leerem Key die Suche _nicht_ anschmeissen und auch nicht
	// das Erbegnis rendern.
	
	_searchphrase = cgi["sn_key"];
	if( _searchphrase.empty() )
		return false;
	
	// formular bestücken
	body["sn_key"].from_string( _searchphrase );
	bool use_questions = ( !cgi["sn_searchquestions"].empty() );
	bool search_body = ( !cgi["sn_searchbody"].empty() );	
	optionsblock["personal"]["sn_searchquestions"].from_string( use_questions ? "checked" : " " );	
	optionsblock["sn_searchbody"].from_string( search_body ? "checked" : " " );
		
	ddstring typefilter = "and (";
	dditem& types = optionsblock["sn_types"];
	ddstring key = "sn_check1";
	
	bool first = true;
	bool found = false;
	
	for( size_t i=0; i<8; ++i )
	{
		key[8] = '1' + i;
		if( types.contains_key( key ) )
		{
			// die checkbox behandeln ...
			bool keyempty = cgi[ key ].empty();
			types[ key ].from_string(  keyempty ? " " : "checked" );			
			// ... den typefilter string setzen
			if( !keyempty )
			{
				found = true;
				if( !first )
					typefilter += " or ";
				typefilter += "id_type='" + cgi[ key ] + "'";
				first = false;
			}
		}
	}
	
	// alles Durchsuchen
	if( !cgi["sn_check1"].empty() || !found )
		typefilter = "";
	else
	 typefilter += ") ";
	
  dddataquery& query = get_view().get_query( "on_search" );
  
	ddstring orderby = "sn_datecreated desc";
	ddstring flgroup = "id_group != 2";
	ddstring flfield = "sn_msgsubject";
	ddstring flquestions;
	
	// passende gruppe setzen
	if( !cgi["id_group"].empty() && cgi["id_group"] != "#" )
		flgroup =" id_group = " + cgi["id_group"];
	
	if( !cgi["orderby"].empty() )
		orderby = cgi["orderby"];

	// passenden index setzen
	if( search_body )
		flfield +=", sn_msgbody";
	if( use_questions )		
	{
		flquestions = " and id_user = ";
		flquestions += get_user_id().get_id();
	}
	
	if( query.contains_key( "group" ) )
		query["group"] = flgroup;
	
	if( query.contains_key( "questions" ) )
	 	query["questions"] = flquestions;
	
	if( query.contains_key( "field" ) )
		query["field"] = flfield;
 	
 	if( query.contains_key( "sn_key" ) )
		query["sn_key"] = _keygen.prepare_key( _searchphrase );	
	
	if( query.contains_key( "type" ) )
		query["type"] = typefilter;
 	
	// wenn nach news gesucht wird, keinen Gruppenfilter setzen
	if( typefilter.contains( "news" ) )
		flgroup	= "id_group != 2";
		
	if( query.contains_key( "group" ) )
		query["group"] = flgroup;
		
	if( query.contains_key( "sn_filter" ) )
		query["sn_filter"] = DDADMFILTER;
	
	query["orderby"] = orderby;
  	
  // linkbase setzen
	ddstring path = get_connection().get_request().get_cgi_path();
	size_t dot = path.rfind( "&orderby" );
	if( dot != ddstring::npos )
	{
		path = path.substr( 0, dot );
		// FIX! hässlich
	}
	else
	{
		dot = path.rfind( "&page" );
		if( dot != ddstring::npos )
			path = path.substr( 0, dot );
	}
	context.navilinkbase = "/fullsearch?" + path;
	
	
	if( !cgi["orderby"].empty() )
		context.navilinkbase += "&orderby=" + cgi["orderby"];
	context.navilinkbase += "&page=";

	return true;	
	
	

}

	
dd_result sxpagesearchbase::on_search( dditem& item )
{
	
	// hack: es kann per checkbox die membersuche abgefrat werden
	if( get_cgi()["sn_check6"] == "1" )
		return create_redirect( "/membersearch?sn_key="+ get_cgi()["sn_key"] );
	
	// ergebnisliste erstmal abschalten.
	dditem& snlist = get_body()["sn_content"];
	//dditem& snjama = get_body()["sn_jamaipa"];
	
	snlist.set_visible( false ); 
	//snjama.set_visible( false );
	
	// title setzen
	context.pagetitle	= context.pagetitlestatic + ": " + get_cgi()["sn_key"];
	
	// key leer? dann weg
	if( !prepare_query() )
		return rs_ok;						
			 
	// jamaipablock füllen
	//snjama.set_visible( true );
	//snjama["sn_key"].from_string( get_cgi()["sn_key"] );
	
	// auf 5 suchworte begrenzen: bei mehr als 5 begriffen
	// ist prepare_query war true, aber 'sn_key' ist leer
	dddataquery& query = get_view().get_query( "on_search" );
	if( query.contains_key( "sn_key" ) && query["sn_key"].empty() )
		return create_hint_box( snlist, DDHINTBADQUERY );
		
	ddwebview& table = get_view( get_name() );
	context.numrows = table.fill( "on_search" );
	
	// die suche loggen, aber nur wenn sie neu für diesen user ist
	if( get_user_id().get_property( _searchphrase ).empty() ) 
	{
		ddstring msg = "search: " + _searchphrase + " hits: " + ddstrutil::from_int( context.numrows );
		// hier noch nicht markieren, das passiert im block_search_faqs
		//get_user_id().get_property( _searchphrase ) = "1";
		get_site().log_message( ddlogdevice::lg_search, msg );
	}

	if( context.numrows <= 0 )
		return create_hint_box( snlist, DDHINTNOTFOUND );
	
	// ab hier: gesucht & gefunden
	snlist.set_visible( true );			
			
	// ...anzeigen...
	dditem& block = get_body()["sn_content"]["sn_msgentry"];
	table.on_render( *this, block, context.navifrom, context.navito );	
	
	return rs_ok;


}


/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


/**
	Constructor.
*/

sxpagesearch::sxpagesearch( const ddstring& name, ddwebsite* site ) 
: sxpagesearchbase( name, site )
{			
	
	add_request_handler( "fullsearch",  	"xx_search_all",				(ddmemptr) &sxpagesearch::on_search );
	// FIX! Die Quicksearch dient zur Lastverteilung! Wieder einbauen!
	// die quicksearch war ein externer link...
	add_request_handler( "quicksearch", 	"xx_search_all",				(ddmemptr) &sxpagesearch::on_search );
	add_request_handler( "linknotfound", 	"xx_search_not_found",	(ddmemptr) &sxpagesearch::on_link_not_found );
	
	ddstring content;
	get_site().fetch_data_entry( DDKEYSTOPWORDS, content );
	_keygen.init_stop_words( content, get_site().get_config()["main"]["evilchars"] );

	
	add_request_handler( "threadwatch","xx_search_watch",				(ddmemptr) &sxpagesearch::on_search_watch,  1, dduserid::usr_is_registered  );


	// neu: alles redirecten
	add_request_handler( "answers",    "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,	    1, dduserid::usr_is_registered );
	add_request_handler( "questions",  "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect, 			1, dduserid::usr_is_registered );
	
	add_request_handler( "mynews",		 "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,1, dduserid::usr_is_registered  );
	add_request_handler( "myfaqs",		 "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,1, dduserid::usr_is_registered  );
	add_request_handler( "myrecipes",	 "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,1, dduserid::usr_is_registered  );
	add_request_handler( "mycheats",	 "xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,1, dduserid::usr_is_registered  );
	add_request_handler( "mysolutions","xx_dummy",	(ddmemptr) &sxpagesearch::on_redirect,1, dduserid::usr_is_registered  );

} 


/**
	Überladene Suchmethode für die admins, der test auf mehr als
	5 suchbgriffe fehlt hier.
*/

dd_result sxpagesearch::on_link_not_found( dditem& item )
{
	// feld setzen, so vorhanden
	get_body()["sn_hint"]["sn_subbody"].clear_children();
	if( !get_cgi()["sn_key"].empty() ) 
		get_body()["sn_hint"]["sn_subbody"].set_field_value( "sn_key", "<font color='red'>(" + get_cgi()["sn_key"] + ") </font>" );

	// ...und gut
	return rs_ok;
	(void) item;
}


/**
	Sammelt die alten Content-Suchen (myfaqs etc.) eines Nutzers ein und schickt sie an
	"beitraege/<mynick>"
*/

dd_result sxpagesearch::on_redirect( dditem& item )
{
	return create_redirect( "/beitraege/" + get_user_id().get_nick_name(), ret_301_moved_permanently );
}




/**
	Die von einem User beobachteten Threads: 'meine Favortiten'
*/

dd_result sxpagesearch::on_search_watch( dditem& item )
{
		
	dditem& snlist = get_body();
		
	ddwebview& table = get_view();
  context.numrows = table.fill( "threadwatch", get_user_id().get_id() );
	if( context.numrows <= 0 )
		return create_hint_box( snlist, DDHINTNOTFOUND );
	
	snlist.set_visible( true ); 
		// ...anzeigen...
	dditem& block = snlist["sn_msgentry"];
	table.on_render( *this, block, 0, context.numrows );	
	//nciht nötig
	//context.navilinkbase = "/threadwatch/";
	
	return rs_ok;
	
}
 












/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/


/**
	Constructor.
*/

sxpagesearchadmin::sxpagesearchadmin( const ddstring& name, ddwebsite* site, const ddstring& title ) 
: sxpagesearchbase( name, site )
{	
		
	//add_request_handler( "admin_search",			 "xx_search_admin",  			(ddmemptr) &sxpagesearchadmin::admin_search,   			1, dduserid::usr_can_edit_msg );
	add_request_handler( "admin_search_thread",			"xx_admin_search_thread",			(ddmemptr) &sxpagesearchadmin::on_search, 								1, dduserid::usr_can_edit_news );
	add_request_handler( "admin_kill_multi",	 			"xx_dummy",										(ddmemptr) &sxpagesearchadmin::on_kill_multi, 						1, dduserid::usr_can_edit_news ); 
	add_request_handler( "admin_user_content",			"xx_admin_user_content",			(ddmemptr) &sxpagesearchadmin::on_show_user_content,			1, dduserid::usr_can_edit_news ); 
	add_request_handler( "admin_user_images",				"xx_admin_user_images",				(ddmemptr) &sxpagesearchadmin::on_show_user_images, 			1, dduserid::usr_can_edit_news ); 
	add_request_handler( "admin_user_image_votes",	"xx_admin_user_image_votes",	(ddmemptr) &sxpagesearchadmin::on_show_user_image_votes, 	1, dduserid::usr_can_edit_news ); 
	
} 


/**
	Die Query vorbereiten
*/

bool sxpagesearchadmin::prepare_query()
{
	
	
	//dditem& body = get_body()["sn_form"]["sn_subbody"];
	dditem& body = get_body()["sn_subbody"];
	body.clear_children();
	
	// 'Heute' erstmal als default setzen
	if( body["sn_date1"].get_value().empty() )
		body["sn_date1"].from_string( ddbasedate::now().to_string_en() );
	
	ddwebcgi& cgi =  get_cgi();  
	if( cgi.empty() )
		return false;
	
	body.sync( cgi );
		
	ddstring flip;
	ddstring flgroup;
	ddstring fltype;
	ddstring fldate1;
	ddstring fldate2;
	ddstring flnick;
	ddstring flmail;
	ddstring flsubject;
	ddstring flbody;
	
	// passende ip setzen
	if( !cgi["sn_senderip"].empty()  )
		flip = " and sn_senderip like '" + cgi["sn_senderip"] + "' ";
	
	// passende gruppe setzen
	if( !cgi["id_group"].empty() && cgi["id_group"] != "#" )
		flgroup ="and id_group = " + cgi["id_group"];
	
	// type filter setzen
	if( !cgi["id_type"].empty() && cgi["id_type"] != "#" )
		fltype = " and id_type = '" + cgi["id_type"] + "'";
	
	// passendes date1 setzen
	if( !cgi["sn_date1"].empty() )
		fldate1 = " and DATE_SUB( '" + cgi["sn_date1"] +"', INTERVAL " + cgi["sn_op1"] + " HOUR) <= sn_datecreated";
	else
		body["sn_date1"].clear_value();
		
	// passendes date2 setzen
	if( !cgi["sn_date2"].empty() )
		fldate1 = " and DATE_SUB( '" + cgi["sn_date2"] +"', INTERVAL " + cgi["sn_op2"] + " HOUR) <= sn_datemodified";
	
	// passenden nick setzen
	if( !cgi["sn_nickname"].empty() )
		flnick = " and sn_nickname = '" + cgi["sn_nickname"] + "'";
		
	// passende mail setzen
	if( !cgi["sn_nickmail"].empty() )
		flmail = " and sn_nickmail = '" + cgi["sn_nickmail"] + "'";
	
	// passendes subject setzen
	if( !cgi["sn_msgsubject"].empty() )
		flsubject = " and sn_msgsubject like '%" + cgi["sn_msgsubject"] + "%'";
	
	// passenden body setzen
	if( !cgi["sn_msgbody"].empty() )
		flbody = " and sn_msgbody like '%" + cgi["sn_msgbody"] + "%'";
	
	// daten holen, sofern nötig...
	dddataquery& query =  get_view().get_query( "on_search" );
		
	query["flip"] 			= flip;
	query["flgroup"] 		= flgroup;
	query["fltype"] 		= fltype;
	query["fldate1"] 		= fldate1;
	query["fldate2"] 		= fldate2;
	query["flnick"] 		=	flnick;
	query["flmail"] 		= flmail;
	query["flsubject"]	= flsubject;
	query["flbody"] 		= flbody;
	
	return true;
}



/**
	Überladene Suchmethode für die admins, der test auf mehr als
	5 suchbgriffe fehlt hier.
*/

dd_result sxpagesearchadmin::on_search( dditem& item )
{
		
	// ergebnisliste erstmal abschalten.
	//snlist.clear_children();
	dditem& snlist = get_body();
	snlist.set_visible( false ); 
	
	// title setzen
	context.pagetitle	= context.pagetitlestatic + ": " + get_cgi()["sn_key"];
	
	// key leer? dann weg
	if( !prepare_query() )
		return rs_ok;						
		
	ddwebview& table = get_view( get_name() );
	context.numrows = table.fill( "on_search" );
	if( context.numrows <= 0 )
		return create_hint_box( snlist, DDHINTNOTFOUND );
	
	// ab hier: gesucht & gefunden
	snlist.set_visible( true );			
			
	// ...anzeigen...
	dditem& block = get_body()["sn_msgentry"];
	table.on_render( *this, block, context.navifrom, context.navito );	
	
	// ...und gut
	return rs_ok;
	(void) item;

}


/**
	Mehrere Antworten kurz & schmerzlos löschen.
	Wird aus den Übersichten heraus aufgerufen.
*/

dd_result sxpagesearchadmin::on_kill_multi( dditem& item )
{	
	
	ddwebcgi& cgi = get_cgi();
	// über alle kill-kandidaten
	for( size_t i=0; i<200; ++i )
	{	
		
		const ddstring& base = cgi[ "killid" + ddstrutil::from_size_t(i) ];		
		if( base.empty() )
			continue;
				
		// format: <!--#id-->_<!--#id_parent-->_<!--#id_group-->
		ddstringrow row( base, "_", 3 );	
		
		// Fallunterscheidung zwischen replys und postings:
		if( row[0] != row[1] )
			get_view().execute( "on_reply_remove", row[0], row[1] );	
		else
			get_view().execute( "on_remove", row[0] );	

		//??
		// FIX! AUTOMATISIEREN!
		get_groups()[ row[2] ].invalidate_cache();
			
	
	}
	
	return create_redirect();

	(void) item;
}


/**
	Die von Usern erzeugten artikel anzeigen.
*/

dd_result sxpagesearchadmin::on_show_user_content( dditem& item )
{

	// daten holen, sofern nötig...
	ddwebview& table = get_view( get_name() );
	
	// anzeige updaten	
	get_site().get_user_content_count() = "";

		
	// 'geister einträge' löschen: das sind schon angelegte aber nicht mit content
	// gefüllte, die älter als ein tag sind
	
	table.execute( "on_clean_user_content" );
	
	
	// ...daten holen: alle 'drafts' die schon content haben
	context.numrows = table.fill( "on_show_user_content" );			
	
	// ...testen...
	if( context.numrows <= 0 )
		return create_hint_box( get_body(), DDHINTNOGROUPENTRY );	
	
	// ...alles fein...
	get_body().set_visible( true );
	// ...anzeigen...
	dditem& entry = get_body()["sn_msgentry"];
	table.on_render( *this, entry, 0, context.numrows );	
	
	// ...und gut
	return rs_ok;
	(void) item;

}


/**
	Hochgeladene Bilder und ggf. ihre Bewertung anzeigen
*/


dd_result sxpagesearchadmin::on_show_user_images( dditem& item )
{
	
	context.pagetype = "admin";
	ddwebview& table = get_view();

	context.numrows = table.fill( "on_show_user_images" );			
	dditem& block = get_body()["sn_content"];
	
	// ...testen...
	if( context.numrows <= 0 )
		return create_hint_box( block, DDHINTNOTFOUND );	
	
	block.clear_value();
	table.dump();
	
	// ...anzeigen...
	table.on_render( *this, block["sn_msgentry"] );	
	
	
	return rs_ok;
	
	
}


/**
	Hochgeladene Bilder und ggf. ihre Bewertung anzeigen
*/

dd_result sxpagesearchadmin::on_show_user_image_votes( dditem& item )
{
	
	context.pagetype = "admin";
	ddwebview& table = get_view();

	context.numrows = table.fill( "on_show_user_image_votes", get_cgi()["sn_key"] );			
	dditem& block = get_body()["sn_content"];
	block["sn_image"].from_string( get_cgi()["sn_key"] );
	
	// ...testen...
	if( context.numrows <= 0 )
		return create_hint_box( block, DDHINTNOTFOUND );	
	
	block.clear_value();
	table.dump();
	
	// ...anzeigen...
	table.on_render( *this, block["sn_msgentry"] );	
	
	
	return rs_ok;
	
	
}
