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

    supportware
    Copyright (C) 2001-2010 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 <sxpagemembers.h>
#include <dditemset.h>
#include <dditemlink.h>
#include <ddwebconnection.h>


/**
	Constructor.
*/

sxpagemembers::sxpagemembers( const ddstring& name, ddwebsite* site )
: sxpage( name, site, "members", "Mitgliederliste" )
{
	
	add_request_handler( "members", 									"xx_members_overview",					(ddmemptr) &sxpagemembers::member_main );
	add_request_handler( "memberlist", 								"xx_members_overview", 					(ddmemptr) &sxpagemembers::member_list, 4 );
  add_request_handler( "membersearch", 							"xx_members_overview", 					(ddmemptr) &sxpagemembers::member_search );
	
  add_request_handler( "adm_membersearch",  				"xx_admin_membersearch", 				(ddmemptr) &sxpagemembers::adm_member_search, 1, dduserid::usr_can_edit_news );	
	add_request_handler( "adm_memberlist",  					"xx_admin_memberlist",	 				(ddmemptr) &sxpagemembers::adm_member_list, 	1, dduserid::usr_can_edit_news );	
	
	add_request_handler( "member_show",       				"xx_members_show_tab1", 				(ddmemptr) &sxpagemembers::member_show, 2 );
	add_request_handler( "member",			       				"xx_members_show_tab1", 				(ddmemptr) &sxpagemembers::member_tab1_home, 	2 );
	add_request_handler( "beitraege",			     				"xx_members_show_tab2", 				(ddmemptr) &sxpagemembers::member_tab2_content, 2 );
	add_request_handler( "meine_einstellungen",  			"xx_members_show_tab3", 				(ddmemptr) &sxpagemembers::member_tab3_config );	
	
	add_request_handler( "member_register", 					"xx_members_register", 					(ddmemptr) &sxpagemembers::member_register );
	add_request_handler( "member_activate", 					"xx_members_login", 						(ddmemptr) &sxpagemembers::member_activate );	
	add_request_handler( "member_login", 							"xx_members_login", 						(ddmemptr) &sxpagemembers::member_login  );	
	add_request_handler( "member_logout", 						"xx_dummy",					 						(ddmemptr) &sxpagemembers::member_logout );	
	add_request_handler( "member_welcome", 						"xx_dummy",						 					(ddmemptr) &sxpagemembers::member_welcome  );		
	add_request_handler( "member_passwd", 						"xx_members_passwd",						(ddmemptr) &sxpagemembers::member_passwd, 	1,	dduserid::usr_is_member );
	add_request_handler( "member_block", 							"xx_members_admin" ,						(ddmemptr) &sxpagemembers::member_block,		1, 	dduserid::usr_can_edit_usr );
	add_request_handler( "member_setup", 							"xx_members_admin" ,						(ddmemptr) &sxpagemembers::member_setup );
	add_request_handler( "member_passmail", 					"xx_members_base",							(ddmemptr) &sxpagemembers::member_passmail, 1,	dduserid::usr_can_edit_usr  );
	add_request_handler( "member_sendpass", 					"xx_members_sendpass", 					(ddmemptr) &sxpagemembers::member_sendpass );
		
	
	// aufgehübschte alte ...
	add_request_handler( "on_edit",										"xx_members_update",						(ddmemptr) &sxpagemembers::on_edit, 		1,	dduserid::usr_is_member );
	add_request_handler( "on_edit_home",							"xx_members_update_home",				(ddmemptr) &sxpagemembers::on_edit, 		1,	dduserid::usr_is_member );
	
	add_request_handler( "on_update",									"xx_members_update",						(ddmemptr) &sxpagemembers::on_update, 	1,	dduserid::usr_is_member );
	add_request_handler( "on_update_home",						"xx_members_update_home",				(ddmemptr) &sxpagemembers::on_update, 	1,	dduserid::usr_is_member );
	add_request_handler( "on_admin_edit", 						"xx_members_admin",							(ddmemptr) &sxpagemembers::on_admin_edit,    1,	dduserid::usr_can_edit_usr );
	add_request_handler( "on_admin_update",						"xx_members_admin",							(ddmemptr) &sxpagemembers::on_admin_edit,    1,	dduserid::usr_can_edit_usr );
	add_request_handler( "on_admin_remove",						"xx_members_admin",							(ddmemptr) &sxpagemembers::on_admin_edit,    1,	dduserid::usr_can_edit_usr );
	add_request_handler( "on_preview",								"xx_members_preview", 					(ddmemptr) &sxpagemembers::on_preview );
	add_request_handler( "on_save_settings", 					"xx_dummy", 										(ddmemptr) &sxpagemembers::on_save_settings );
	
	// neu: listen
	add_request_handler( "list_friends",							"xx_members_list", 							(ddmemptr) &sxpagemembers::on_list_friends );
	add_request_handler( "list_visitors", 						"xx_members_list",  						(ddmemptr) &sxpagemembers::on_list_visitors );  
	add_request_handler( "list_invitations_sent",			"xx_members_list",  						(ddmemptr) &sxpagemembers::on_list_invitations_sent );  
	add_request_handler( "list_invitations_received",	"xx_members_list",  						(ddmemptr) &sxpagemembers::on_list_invitations_received );  
	
	// neu: gästebuch etc.	
	add_request_handler( "on_reply_create",						"xx_members_show_tab1",					(ddmemptr) &sxpagemembers::on_reply_create );
	add_request_handler( "on_reply_preview",					"xx_members_preview_guestbook", (ddmemptr) &sxpagemembers::on_preview );  
	add_request_handler( "on_alert",	 								"xx_admin_alert", 			 				(ddmemptr) &sxpage::on_alert ); 
	add_request_handler( "on_alert_send",							"xx_admin_alert", 			 				(ddmemptr) &sxpage::on_alert_send ); 
	
	// neu: freunde einladen etc.
	add_request_handler( "on_friend_invite",					"xx_dummy", 										(ddmemptr) &sxpagemembers::on_friend_invite );
	add_request_handler( "on_friend_accept", 					"xx_dummy",  										(ddmemptr) &sxpagemembers::on_friend_accept );  
	add_request_handler( "on_friend_drop", 						"xx_dummy",  										(ddmemptr) &sxpagemembers::on_friend_drop );  
	
	// neu: übersichten
	add_inner_call( 		 "sn_box_members_friends",																(ddmemptr) &sxpagemembers::create_box_friends );
	add_inner_call( 		 "sn_box_members_invitations",														(ddmemptr) &sxpagemembers::create_box_invitations );
	

	

 	// FIX! PFUSCH!

    get_view().connect( "users;localhost;chris;kpdrZ49$#" );
	// die verbotenen mail-provider list anlegen.
	ddstring provs;
	get_site().fetch_data_entry( DDKEYBLOCKEDMAILS, provs );
	ddstringrow providers( provs, "\n" );
	for( size_t i=0; i<providers.size(); ++i )
		_badmails.insert( providers[i] );
	
	// title-liste aufbauen
	_titles["sn_datelastlogin.desc"] 	= " sortiert nach letzter Aktion";
	_titles["sn_nickname.asc"] 				= " sortiert nach Alphabet";
	_titles["sn_datecreated.asc"] 		= " sortiert nach Mitgliedszeit";
	_titles["sn_datecreated.desc"] 		= " sortiert nach Mitgliedszeit";
	_titles["sn_memberbonus"] 				= " sortiert nach Bonus";
	_titles["sn_numquestions"] 				= " sortiert nach Fragen";
	_titles["sn_numanswers"] 					= " sortiert nach Antworten";
	_titles["sn_numreasonable"] 			= " sortiert nach guten Antworten";
	_titles["sn_numsolutions"] 				= " sortiert nach L&ouml;sungen";
	_titles["sn_numvotes"] 						= " sortiert nach Votes";
	_titles["sn_homepagehits.desc"] 	= " sortiert nach Homepage Hits";

}


