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

    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 <sxpageforumbase.h>

/**
	Constructor.
*/

sxpageforumbase::sxpageforumbase( const ddstring& name, ddwebsite* site ) 
: sxpage( name, site, "forum" ), _itemsperhome( 20 )
{	
	// Anzahl der Einträge, die Gästen angezeigt wird. 
	_itemsperhome = site->get_config()["main"].get_int( "items_per_page", 20 );
	_use_overlay_image = site->get_config()["main"].get_bool( "use_forum_overlay_images", false );
	_use_overlay_links = site->get_config()["main"].get_bool( "use_forum_overlay_links", false );

}

/**
	Initialisiert alle gängigen callbacks.
	ACHTUNG! die entsprechenden Items müssen vorhanden sein
*/

void sxpageforumbase::init_requests()
{
	// gilt für 'thread', 'listthread' und 't'
	
	add_request_handler( "on_create",		 					"xx_forum_groups", 						(ddmemptr) &sxpageforumbase::on_create );  
	add_request_handler( "on_preview", 						"xx_forum_preview",  					(ddmemptr) &sxpageforumbase::on_preview );  
	
	add_request_handler( "on_edit",		 						"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_edit, 			2, dduserid::usr_can_edit_news  );  
	add_request_handler( "on_user_edit",	 				"xx_forum_user_update",				(ddmemptr) &sxpageforumbase::on_user_edit,	2  );  	
	add_request_handler( "on_user_update",	 			"xx_forum_user_update",				(ddmemptr) &sxpageforumbase::on_user_edit,	2  );  	

	add_request_handler( "on_update", 						"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_update, 		2, dduserid::usr_can_edit_news  );  
	add_request_handler( "on_remove", 						"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_remove, 		2, dduserid::usr_can_edit_news  );  
	add_request_handler( "on_remove_block",				"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_remove, 		2, dduserid::usr_can_edit_news  );  
	
	add_request_handler( "on_close", 							"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_set_state, 	2, dduserid::usr_can_edit_news  );  
	add_request_handler( "on_open", 							"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_set_state, 	2, dduserid::usr_can_edit_news  ); 
	add_request_handler( "on_solve", 							"xx_forum_update", 						(ddmemptr) &sxpageforumbase::on_solve,			2, dduserid::usr_can_edit_news  );  	
	add_request_handler( "on_set_solved", 				"xx_dummy",										(ddmemptr) &sxpageforumbase::on_set_solved,	2  );
	
	add_request_handler( "on_alert", 							"xx_admin_alert", 						(ddmemptr) &sxpageforumbase::on_alert ); 
	add_request_handler( "on_alert_send",					"xx_admin_alert", 						(ddmemptr) &sxpageforumbase::on_alert_send ); 

	add_request_handler( "on_reply_create",				"xx_forum_show",							(ddmemptr) &sxpageforumbase::on_reply_create, 2 );	
	add_request_handler( "on_reply_vote", 				"xx_dummy",										(ddmemptr) &sxpageforumbase::on_reply_vote );	
	add_request_handler( "on_reply_edit", 				"xx_forum_update_reply",			(ddmemptr) &sxpageforumbase::on_reply_edit, 	2, dduserid::usr_can_edit_news );  
	add_request_handler( "on_reply_user_edit",		"xx_forum_user_update_reply",	(ddmemptr) &sxpageforumbase::on_reply_user_edit, 	2  );  
	add_request_handler( "on_reply_user_update",	"xx_forum_user_update_reply",	(ddmemptr) &sxpageforumbase::on_reply_user_edit, 	2  );  
	add_request_handler( "on_reply_remove", 			"xx_forum_show",							(ddmemptr) &sxpageforumbase::on_reply_remove, 2, dduserid::usr_can_edit_news );  
	add_request_handler( "on_reply_remove_block", "xx_forum_show",							(ddmemptr) &sxpageforumbase::on_reply_remove, 2, dduserid::usr_can_edit_news );  

	add_request_handler( "on_reply_update", 			"xx_forum_update_reply",			(ddmemptr) &sxpageforumbase::on_reply_update,	2, dduserid::usr_can_edit_news );  
	
	add_request_handler( "on_drop_subscription",	"xx_dummy",										(ddmemptr) &sxpageforumbase::on_drop_subscription );
	
	add_request_handler( "on_bookmark",						"xx_dummy",										(ddmemptr) &sxpageforumbase::on_bookmark );
	add_request_handler( "on_bookmark_drop",			"xx_dummy",										(ddmemptr) &sxpageforumbase::on_bookmark );
	add_request_handler( "on_bookmark_update",		"xx_dummy",										(ddmemptr) &sxpageforumbase::on_bookmark );
			
		
	context.navilinkbase = "/--auch falsch--/";
	_linkroot = "/--falsch--/";
	
}



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

dd_result sxpageforumbase::create_box_teaser( dditem& item )
{




	return rs_ok;


	// inhalt schon im cache?
	/*
	if( !_blockteaser.empty() )	
	{
		get_buffer().append( _blockteaser );
		return rs_ok;
	}
	*/	
	// noch nicht im cache, dann bauen
	ddwebview& table = get_view();
	//ddwebcategorymap& cats  =	get_site().get_category_map();
	
	//cats.dump();
	
	
	// erst die entry ids holen
	ddstring entryids;
	table.execute( "on_fetch_teaser_ids" ).read( entryids );
	// dann die einträge dazu
	ddstringrow entries( entryids, "," );
	//table.fill( "on_fetch_teaser_entries", entryids );
	// hier muss jeder eintrag einzeln gerendert werden, da die 
	// templates unterschiedlich sind.
	
	// hack
	item[ "sn_msgentry1" ].set_visible( false );
	item[ "sn_msgentry2" ].set_visible( false );
	item[ "sn_msgentry3" ].set_visible( false );
	
	for( size_t i=0; i < entries.size(); ++i )
	{
		dditem& subitem = item[ "sn_msgentry" + ddstrutil::from_size_t( i+1 ) ];
		table.execute( "on_fetch_teaser_entry", entries[i] ).read( *this, subitem );
		subitem.set_visible( true );
		//table.on_render_entry( *this, subitem, i, true );
	
		// hack: cat aus dem item holen
		//const ddstring& catpath = cats.find_category_by_key( subitem[ "sn_categorykey" ].get_value() ).path;
		//subitem[ "sn_catpath" ].from_string( catpath );
	}
	get_buffer().append( item.to_string() );
	
	return rs_ok;
	
}


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

dd_result sxpageforumbase::create_box_news( dditem& item )
{

	ddwebview& table = get_view();	
	table.fill( "on_fetch_news" );
	item.clear_value();
	table.on_render( *this, item["sn_msgentry"] );	
	get_buffer().append( item.to_string() );
	
	return rs_ok;

}


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

dd_result sxpageforumbase::create_box_top_news( dditem& item )
{
	ddwebview& table = get_view();	
	table.fill( "on_fetch_top_news" );
	item.clear_value();
	table.on_render( *this, item["sn_msgentry"] );	
	get_buffer().append( item.to_string() );
	
	return rs_ok;
}

/**
 	Die Supportnet Cache-Übersicht Seite rendern.
 	--changed--
*/

dd_result sxpageforumbase::on_overview( dditem& item )
{
	// hack '/mostwanted/' ist doppelter content zu '/', also redirecte
	context.pagetitle = get_site().get_default_page_title();
	if( get_full_path() == "/mostwanted/" )
		return create_redirect( "/", ret_301_moved_permanently );
		
	// ausschnitt der tabelle ermitteln
	dduserid& uid = get_user_id();

	// 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
	ddstring count;	
	table.execute( "on_count", DDADMFILTER ).read( count );	
	context.numrows = count.as_int();
	dditem& entry = get_body()["sn_content"]["sn_msgentry"];
	table.on_render( *this, entry, 0, numrows );	
		
	// ...und gut
	return rs_ok;
	(void) item;
	
}

/**
 	Allgemeiner Einstieg: Das Antwortformular säubern und dann den Thread anzeigen,
	mittels @see on_show_entry, das wird dann überladen in 
	- @see sxpagefaqs
	Unterschied sind hier nur die unterschiedlichen form-pfade.
	
*/

dd_result sxpageforumbase::on_show( dditem& item )
{
	
	// draftID löschen
	get_user_id().clear_property( DDENTRYID );	
	get_body()["sn_box_post_reply"]["sn_subbody"].clear_children();
	return on_show_entry( item );
}


/**
 	Einen Thread im Forum anzeigen, überladene Version
*/

dd_result sxpageforumbase::on_show_entry( dditem& item )
{
	
	dduserid& uid = get_user_id();
	
	// thread holen ...
	ddwebview& table = get_view( get_name()+".show" );
	// param 2 steuert den müllfilter: admins kriegen den müll zu sehen
  context.numrows = table.fill( "on_show", context.id, DDADMFILTERFORUM );
	
	
	// alt: 404 erzeugen
	// neu: exceptions vermeiden und dummy page anzeigen
	if( !context.numrows )
		return create_redirect( "/linknotfound?sn_key=" + get_full_path().dup().escape(), ret_301_moved_permanently );

	
	if( table[0]["id_type"] != "posting" )
		return create_error( "Falscher Artikeltyp: " + table[0]["id_type"], ddwebresponse::ret_404_not_found );
	
	// Posting anzeigen
	get_body().clear_value();
	table.on_render_entry( *this, get_body()["sn_msgentry"], 0, true );
		
	create_header_entries( table, item );
			
	dditem& blockpostreply = get_body()["sn_box_post_reply"];
	// thread veraltet?
	if( /*get_user_id().is_guest() && */ table[0]["sn_age"].as_int() > 90 )
		create_hint_box( blockpostreply, DDHINTDEPRECATED );
	else
		// thread geschlossen?
		create_hint_box( blockpostreply, DDHINTCLOSED, table[0].is_closed() );
	
	dditem& thread = get_body()["sn_comments"];			
  thread.set_visible( context.numrows > 1 );
 
 	// mailbenachrichtigungssperre löschen
	ddmailmanager& mm = get_site().get_mail_manager();
	mm.clear_alert_flag( uid.get_nick_name(), context.id );
 	
 	if( context.numrows > 1 )
  	table.on_render( *this, thread, context.navifrom+1, context.navito+1 );	
 
 	// ...navi basteln ...
	context.navilinkbase = _linkroot + context.id + "/";
	// hack
	item.set_field_value( "sn_gtraq", context.id == "1437277" ? "" : " " );
	
	// ...und gut
	return rs_ok;
	

}


/**
 Die Gruppenseiten im Forum rendern, Unterschied zu sxpage::on_show_group:
 Es wird versucht, die Übersichten aus einem Cache zu holen.
*/

dd_result sxpageforumbase::on_show_group( dditem& item )
{
 	// draftID löschen
	get_user_id().clear_property( DDENTRYID );
	
	// eventuell redirecten, anhand der grpid
	ddstring idgrp;	
	if( get_site().translate_group_id( context.idgrp, idgrp ) )
		return create_redirect( "/groups/" + idgrp, ret_301_moved_permanently );
	
	
	dditem& block = get_body()["sn_content"];
	block.clear_value();
	
	if( !get_user_id().is_sub_admin() && !get_site().is_group_valid( idgrp.as_int() ) )				
		return create_hint_box( block, DDHINTNONPUBLICGROUP );
 	
 	// header krempel anzeigen	
	ddwebgroup<ddwebgroupmgr>& group = get_groups()[ idgrp ];
	
	// Gruppen-Schrempel  
	context.pagetitle = "Supportnet - Gruppe " + group.get_name();
	get_item()["sn_meta"]["sn_meta_header"].from_string( group.get_description() );
	get_item()["sn_meta"]["sn_meta_keyword"].from_string( group.get_keys() );
	
	// Ist der Block im Cache?
	ddstring cachekey = ddstrutil::from_int( context.itemspp ) + "." + get_raw_path();
	const ddstring& pagedata = group.get_cache_entry( cachekey );
	
	// page ist im cache: ab dafür..
	if( !pagedata.empty() )
	{
		get_body().from_string( pagedata );
		return rs_ok;
	}
	
	// Nicht im cache: erzeugen
	
	// ausschnitt der tabelle ermitteln
	ddstring sxcount  = ddstrutil::from_size_t( context.itemspp );
	ddstring sfrom    = ddstrutil::from_size_t( context.navifrom );
	
	// daten holen...
	ddwebview& table = get_view( get_name() + ".groups" );
	context.numrows = table.fill( "on_show_group", idgrp, DDADMFILTER, sfrom, sxcount );	
	
	// ...testen...
	dditem& list = block["sn_msgentry"];
	if( context.numrows <= 0)
		return create_hint_box( block, DDHINTNOGROUPENTRY );	
	
	// ...alles fein...
	list.set_visible( true );
	
	// ...anzeigen...
	table.on_render( *this, list, 0, context.numrows );	
	
	table.execute( "on_count", idgrp, DDADMFILTER ).read( context.numrows );	
	// für den navi
	context.navilinkbase =  "/groups/" + idgrp + "/";

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

	
}


/**
 	Einen Thread als Lösung markieren, admin-version
*/

dd_result sxpageforumbase::on_solve( dditem& item )
{	
	ddwebcgi& cgi = get_cgi();
	// cache auch löschen
	// FIX! Der Cache wird eh nicht benutzt!!
	//get_groups()[ cgi["id_group"] ].invalidate_cache();
	
	// ...ausführen....
	ddwebview& table = get_view();
	// flag:
	ddstring op = "id_state | 16";
	// sowohl parent als auch
	table.execute( "on_set_state", op, context.id );	
	// kind als lösung markieren
	table.execute( "on_set_state", op, cgi["id"] );	

	// punkte vergeben: der sender ...
	size_t points = get_user_id().get_rank_score();
	// an den Empänger
	ddstring& iduser = cgi["id_user"];
	// nicht aber bei gästen
	if( iduser != "1" )
		get_user_manager().usr_inc_score( iduser, points );
	
	// ...und zur Übersicht zurück.
	return create_redirect(  get_full_path() );
	
	(void) item;
}	


/**
	Alte Version von on_create, in sxpage ist eine andere variante am start.
	
	Neu: Fallunterscheidung:
	
	Bei Members ist alles wie gehabt,
	Gäste werden umgeleitet auf die registerseite,
	vorher muss ihr geschreibsel aber unbedingt 
	gespeichert werden.
	
*/

dd_result sxpageforumbase::on_create( dditem& item )
{
	
	//ddbasetime timer;
	//timer.start();
	
	ddwebcgi& cgi = get_cgi();
	
	// noch nichts belegt?
	if( cgi["id_user"].empty() )
		return rs_ok;
	
	dditem& block = get_body()["sn_block_create"]["sn_subbody"];
	ddformmanager& mgr = get_site().get_form_manager();
	dduserid& uid = get_user_id();
	ddwebview& table = get_view();
	
	// ab hier: es wird versucht, einen thread anzulegen.
	
	// daten erst testen...
	if( !mgr.check_form( "check.posting", block, uid, cgi ) )
		return rs_ok;
		
	// nur speichern, wenn ok
	if(	!mgr.contains_blocked_words() )
	{
		
		// .. ip nachreichen ...
		cgi["sn_senderip"]	= get_connection().get_host_ip();
		
		// ... overlay die links einbauen...
		if( _use_overlay_links )	
			get_site().get_overlay_links().replace_keys( cgi["sn_msgbody"] );
		// ... eventuell die bilder einbauen...
		if( _use_overlay_image )	
			get_site().get_overlay_images().replace_keys( cgi["sn_msgbody"], cgi["sn_msgsubject"] );
	
		// hack: bei gästen die anmeldeprozedur starten, dazu die query umbiegen
		// und den ganzen sotter in der tabelle tr_msgtmp speichern.
		
		/*
		
		Daten ab hier:
		
		key: <id_group> value: <56>
		key: <id_user> value: <1>
		key: <sn_mailalert> value: <9>
		key: <sn_msgbody> value: <cgi.dump();>
		key: <sn_msgsubject> value: <cgi.dump();>
		key: <sn_senderip> value: <127.0.0.2>
		key: <sx_action> value: <on_create>

		*/
		
		if( uid.is_guest() )
		{
			cgi[ "sn_key" ] = uid.get_session_key();
			cgi[ "sn_lastpath" ] = uid.get_property( DDLASTPATH );		
			cgi[ DDACTIONKEY ] = "on_tmp_create";
			table.execute( cgi );
			// gäste zum anmelden schicken
			return create_login_message( "Nach dem Anmelden wird ihre Nachricht freigeschaltet." );
		}
		
		// und noch eine Fallunterscheidung: Müssen wir einen temporären
		// Beitrag umbiegen oder legen wir einen neuen an?
		
		// Gibt es einen Draft-Eintrag?
		ddstring draftid;
		get_view( "sxpageforumstart.draft" ).execute( "fetch_draft", uid.get_id() ).read( draftid );
		cgi[ "id_type" ] = "posting";
		// es gibt keinen 'Entwurf', also stino inserter anwerfen
		if( draftid.empty() )
		{
			table.execute( cgi );
		}
		else
		{
			cgi[ "id" ] = draftid;
			cgi[ "id_parent" ] = draftid;
			get_view( "sxpageforumstart.draft").execute( "on_draft_update", cgi );
		}
		
		// draftID löschen
		get_user_id().clear_property( DDENTRYID );
		
			
	}
	
	// ...und zur Übersicht
	return create_redirect( get_full_path().trim_pattern( "/docreate" ) );
	(void) item;

}


/**
	Eine Antwort erzeugen, überladene Version für threads, welche korrekt ans
	Ende des threads springt, damit man seine frisch geschriebene Antwort sehen
	kann.
*/

dd_result sxpageforumbase::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_box_post_reply"]["sn_subbody"];
	ddformmanager& mgr = get_site().get_form_manager();
	
	// testen, ob der thread überhaupt offen und gültig ist.
	ddwebview& table = get_view( get_name()+".comments" );
	int flag;
	table.execute( "on_close_check", context.id ).read( flag );
	if( flag )
		return create_error( "Thread geschlossen oder ung&uuml;ltig!" );
	
	// im fehlerfall:
	if( !mgr.check_form( "check.reply", block, uid, cgi ) || mgr.contains_blocked_words() )
		return on_show_entry( item );

	// alles ok: die fehlenden Daten nachreichen...	
	cgi["id"]						= context.id;
	cgi["sn_senderip"]	= get_connection().get_host_ip();
	cgi["id_user"]			= uid.get_id();
	cgi["sn_nickmail"]	= uid.get_nick_mail();

	cgi.dump();
	
	// hack: bei gästen die anmeldeprozedur starten, dazu die query umbiegen
	// und den ganzen sotter in der tabelle tr_msgtmp speichern.
	
	/*
	
	Daten ab hier:
	
	key: <id> value: <2333390>
	key: <id_group> value: <56>
	key: <id_user> value: <1>
	key: <sn_mailalert> value: <9>
	key: <sn_msgbody> value: <moooooooooo>
	key: <sn_msgsubject> value: <RE: cgi.dump();>
	key: <sn_nickmail> value: <>
	key: <sn_senderip> value: <127.0.0.2>
	key: <sx_action> value: <on_reply_create>

	*/
	
	if( uid.is_guest() )
	{
		cgi[ "sn_key" ] = uid.get_session_key();
		cgi[ "sn_lastpath" ] = uid.get_property( DDLASTPATH );		
		cgi[ DDACTIONKEY ] = "on_tmp_reply_create";
		table.execute( cgi );
		// gäste zum anmelden schicken
		return create_login_message( "Nach dem Anmelden wird ihre Nachricht freigeschaltet." );
	}
	
		
	// und noch eine Fallunterscheidung: Müssen wir einen temporären
	// Beitrag umbiegen oder legen wir einen neuen an?
		
	// Gibt es einen Draft-Eintrag?
	ddstring draftid;
	get_view( "sxpageforumstart.draft").execute( "fetch_draft", uid.get_id() ).read( draftid );
	cgi[ "id_type" ] = "reply";	
	// es gibt keinen 'Entwurf', also stino inserter anwerfen
	if( draftid.empty() )
	{
		table.execute( cgi );
	}
	else
	{
		cgi[ "id" ] = draftid;
		// hier sind wir kind
		cgi[ "id_parent" ] = context.id;
		get_view( "sxpageforumstart.draft").execute( "on_draft_update", cgi );
		
	}
	// draftID löschen
	get_user_id().clear_property( DDENTRYID );	
	
	/*
		BUG SNSPII-156:
		Aufgrund der langen uptime von 10 tagen wurde die cache-table nicht neu geladen und die betreffenden threads sind da rausgegplumst.
		Im Detail: post von 30.8, letzte antwort 31.8, Serverstart am 22.9 -> thread ist zu alt, kommt nicht in die cache-table
		neue antwort am 29.09 -> thread müsste in die Übersicht, ist aber nicht in der cache table ...
	
		Lösung: Die query
		"update tr_msgcache set sn_childcount = sn_childcount + 1, sn_datemodified = now() where id_parent = '2259573'" schlägt im diesem Fall fehl,
		also die query vereinzeln, das ergebnis testen (get_affected_rows ) und ggf. dann ein "insert into tr_msgcache select ... " hinterherschicken.
	
	*/
	cgi[ "id" ] = context.id;
	int affrows = table.execute( "on_cache_update", cgi ).read();
	// fehlgeschlagen: dann den datensatz in die cache-table laden
	if( !affrows )
		table.execute( "on_cache_insert", cgi );

	// mailalerts verschicken
	ddmailmanager& mm = get_site().get_mail_manager();
	mm.create_alert_mails( context.id, uid.get_nick_mail(), uid.get_nick_name(), cgi["sn_msgsubject"], get_site().get_name() );	
	
	// den antwort-counter hochzählen	
	if( uid.get_id() != "1" )
		get_user_manager().usr_update_single( uid.get_id(), "sn_numanswers", "sn_numanswers+1" );

	// alles ok, wir machen einen redirect auf die letzte seite des threads, damit
	// man die neue Antwort sehen kann.
	
	table.execute( "on_count", context.id, DDADMFILTERFORUM ).read( context.numrows );
	
	//return create_redirect( get_full_path().trim_pattern( "/docreate" ) + "#jumplast" );
	return create_redirect( get_jump_last_url() + "#jumplast" );
	
	
}


dd_result sxpageforumbase::on_user_edit( dditem& item )
{
	
	
	dduserid& uid = get_user_id();
	ddwebcgi& cgi = get_cgi();
	ddwebview& table = get_view();
	dditem& block = get_body()["sn_form"];
	block.clear_children();
	ddformmanager& mgr = get_site().get_form_manager();
	block.clear_children();
	
	// Fall 1: Editieren, also erstmal den Artikel ins Formular laden
	if( cgi[DDACTIONKEY] == "on_user_edit" ) 
	{
		// 1. daten laden	
		get_view().execute( "on_edit", context.id ).read( *this, block );
		
		// 2. testen 
		if( block["sn_nickname"].get_value() != uid.get_nick_name() )
			return create_system_message( "Sie k&ouml;nnen nur Ihre eigenen Beitr&auml;ge &auml;ndern." ); 
		
		if( block["sn_childcount"].get_value().as_int() > 0 )
			return create_system_message( "Sie k&ouml;nnen Ihren Beitrag nur dann &auml;ndern, wenn noch keine Antworten vorhanden sind." ); 
			
		// form ok, id speichern
		uid.set_property( DDENTRYID, context.id );

			
		return rs_ok;
	}
	
	
	// ab hier: es wird versucht, einen thread upzudaten.
	
	// daten erst testen...
	if( !mgr.check_form( "check." + get_name(), block, uid, cgi ) )
		return rs_ok;
	
	// nur speichern, wenn ok
	if(	!mgr.contains_blocked_words() )
		table.execute( cgi );
	
	uid.clear_property( DDENTRYID );
	
	//uid.set_system_message( "Der Artikel wurde erfolgreich abgeschickt.", "Herzlichen Dank f&uuml;r Ihren neuen Artikel." );
	// ...und zur Übersicht bzw. als admin zum neuen thread
	return create_redirect( get_full_path() );

	
}


dd_result sxpageforumbase::on_reply_user_edit( dditem& item )
{
	dduserid& uid = get_user_id();
	ddwebcgi& cgi = get_cgi();
	ddwebview& table = get_view( get_name() + ".comments" );
	dditem& block = get_body()["sn_form"];
	block.clear_children();
	ddformmanager& mgr = get_site().get_form_manager();
	block.clear_children();
	
	// Fall 1: Editieren, also erstmal den Artikel ins Formular laden
	if( cgi[DDACTIONKEY] == "on_reply_user_edit" ) 
	{
		// 1. daten laden	
		table.execute( "on_reply_edit", cgi["id"] ).read( *this, block );
		
		// 2. testen 
		if( block["sn_nickname"].get_value() != uid.get_nick_name() )
			return create_system_message( "Sie k&ouml;nnen nur Ihre eigenen Beitr&auml;ge &auml;ndern." ); 
		
		// form ok, id merken
		uid.set_property( DDENTRYID,  cgi["id"] );
	
		return rs_ok;
	}
	
	
	// ab hier: es wird versucht, eine reply upzudaten.
	
	// daten erst testen...
	if( !mgr.check_form( "check." + get_name(), block, uid, cgi ) )
		return rs_ok;
	
	// nur speichern, wenn ok
	if(	!mgr.contains_blocked_words() )
		table.execute( cgi );
	
	uid.clear_property( DDENTRYID );
		
	//uid.set_system_message( "Der Artikel wurde erfolgreich abgeschickt.", "Herzlichen Dank f&uuml;r Ihren neuen Artikel." );
	// ...und zur Übersicht bzw. als admin zum neuen thread
	return create_redirect( get_full_path() );
	
	
	
	

	return rs_ok;
}



/**
	Das subject-Feld retten und weiter zum 1. Formular.
*/

dd_result sxpageforumbase::query_stage0( dditem& item )
{
	
	// die daten müssen irgendwie von form zu form transportiert
	// werden -> zwischenspeicher beim ersten schritt erstmal löschen
	
	/*
	update:
	
	Alle AOL daus kriegen nur eine IP,
	speichern per session geht also nicht mehr
	HACK: session key simulieren
	
	*/
	
	// erster aufruf, noch nüscht drin -> weiter
	dditem& block = get_body()["sn_subbody"];
	block.clear_children();
	block["sn_msgsubject"].from_string( get_cgi()["sn_msgsubject"] );
	block["sn_key"].from_string( get_site().create_passwd() );
	// draftID löschen
	get_user_id().clear_property( DDENTRYID );
	
	return rs_ok;
	
}


/**
	Eingabeformulare behandeln: Diese Methode wird für beide
	Formularteile benutzt.
*/

dd_result sxpageforumbase::query_stage1( dditem& item )
{
	
	dditem& block  = get_body()["sn_subbody"];
 	ddwebcgi& cgi = get_cgi();
	
	if( get_split_path().size() < 2 )
		return create_error( "query_stage1: path to short: " + get_raw_path() );


cgi.dump();

	const ddstring& key = get_split_path()[1];	
	// testen: dableiben, bis unser form akzeptiert ist ...
	ddformmanager& messman = get_site().get_form_manager();
	if( !messman.check_form( "check.posting", block, get_user_id(), cgi ) )	
	{
		block["sn_key"].from_string( key );
		return rs_ok;
	}
	
	// ... und dann die daten speichern ...
	// FIX ME! auto-sync basteln
	
	dduserid& uid = get_user_id();
	uid.set_property( key + ".sn_msgsubject", cgi["sn_msgsubject"] );
	uid.set_property( key + ".sn_msgbody", cgi["sn_msgbody"] );
	uid.set_property( key + ".id_group", cgi["id_group"] );
	
	// ... und ab zum nächsten schritt
	return create_redirect( "/query2/" + key );
	(void) item;
	
}


dd_result sxpageforumbase::query_stage2( dditem& item )
{
		
	dditem& block  = get_body()["sn_subbody"];
 	block.clear_children();
 	ddwebcgi& cgi = get_cgi();
	
	const ddstring& key = get_split_path()[1];	
	block["sn_key"].from_string( key );
	
	// noch nix neues -> weiter
	if( get_split_path()[0] == "query2" )	
		return rs_ok;
	
	// testen: dableiben, bis unser form akzeptiert ist ...
	ddformmanager& messman = get_site().get_form_manager();
	if( !messman.check_form( "check.posting", block, get_user_id(), cgi ) )	
	{	
		block["sn_key"].from_string( key );
		return rs_ok;
	}
	
	// die vorher gespeicherten Sachen ins CGI zurückschreiben
	dduserid& uid = get_user_id();
	cgi["sn_msgsubject"] = uid.get_property( key + ".sn_msgsubject" );
	cgi["sn_msgbody"]    = uid.get_property( key + ".sn_msgbody" );
	cgi["id_group"]      = uid.get_property( key + ".id_group" );
	
	if( cgi["id_group"].empty() || cgi["sn_msgbody"].empty() || cgi["sn_msgsubject"].empty() )
	{
		get_connection().create_log_entry();
		log_debug( "EMPTY query: " + get_connection().get_log_entry() );
		return create_error( "Sorry, Datenbankfehler!" );
	}
	
	// PFUSCH! Das gehört in die VIEW!
	// ab hier: es wird versucht, einen thread anzulegen.
	
	ddformmanager& mgr = get_site().get_form_manager();
	// daten erst testen...
	if( !mgr.check_form( "check.posting", block, get_user_id(), cgi ) )
		return rs_ok;
	
	// .. ip nachreichen ...
	cgi["sn_senderip"]	= get_connection().get_host_ip();
	cgi[ DDACTIONKEY ]	  = "on_create";
	// uid kram nachreichen
	cgi["id_user"]	  = uid.get_id();
	
	
	// und noch eine Fallunterscheidung: Müssen wir einen temporären
	// Beitrag umbiegen oder legen wir einen neuen an?
		
	// Gibt es einen Draft-Eintrag?
	ddstring draftid;
	get_view( "sxpageforumstart.draft").execute( "fetch_draft", uid.get_id() ).read( draftid );
	cgi[ "id_type" ] = "posting";	
	if( draftid.empty() )
	{
		get_view().execute( cgi );
		get_view().execute( "insert_id" ).read( draftid );
	
	}
	else
	{
		cgi[ "id" ] = draftid;	
		cgi[ "id_parent" ] = draftid;
		get_view( "sxpageforumstart.draft").execute( "on_draft_update", cgi );

	}
	
	// draftID löschen
	get_user_id().clear_property( DDENTRYID );
	
	return create_redirect( "/query4?id_group=" + cgi["id_group"] + "&id_thread=" + draftid );
	
}


dd_result sxpageforumbase::query_stage3( dditem& item )
{
	
	ddwebcgi& cgi = get_cgi();
	dditem& block  = get_body()["sn_subbody"];
	
	get_groups()[ cgi["id_group"] ].create_group_link( block["sn_groupname"] );	
	
	// 'mostwanted' ist hier falsch als linkbase
	// ddstring threadlink = context.navilinkbase + cgi["id_thread"];
	ddstring threadlink = "/t/" + cgi["id_thread"];
	block["sn_l1"].from_string( threadlink );
	block["sn_l2"].from_string( threadlink );
	block["sn_l3"].from_string( threadlink );
	block["sn_l4"].from_string( threadlink );
	
	return rs_ok;	
	
}