/**
	Innercall, der die 'Freunde'-Box rendert.
*/

dd_result sxpagemembers::create_box_friends( dditem& item )
{
	ddwebview& table = get_view();
	dditem& block1 = item["sn_msgentry1"];
	const ddstring&  myid = get_user_id().get_id();	
	item.clear_children();
	//item.clear_value();
	
	if( table.fill( "member_friends", myid ) > 0 )
		table.on_render( *this, block1 );
	else
		block1.from_string( "Sie haben noch keine Freunde." );


	//
	// fallunterscheidung: falls der Besucher schon da war, 
	// wir der count erhöht (und das datum aktualisiert),
	// bei neuen besuchern muss erst ein eitrag erzeugt werden.
	//
	
	int count;
	const ddstring& hisid = context.id;
	
	table.execute( "member_visitors_count", hisid, myid ).read( count );
	
	// nur einmal per session zählen, sich selbst nicht zählen
	ddstring vkey = "snhits." + hisid + myid;
	if( hisid != myid && get_user_id().get_property( vkey ).empty() )
	{
		ddstring query = count == 0 ?  "member_visitors_insert" : "member_visitors_update" ;
		table.execute( query, hisid, myid );
		get_user_id().set_property( vkey, hisid );
  }	
	
	dditem& block2 = item["sn_msgentry2"];
	if( table.fill( "member_visitors", hisid ) > 0 )
		table.on_render( *this, block2 );
	else
		block2.from_string(  "Sie haben noch keine Besucher" );


	get_buffer().append( item.to_string() );
	
	return rs_ok;
	
}


dd_result sxpagemembers::create_box_invitations( dditem& item )
{
	ddwebview& table = get_view();
	dditem& block1 = item["sn_msgentry1"];
	const ddstring& id = get_user_id().get_id();
	item.clear_children();
	//item.clear_value();
	
	if( table.fill( "member_invitations_received", id ) > 0 )
		table.on_render( *this, block1 );
	else
		block1.from_string( "Sie haben noch keine Einladungen erhalten." );

	dditem& block2 = item["sn_msgentry2"];
	
	
	if( table.fill( "member_invitations_sent", id ) > 0 )
		table.on_render( *this, block2 );
	else
		block2.from_string(  "Sie haben noch keine Einladungen verschickt." );

	get_buffer().append( item.to_string() );
		
	return rs_ok;
	
}


/**
	Moo!
*/

dd_result sxpagemembers::on_list_friends( dditem& item )
{
	ddwebview& table = get_view();
	dditem& list = get_body()["sn_content"]["sn_msgentry"];
	get_body()["sn_title"].from_string( "Meine Freunde" );
	
	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sxcount = ddstrutil::from_int( context.itemspp );	
	context.numrows = table.fill( "member_friends", get_user_id().get_id() );
	if( context.numrows <= 0 )
	{
		// erzeugt html tabellenfehler
		//return create_hint_box( list, DDHINTNOTFOUND );	
		ddstring hint = "<tr><td>" + ddstring( DDHINTNOTFOUND ) + "</td></tr>"; 
		list.from_string( hint );	
		return rs_ok;
	}
	
	table.on_render( *this, list, 0, context.numrows );	
		
	//context.navilinkbase = linkval;
	
	return rs_ok;
	
}


/**
	Moo!
*/

dd_result sxpagemembers::on_list_visitors( dditem& item )
{
	get_body()["sn_title"].from_string( "Meine Besucher" );
	
	ddwebview& table = get_view();
	dditem& list = get_body()["sn_content"]["sn_msgentry"];

	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sxcount = ddstrutil::from_int( context.itemspp );	
	context.numrows = table.fill( "member_visitors", get_user_id().get_id() );
	if( context.numrows <= 0 )
	{
		// erzeugt html tabellenfehler
		//return create_hint_box( list, DDHINTNOTFOUND );	
		ddstring hint = "<tr><td>" + ddstring( DDHINTNOTFOUND ) + "</td></tr>"; 
		list.from_string( hint );	
		return rs_ok;
	}
	
	table.on_render( *this, list, 0, context.numrows );	
		
	//context.navilinkbase = linkval;
	
	return rs_ok;
	
}


/**
	Moo!
*/

dd_result sxpagemembers::on_list_invitations_sent( dditem& item )
{
	
	get_body()["sn_title"].from_string( "verschickte Einladungen" );
	
	ddwebview& table = get_view();
	dditem& list = get_body()["sn_content"]["sn_msgentry"];
	
	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sxcount = ddstrutil::from_int( context.itemspp );	
	context.numrows = table.fill( "member_invitations_sent", get_user_id().get_id() );
	if( context.numrows <= 0 )
	{
		// erzeugt html tabellenfehler
		//return create_hint_box( list, DDHINTNOTFOUND );	
		ddstring hint = "<tr><td>" + ddstring( DDHINTNOTFOUND ) + "</td></tr>"; 
		list.from_string( hint );	
		return rs_ok;
	}
	
	table.on_render( *this, list, 0, context.numrows );	
		
	//context.navilinkbase = linkval;
	
	return rs_ok;
}


/**
	Moo!
*/

dd_result sxpagemembers::on_list_invitations_received( dditem& item )
{
	
	get_body()["sn_title"].from_string( "empfangene Einladungen" );	
	
	ddwebview& table = get_view();
	dditem& list = get_body()["sn_content"]["sn_msgentry"];
	get_body()["sn_title"].from_string( "Meine Freunde" );
	
	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sxcount = ddstrutil::from_int( context.itemspp );	
	context.numrows = table.fill( "member_invitations_received", get_user_id().get_id() );
	if( context.numrows <= 0 )
	{
		// erzeugt html tabellenfehler
		//return create_hint_box( list, DDHINTNOTFOUND );	
		ddstring hint = "<tr><td>" + ddstring( DDHINTNOTFOUND ) + "</td></tr>"; 
		list.from_string( hint );	
		return rs_ok;
	}
	
	table.on_render( *this, list, 0, context.numrows );	
		
	//context.navilinkbase = linkval;
	
	return rs_ok;
	
}
 	
 	
/**
	Eine Antwort erzeugen.
*/

dd_result sxpagemembers::on_reply_create( dditem& item )
{
	
	// um einen eintrag zu erzeugen, müssen die automatikfelder
	// geladen sein, dazu muss der entsprechende thread anzeigt gewesen
	// sein.
	
	ddwebcgi& cgi = get_cgi();
	dduserid& uid = get_user_id();
	dditem& block = get_body()["sn_form"]["sn_subbody"];
	ddformmanager& mgr = get_site().get_form_manager();
	ddwebview& table = get_view();
		
	// im fehlerfall:
	if( !mgr.check_form( "check.comment", block, uid, cgi ) || mgr.contains_blocked_words() ) 
		return member_tab1_home( item );//create_redirect( get_full_path() );create_redirect( "/member );

	// alles ok: die fehlenden Daten nachreichen...	
	cgi["sn_nickmail"]	= uid.get_nick_mail();
	cgi["id_sender"]		= uid.get_id();
	cgi["sn_senderip"]	= get_connection().get_host_ip();
	cgi["id_user"]			= context.id;
	
	// speichern
	table.execute( cgi );
	
	// form säubern
	block.clear_children();
	//return create_redirect( DDMEMBERLINKURL + context.id, ret_302_moved_temporarily );
	//??
	return member_tab1_home( item );

}


/**
	Jemanden als Freund einladen. Format: /member/<meineId>?sx_action=on_friend_invite&id=<seineId>
*/

dd_result sxpagemembers::on_friend_invite( dditem& item )
{
	
	dduserid& uid = get_user_id();
	//dditem& block = get_body()["sn_form"]["sn_subbody"];
	ddwebview& table = get_view();
	//cgi["sn_senderip"]	= get_connection().get_host_ip();
	// speichern
	table.execute( "on_friend_invite", uid.get_id(), get_cgi()["id"] );
	
	return create_redirect( DDMEMBERLINKURL + context.id, ret_302_moved_temporarily );

}


dd_result sxpagemembers::on_friend_accept( dditem& item )
{
	dduserid& uid = get_user_id();
	ddwebview& table = get_view();
	// speichern
	table.execute( "on_friend_accept", uid.get_id(), get_cgi()["id"] );
	
	return create_redirect( DDMEMBERLINKURL + context.id, ret_302_moved_temporarily );
}


dd_result sxpagemembers::on_friend_drop( dditem& item )
{
	dduserid& uid = get_user_id();
	ddwebview& table = get_view();
	// speichern
	table.execute( "on_friend_drop", uid.get_id(), get_cgi()["id"] );
	
	return create_redirect( DDMEMBERLINKURL + context.id, ret_302_moved_temporarily );
}


/**
	Erzeugt die links im header der Tabs auf der memberseite
*/

void sxpagemembers::prepare_page_header()
{

	dditem& item = get_body()["sn_content"];
	item.clear_children();
	// susi's ... visi etc. anzeigen
	item["sn_nick"].from_string( get_user_manager().get_nick_name( context.id ) );
	//item["sn_link1"]["id"].from_string( context.id );
	//item["sn_link1"].set_visible( false );
	// "eigene Einstellungen" sieht nur der Besitzer
	item["sn_config_link"].set_visible( context.id == get_user_id().get_id() ); 

	
}


/**
	Redirect auf den 'neuen' Visi-link.
*/

dd_result sxpagemembers::member_show( dditem& item )
{
	return create_redirect( DDMEMBERLINKURL + get_cgi()["id"], ret_302_moved_temporarily );
}	 
	

/**
	Die Visi eines Members anzeigen.
*/

dd_result sxpagemembers::member_tab1_home( dditem& item )
{	
	
	
	prepare_page_header();
	
	// schrott
  const ddstring& id = context.id;
  ddwebview& table = get_view();		
  dduserid& uid = get_user_id();
	dditem& body = get_body()["sn_content"];
	body.clear_value();
	
	if( table.execute( "member_show", id ).read( *this, body ) < 0 )
		return create_error( "DB-Error:", ddwebresponse::ret_404_not_found );
	
	//??
	if( body["sn_nickname"].get_value().empty() )
	{
		body.from_string( "(Kein Eintrag gefunden)" );
		return rs_ok;
	}
	context.pagetitle =  "Visitenkarte von \"" + body["sn_nickname"].get_value() + "\"";
	
	
	// Pfusch: Je nach persönlichen privacy-vorstellungen des members
	// die eben gelesenen daten wieder zensieren
	
	
	if( !uid.check_property( "xx_prop_name" ) )
	{
		body["sn_firstname"].from_string( "Nicht freigegeben" );
		body["sn_lastname"].clear_value();
	}
	if( !uid.check_property( "xx_prop_address" ) )
	{
		body["sn_street"].from_string( "Nicht freigegeben" );	
		body["sn_city"].from_string( "Nicht freigegeben" );		
	}
	
	
	
	/*
	// prepare hidden admin link
	const ddstring& nick = get_user_manager().get_nick_name( id );
	
	dditem& pager = body["sn_pager"]; 
	if( get_user_id().is_guest() )
	{
		pager.from_string( "Der Pager steht nur Membern zur Verf&uuml;gung." );
	}
	else
	{
		pager.from_string( "" );
		pager["sn_nick2"].from_string( nick ); 
		pager["sn_nick3"].from_string( nick ); 
	}
	*/
	// hack: hide image
	const ddstring& img = body["sn_homepageimage"].get_value();
	if( img.empty() || img == " " )
		body["sn_homepageimage"].from_string( "blank.gif" );
	
	//
	// ab hier: Gästebuch des Members anzeigen, auf die doofe
	//
	
	// daten holen, sofern nötig...
	dditem& comblock = get_body()["sn_comments"];	
	comblock.set_visible( false );
	
	return rs_ok;
	
	context.numrows = table.fill( "member_guestbook", id );
	comblock.set_visible( context.numrows > 0 );		
	if( context.numrows < 0 )
		return rs_ok;
	
	// ...anzeigen...
	table.on_render( *this, comblock["sn_msgentry"] );	
	
	return rs_ok;

}


/**
	Neue Version von 'meine Fragen', 'meine Antworten' etc, diesmal zusammengefasst.
*/

dd_result sxpagemembers::member_tab2_content( dditem& item )
{	

	prepare_page_header();
	
	ddwebview& table = get_view( "sxpagemembers.content" );
 	dditem& snlist = get_body()["sn_content"];
	// FIX! Filter fehlt!
	snlist.clear_value();
	
	context.itemspp 			= get_user_id().get_items_per_page();
 	context.navifrom 			= context.navipage * context.itemspp;
	context.navito   			= context.navifrom + context.itemspp;
 	context.navilinkbase 	= "/beitraege/" + context.id + "/";
 	
	context.numrows = table.fill( "on_overview", context.id );
	if( context.numrows <= 0 )
  	return create_hint_box( snlist, DDHINTNOTFOUND );

	table.on_render( *this, snlist["sn_msgentry"], context.navifrom, context.navito );	
	 
	return rs_ok;
	
	
	/*
	// hier abweichend, da konfigurierbar (siehe ddwebpage::handle_content
	context.itemspp = uid.is_guest() ? _itemsperhome : uid.get_items_per_page();
 	context.navifrom = context.navipage * context.itemspp;
	context.navito   = context.navifrom + context.itemspp;
 	
 	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sitemspp= ddstrutil::from_int( context.itemspp );	
	
	ddwebview& table = get_view( get_name()+".overview" );
	int numrows = table.fill( "on_overview", DDADMFILTER, sfrom, sitemspp );
	
	// für die navigation innerhalb der cache-table
	table.execute( "on_count", DDADMFILTER ).read( context.numrows );	
	
*/		

}


/**
	Rendert "Meine Einstellungen"
*/

dd_result sxpagemembers::member_tab3_config( dditem& item )
{	
	
	dduserid& uid = get_user_id();
	context.id = uid.get_id();
	prepare_page_header();
		
	// properties ins form laden
	dditem& form = get_body()[ "sn_content" ];
	form.clear_children();	
	
	const ddstringmap& properties = uid.get_property_map();
	ddwebcgi::const_iterator pos = properties.begin();
	for( ; pos != properties.end(); ++pos )
	{
		const ddstring& prpkey = (*pos).first;
		// ist es ein user-property ?
		if( prpkey.contains( DDUSERPROPERTY ) )
			// für 'true' bzw. '1' brauchen wir 'checked'
			form.set_field_value( prpkey, uid.check_property( prpkey ) ? "checked" : "" );			
	}
	
	return rs_ok;
	
}


dd_result sxpagemembers::on_save_settings( dditem& item )
{
	
	dduserid& uid = get_user_id();
	context.id = uid.get_id();
	
	// bei änderungen diese erst sichern
	ddwebcgi& cgi =  get_cgi();
	
	cgi.dump();
	
	// 'ungecheckte' checkboxen werden im cgi nicht übertragen,
	// also müssen wir alle vorhandenen properties erstmal löschen
	
	uid.reset_properties();		
	
	// ganz plump den CGI Content als Properties 
	// in die UID blasen
	
	ddwebcgi::const_iterator pos = cgi.begin();
	for( ; pos != cgi.end(); ++pos )
	{
		// ist es ein user-property ?
		if( (*pos).first.contains( DDUSERPROPERTY ) )
			uid.set_property( (*pos).first, (*pos).second );			
	}
	uid.save_properties();		
	
	return create_system_message( "Ihr Einstellungen wurden gespeichert.", "", "", "/meine_einstellungen" );

}





dd_result sxpagemembers::on_alert( dditem& item )
{	
	return rs_ok;
}











/**
	Parameter setzen, Abfrage ausführen und das Ergebnis rendern.
*/

dd_result sxpagemembers::render_table( dditem& list, const ddstring& query, const ddstring& acondition, const ddstring& aorderby, const ddstring& amode, const ddstring& linkval, int max )
{

	ddwebview& table = get_view();		
	
	// 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( ";" );
	
 	ddstring condition	= acondition.dup().trim_all_of( ";" );
 	ddstring mode				= amode.dup().trim_all_of( ";" );
 	ddstring orderby 		= aorderby.dup().trim_all_of( ";" );
 	
 	// daten holen
	ddstring sfrom   = ddstrutil::from_int( context.navifrom );
	ddstring sxcount = ddstrutil::from_int( context.itemspp );	
	context.numrows = table.fill( query, condition, orderby, mode, sfrom, sxcount );
	if( context.numrows <= 0 )
	{
		// erzeugt html tabellenfehler
		//return create_hint_box( list, DDHINTNOTFOUND );	
		ddstring hint = "<tr><td>" + ddstring( DDHINTNOTFOUND ) + "</td></tr>"; 
		list.from_string( hint );	
		return rs_ok;
	}
	
	table.on_render( *this, list, 0, context.numrows );	
		
	// wenn die maximalanzahl nicht gegeben ist, müssen wir 
	// sie selber erforschen
	
	if( max<0 )
		table.execute( "on_count", condition ).read( max );
	
	context.numrows = max;
	context.navilinkbase = linkval;
	
	return rs_ok;
			
	
			
}	


/**
	Die Default-Memberliste anzeigen. 
*/  

dd_result sxpagemembers::member_main( dditem& item )
{
 	dditem& list = get_body()["sn_content"]["sn_msgentry"];
 	return render_table( list, "on_overview", "id>1", "sn_datelastlogin", "desc", "/members/", get_user_manager().size() );
}


/**
	Eine sortierte Memberliste anzeigen.
*/  

dd_result sxpagemembers::member_list( dditem& item )
{	
	
	// pfusch: die sortierung und die
	// db-felder sind in die url kodiert.
	
	ddstring orderby = get_split_path()[1];
	ddstring ordermode = "desc";
  ddstring condition = "id>1";
	size_t dot = orderby.rfind( '.' );
	if( dot != ddstring::npos )
	{
		ordermode = orderby.substr( dot+1 );		
		orderby  = orderby.substr( 0, dot );		
	}
	
	// neu: wie hab hier optionale conditions:
	// - hat der user ein bild auf der visi
	// - hat der user titten 
	
	// bild?
	const ddstring& p1 = get_split_path()[1];
	const ddstring& p2 = get_split_path()[2];
	const ddstring& p3 = get_split_path()[3];
	
	if( p2  == "pic" )
		condition = " sn_homepageimage != '' ";
	
	if( p3  != "p3" )
		condition = " and flag_male = " + p3  == "male" ?  "1 " : "0 ";
	
	
	// title setzen ??	
	context.pagetitle = _titles[ p1 ];
	// params retten
	dditem& block = get_body()["sn_content"];
	block.clear_children();
	block[ p1 ].from_string( "selected" );
	block[ p2 ].from_string( "selected" );	
	block[ p3 ].from_string( "selected" );
	
	dditem& list = block["sn_msgentry"]; 	
	
	/*
	on_overview = "select ' ' sn_online, id, id id_user, sn_nickname, sn_homepagehits, sn_memberbonus, sn_numquestions, sn_numanswers, 
		sn_numreasonable, sn_numsolutions, sn_numvotes,	DATE_FORMAT( sn_datecreated,'%d.%m.%Y') 'sn_datecreated1', 
		DATE_FORMAT( sn_datelastlogin,'%d.%m.%Y') 'sn_datelastlogin1' 
		from tr_user where {condition} order by {orderby} {mode} limit {count}, {max}";	
	*/
	ddstring path = "/memberlist/" + p1 + "/" + p2 + "/" + p3 + "/" ;
	return render_table( list, "on_overview", condition, orderby, ordermode, path, get_user_manager().size() );

}


/**
	Nach Members suchen.
*/  

dd_result sxpagemembers::member_search( dditem& item )
{	
	ddwebcgi& cgi =  get_cgi();	
	// hack
	cgi["field"] = "sn_nickname";
	ddstring condition = cgi["field"] + " like '%" + cgi["sn_key"] + "%'";
	
	// create linkbase for navi
	ddstring path = get_connection().get_request().get_cgi_path();
	size_t dot = path.rfind( "&page" );
	if( dot != ddstring::npos )
		path = path.substr( 0, dot );
	
	dditem& list = get_body()["sn_content"]["sn_msgentry"]; 	
	return render_table( list, "on_overview", condition, cgi["field"], "asc", "/membersearch?" + path +"&page=" );

	(void) item;
	
}


/**
	Die Admin-Memberliste, die Bonus & Punkte anzeigt.
*/  

dd_result sxpagemembers::adm_member_list( dditem& item )
{
	dditem& list = get_body()["sn_subbody"]["sn_msgentry"]; 	
	return render_table( list, "on_admin_search", "id>1", "sn_datelastlogin", "desc", "adm_memberlist/", get_user_manager().size() );
	(void) item;
}


/**
	Die Admin-Variante der membersuche (mit mail & ip)
*/  

dd_result sxpagemembers::adm_member_search( dditem& item )
{
	
	get_body().clear_value();
	
	ddwebcgi& cgi =  get_cgi();
 	if( cgi["key"].empty() )
 		return rs_ok;
  
  // presets erzwingen
	if( cgi["field"].empty() )
		cgi["field"] = "sn_nickname";
	if( cgi["sort"].empty() )
		cgi["sort"] = "sn_nickname";
		
	dditem& hint = get_body();//["sn_hint"]["sn_subbody"];
	hint.clear_children();
	hint["sort_"  + cgi["sort"] ].from_string( "checked" );
	hint["field_" + cgi["field"] ].from_string( "checked" );
	hint["sn_preset"].from_string( cgi["key"] );
	ddstring condition = cgi["field"] + " like '%" + cgi["key"] + "%'";
	
	// create linkbase for navi
	ddstring path = get_connection().get_request().get_cgi_path();
	size_t dot = path.rfind( "&page" );
	if( dot != ddstring::npos )
		path = path.substr( 0, dot );
	
	dditem& list = get_body()["sn_msgentry"]; 	
	return render_table( list, "on_admin_search", condition, cgi["sort"], "asc", "/adm_membersearch?" + path +"&page=" );
	
	(void) item;

	
}




/**
	Ein neues Member anmelden.
*/

dd_result sxpagemembers::member_register( dditem& item )
{
  
	ddwebcgi& cgi =  get_cgi();
	dduserid& uid = get_user_id();
	dditem& body = get_body();
	body.clear_value();
	body.clear_children();
  	
	// erster Versuch, also ein leeres CGI ?
	// dann schlagen wir einen Nickname vor.
	// dieser hat die Form 'Benutzer<nnnn>', wobei
	// <nnnn> die DB-ID ist und von ebendieser bereitgestellt.

	if( cgi.empty() )
	{
		// Wenn noch kein Auto-Nickname erzeugt wurde ...
		if( uid.get_prepared_nickname().empty() )
			get_user_manager().create_auto_nickname( uid );

		// den letzten pfad des users speichern
		body["sn_nickname"].from_string( uid.get_prepared_nickname() );
		return rs_ok;
	}
 
 
	// step 1: Test form data first
 	ddformmanager& messman = get_site().get_form_manager();
	if( !messman.check_form( "check.register", body, uid, cgi ) )
		return rs_ok;
	
	ddstring mail, provider;
	cgi["sn_nickmail"].split( "@", mail, provider );
	if( _badmails.count( provider ) > 0 )
		return create_system_message( DDHINTBADMAIL );
	
	// step 3. create nick
	ddstring passwd = get_site().create_passwd();
	cgi["sn_cryptopass"] = ::crypt( passwd.c_str(), "sn" );
	cgi["sn_senderip"] = uid.get_host_ip();
	
	// throws ...
	get_user_manager().usr_create( cgi );
  
	// success
	ddstring& nickname = cgi["sn_nickname"];
	get_site().get_mail_manager().create_login_mail( nickname, cgi["sn_nickmail"], passwd, get_site().get_name() );
	
	// Zuordnen ter temporären Einträge an die neue UID
	get_view().execute( "update_msg_tmp", nickname, uid.get_session_key() );
	
	// alles fein
	uid.set_system_message( "Herzlich Willkommen!", "Ihre Zugangsdaten wurden per eMail verschickt." );
	
	return create_redirect( "/member_activate?sn_nickname=" + nickname.escape()  );
	
	
	
}


/**
	Redirekt zur Login-Seite nach Neuanmeldung.
*/

dd_result sxpagemembers::member_activate( dditem& item )
{ 
	get_body().clear_children();
 	get_body()["sn_nickname"].from_string( get_cgi()["sn_nickname"] );	
	return rs_ok;
}


/**
	Loginseite
*/

dd_result sxpagemembers::member_login( dditem& item )
{
	
	ddwebcgi& cgi = get_cgi();
  dditem& subbody = get_body();
  subbody.clear_children();
  
	ddstring& nick = cgi["sn_nickname"];
	// 0. stage 1: show form
	
	if( cgi.empty() || nick.empty() )
		return rs_ok;
	
	// 1. sync 
	subbody["sn_nickname"].from_string( nick );
	
	
	// 2. try to login
	ddwebconnection& connection = get_connection();
	// wir haben nur noch gecryptete passwds, also "vorcrypten"
	ddstring passwd = ::crypt( cgi["sn_passwd"].c_str(), "sn" ); 

	
    int result = get_user_manager().check_login( nick, passwd );
  //int result = 1;
  
   // login failed, return reason
	// 3. login failed: choose error
  if( result < 0 )
	{
		log_error( "login failed: " + nick + ": " + passwd );
		if( result == ddusermanager::usr_passwd_wrong )
			subbody["sn_error_passwd"].from_string( "<font color='red'><b>Leider war das Passwort f&uuml;r '" + nick + "' nicht korrekt.</b></font> " );
		else
			subbody["sn_error_nickname"].from_string( "<font color='red'><b>Der Nickname existiert (noch) nicht.</b></font>" );
    return rs_ok;
	}

	// 4. login ok, set new cookie data
	const ddstring& host = connection.get_request().get_domain_name();
  ddwebcookie& cookie = connection.get_response().get_cookie();
	cookie.set_cookie_data( "SNID",nick + DDCOOKIESEPARATOR + passwd, -1, host );	
 	 	
	// 5. show redirect
	return create_redirect( "/member_welcome?sn_nickname="+nick.escape() );
  (void) item;

}


/**
	Nach erfolgreichem Login Cookie Testen und redirects bestimmen.
*/

dd_result sxpagemembers::member_welcome( dditem& item )
{
	// cookie testen
	dduserid& uid = get_user_id();
	ddstring& nick = get_cgi()["sn_nickname"];
 	ddstring& cookie = get_connection().get_request().get_cookie( "SNID" ).get_value();	
 	
	if( !cookie.contains( nick ) )
 	{
		uid.set_system_message( "Das Login-Cookie konnte nicht gesetzt werden!", "Bitte &auml;ndern sie ihre Browsereinstellungen entsprechend, da der Supportnet-Server Sie sonst nicht erkennt." );
		return create_redirect( "/member_login?sn_nickname="+nick.escape() );
  }
	
			
	// cookie ok, wenn der user vor der Registrierung schon beiträge verfasst
	// hat, werden diese jetzt umkopiert.
	
	ddstring path;
	ddwebview& table = get_view();
	table.execute( "check_msg_tmp", nick ).read( path );
	ddstring welcome = "Herzlich Willkommen, " + nick + "!";
	// nüscht? dann home
	if( path.empty() )
	{
		uid.set_system_message( welcome );		
		return create_redirect( "/index.html" );
	}
	
	// es gibt daten? dann kopieren und redirecten	
	table.execute( "copy_msg_tmp", get_site().get_db_name(), uid.get_id(), nick );
	uid.set_system_message( welcome, "Sie werden zu Ihrem Beitrag weitergeleitet." );		
	return create_redirect( path );	

}


/**
	Eine User-Session löschen und das login-Cookie überschreiben.
*/

dd_result sxpagemembers::member_logout( dditem& item )
{
	// UPDATE THE FUCKKING COOKIE!
	ddwebcookie& cookie = get_connection().get_response().get_cookie();
	const ddstring& host = get_connection().get_request().get_domain_name();
	cookie.set_cookie_data( "SNID", ddstring( DDGUESTNICK ) + DDCOOKIESEPARATOR + "xxxxxxxxxxx", -1, host );	

	// show redirect
	return create_redirect( "/home" );
  (void) item;
}




/**
	Das Passwort eines Members ändern.
*/

dd_result sxpagemembers::member_passwd( dditem& item )
{
 
 	// 1. check id
  //dditem& block = get_body()["sn_update"]["sn_subbody"];
  dditem& block = get_body()["sn_subbody"];
  block.clear_value();
  block.clear_children();					
 
 	ddwebcgi& cgi  =  get_cgi();
  dduserid& user = get_user_id();
  
  if( cgi["sn_passwd"].empty() && cgi["sn_passwd1"].empty() )
  	return rs_ok;
		
	// auf vorhandensein testen
	ddformmanager& messman = get_site().get_form_manager();
  if( !messman.check_form( "check.passwd", block, get_user_id(), cgi ) )
  	return rs_ok;

	// gleichheit testen
	if( cgi["sn_passwd"] != cgi["sn_passwd1"] )
	{
		block["sn_passwd1_error"].from_string( "Passworte stimmen nicht &uuml;berein!" );
		return rs_ok;
	}
	
	// schliesslich das pw ändern	
	cgi["id"] = user.get_id();
	get_user_manager().usr_change_passwd( user, cgi["sn_passwd"] );
	
	// UPDATE THE FUCKKING COOKIE!
	ddwebcookie& cookie = get_connection().get_response().get_cookie();
	const ddstring& host = get_connection().get_request().get_domain_name();
	cookie.set_cookie_data( "SNID", user.get_nick_name()+ DDCOOKIESEPARATOR + user.get_passwd(), -1, host );	
	
	// step 7: create redirect to members home.	
	block.from_string( "<h3>Ihr Passwort wurde ge&auml;ndert.</h3>" );
	
	return rs_ok;	 

}


/**
	Die persönlichen Daten eines Members in Form  laden und gut.
*/

dd_result sxpagemembers::on_edit( dditem& item )
{
	
	dditem& block = get_body()["sn_form"];
  block.clear_children();  
	get_view().execute( "member_show", get_user_id().get_id() ).read( *this, block );
	
	// hack
	ddstring flagmale = get_view()[0]["flag_male"];
	// kann leer sein
	block.set_field_value( flagmale, "selected" );
	
	return rs_ok;
		 
}


/**
	Die persönlichen Daten eines Members ändern.
*/

dd_result sxpagemembers::on_update( dditem& item )
{
 	
 	dditem& block = get_body()["sn_form"];
 	
 	// 1. check id
  ddwebcgi& cgi =  get_cgi();
  cgi["id"] = get_user_id().get_id();
  cgi["sn_nickname"] = get_user_id().get_nick_name();
  
	// step 3. Test usr data
	ddstring checker = cgi["sx_action"] == "on_update" ? "check.user" : "check.userhome";
	ddformmanager& messman = get_site().get_form_manager();
   	
 	if( !messman.check_form( checker, block, get_user_id(), cgi ) )
  	return rs_ok;

		
	// step 4: exec query    	
	get_user_manager().usr_update( cgi );
	
	// step 6: UPDATE THE FUCKKING COOKIE!
	ddwebcookie& cookie = get_connection().get_response().get_cookie();
	const ddstring& host = get_connection().get_request().get_domain_name();
	cookie.set_cookie_data( "SNID", get_user_id().get_nick_name()+ DDCOOKIESEPARATOR + get_user_id().get_passwd(), -1, host );	
	
	// step 7: create redirect to members home.
	return create_redirect( DDMEMBERLINKURL + cgi["id"] );	
	
	(void) item;
}



/**
	Die Admin-Page anzeigen.
*/

dd_result sxpagemembers::on_admin_edit( dditem& item )
{
	
	dditem& block  = get_body()["sn_subbody"];
  block.clear_children();

  ddwebcgi& cgi = get_cgi();
  ddstring& querystr = cgi[DDACTIONKEY];
   
   
  cgi.dump(); 
   
   
 	ddusermanager& userman = get_user_manager();
 
	// step 1. if we have an id and no query ... we sync our form from the database
  if( querystr == "on_admin_edit" )
  {
  	get_view().execute( "member_show", context.id ).read( *this, block );
		// set id for passmail
		block["tmpnick"].from_string( block["sn_nickname"].get_value() );	
		block["tmpid"].from_string( context.id );					
		// hack
		ddstring flagmale = get_view()[0]["flag_male"];
		// kann leer sein
		block.set_field_value( flagmale, "selected" );
		
		return rs_ok;						
  }
 
 
 	// step 3. Test usr data
	ddformmanager& messman = get_site().get_form_manager();
  if( !messman.check_form( "check.user", block, get_user_id(), cgi ) )
  	return rs_ok;

	// WAS IST DAS DENN??
	// HOTFIX 
	//cgi["id_user"] = id;

	// FIX! Müll
	if( querystr == "on_admin_update" )
		userman.usr_update( cgi );
	else if( querystr == "on_admin_remove" )
		userman.usr_remove( cgi );
	
	// step 6: create redirect to members home.
	if( querystr == "on_admin_update" )
		return create_redirect(DDMEMBERLINKURL + context.id );	
	return create_redirect( "/members" );
	

}


/**
	Ein Member blocken: 
	 - passwd neu
	 - email neu
	 - session killen
*/  

dd_result sxpagemembers::member_block( dditem& item )
{
	ddwebcgi& cgi = get_cgi();
	
	cgi["sn_passwd"] = get_site().create_passwd();
	get_user_manager().usr_block( cgi );
	return create_redirect( "/members/" + cgi[ "id" ] + "?sx_action=on_admin_edit" );	
}


/**
	kurz und schmerzlos userdaten, etwa items per page, ändern.
*/

dd_result sxpagemembers::member_setup( dditem& item )
{
	
	dduserid& user = get_user_id();
	const ddstring& id = user.get_id();
	ddstring& itemspp =  get_cgi()["sn_itemspp"];
	if( !itemspp.empty() )
	{
		if( user.set_items_per_page( itemspp ) && id != "1" )
			get_user_manager().usr_update_single( id, "sn_itemsperpage", itemspp );
		ddstring ref = get_cgi()["sn_referer"];
		ref.replace_all( "&amp;", "&" );
		return create_redirect( ref );		
	}
	  
  ddstring& answercount = get_cgi()["sn_answers"];
	if( !answercount.empty() )
		user.set_property( DDANSWERCOUNT, answercount );

	// Der _DRECKS_ InternetExlporer sendet keinen referer
	//return create_redirect();
	return create_redirect( get_cgi()["sn_referer"] );
	
	(void) item;
}


/**
	Adminfunktion, die ein neues passwd an einen nutzer 
	schickt.
*/

dd_result sxpagemembers::member_passmail( dditem& item )
{ 
	
	ddstring& id = get_cgi()["sn_nickname"];
	ddusermanager& mgr = get_user_manager();
	int idx = mgr.index_of( id.to_lower() );
	dditem& block = get_body()["sn_content"];
	if( idx<0 )
		return create_hint_box( block, "<h2>Member nicht gefunden: " + id + "</h2><br>" );	
	
	dduserid& user = mgr[idx];
	ddstring pass = get_site().create_passwd();
	
	// passwd im klartext verschicken ...
	get_site().get_mail_manager().create_passwd_mail( user.get_nick_name(), user.get_nick_mail(), pass );
	
	// ... und cryted speichern
	pass = ::crypt( pass.c_str(), "sn" );
	user.set_passwd( pass );
	mgr.usr_update_single( user.get_id(), "sn_cryptopass", pass, true );
	
	return create_hint_box( block, "<h2>Eine neues Passwort wurde an '" + user.get_nick_name() + "' verschickt.</h2>" );	

}


/**
	Hier kann sich der nutzer selbst ein neues passwd schicken lassen.
*/

dd_result sxpagemembers::member_sendpass( dditem& item )
{ 
	return rs_ok;
	ddwebcgi& cgi = get_cgi();
	dditem& block = get_body()["sn_subbody"];
	block.clear_value();
	block.clear_children();
	block.sync( cgi );
	ddstring& nickname = cgi["sn_nickname"];
	ddstring& nickmail = cgi["sn_nickmail"];
	
	if( nickname.empty() || nickmail.empty() )
		return rs_ok;
	
	// user finden
	ddusermanager& mgr = get_user_manager();
	int idx = mgr.index_of( nickname.to_lower() );
	if( idx<0 )
	{
		block["sn_hint"].from_string( "Benutzer nicht gefunden: " + nickname );
		return rs_ok;
	}
	
	dduserid& user = mgr[idx];
	if( user.get_nick_mail().as_lower() != nickmail.as_lower() )
	{
		block["sn_hint"].from_string( "eMail-Adresse nicht gefunden: " + nickmail );
		return rs_ok;
	}
	
	ddstring pass = get_site().create_passwd();
	// passwd im klartext verschicken ...	
	get_site().get_mail_manager().create_passwd_mail( nickname, nickmail, pass );	
	// ... und cryted speichern
	pass = ::crypt( pass.c_str(), "sn" );
	mgr.usr_update_single( user.get_id(), "sn_cryptopass", pass, true );
	user.set_passwd( pass );
	block.from_string( "<b>Das Passwort für '"+nickname+"' wurde an '"+nickmail+"' verschickt.</b>" );

	return rs_ok;	
		
	(void) item;
	
}



/**
	Show a homepage preview, 
*/

dd_result sxpagemembers::on_preview( dditem& item )
{
	dditem& body = get_body();
	
	// hack: zum rendern der bbcodes wird eine article-body
	// vorgetäuscht
	get_cgi()["sn_block_article"] = get_cgi()["sn_homepagetext"];
	// hack für den bild-renderer
	get_cgi()["id_parent"] = get_user_id().get_id();
	get_cgi()["id"] = get_user_id().get_id();
	
	get_view().on_render_cgi( *this, body );
	
	
	
	
	
	
	
	//const ddstring& nick = get_user_manager().get_nick_name( get_cgi()["id"] );
	//body.sync( get_cgi() );
	/*
	dditem& pager = body["sn_pager"]; 
	if( get_user_id().is_guest() )
	{
		pager.from_string( "Der Pager steht nur Membern zur Verf&uuml;gung." );
	}
	else
	{
		pager.from_string( "" );
		pager["sn_nick2"].from_string( nick ); 
		pager["sn_nick3"].from_string( nick ); 
	}
	*/
	// hack: hide image
	const ddstring& img = body["sn_homepageimage"].get_value();
	if( img.empty() || img == ".gif" || img == ".jpg" || img == " " )
		body["sn_homepageimage"].from_string( "blank.gif" );

	return rs_ok;
	
}



dd_result sxpagemembers::on_reply_preview( dditem& item )
{
	/*
	dditem& body = get_body()["sn_visi"];
	const ddstring& nick = get_user_manager().get_nick_name( get_cgi()["id"] );
	body.sync( get_cgi() );
	*/
	/*
	dditem& pager = body["sn_pager"]; 
	if( get_user_id().is_guest() )
	{
		pager.from_string( "Der Pager steht nur Membern zur Verf&uuml;gung." );
	}
	else
	{
		pager.from_string( "" );
		pager["sn_nick2"].from_string( nick ); 
		pager["sn_nick3"].from_string( nick ); 
	}
	*/
	/*
	// hack: hide image
	const ddstring& img = body["sn_homepageimage"].get_value();
	if( img.empty() || img == ".gif" || img == ".jpg" || img == " " )
		body["sn_homepageimage"].from_string( "blank.gif" );
*/
	return rs_ok;
	
}


