kbkmud/player/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Thanks to abaddon for proof-reading our comm.c and pointing out bugs.  *
 *  Any remaining bugs are, of course, our work, not his.  :)              *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*	ROM 2.4 is copyright 1993-1996 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@pacinfo.com)				   *
*	    Gabrielle Taylor (gtaylor@pacinfo.com)			   *
*	    Brian Moore (rom@rom.efn.org)				   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Tartarus/doc/rom.license                  *
***************************************************************************/

/***************************************************************************
*       Tartarus code is copyright (C) 1997-1998 by Daniel Graham          *
*	In using this code you agree to comply with the Tartarus license   *
*       found in the file /Tartarus/doc/tartarus.doc                       *
***************************************************************************/
#include "include.h"

/* globals from db.c for load_notes */
#if !defined(macintosh)
extern  int     _filbuf         args( (FILE *) );
#endif
extern FILE *                  fpArea;
extern char                    strArea[MAX_INPUT_LENGTH];

void parse_note(CHAR_DATA *ch, char *argument, int type);
bool hide_note(CHAR_DATA *ch, MYSQL_ROW row);
char * escape_string args((char *string));

char * escape_string(char *string)
{
	char txt[MSL];
	mysql_escape_string(txt, string, strlen(string));
	return str_dup(txt);
}

int count_spool(CHAR_DATA *ch, int type)
{
    int count = 0;
    MYSQL_RES *res;
    MYSQL_ROW row;
    mysql_safe_query("SELECT * FROM notes WHERE type=%d", type);
    res = mysql_store_result(&conn);
    while((row=mysql_fetch_row(res)))
    {
	if(!hide_note(ch,row))
		count++;
    }
    mysql_free_result(res);
    return count;
}

void do_unread(CHAR_DATA *ch, char *argument)
{
    	char buf[MAX_STRING_LENGTH];
    	int count;
    	bool found = FALSE;

    	if (IS_NPC(ch))
		return; 

	if ((count = count_spool(ch,NOTE_NOTE)) > 0)
	{
	  	found = TRUE;
	  	sprintf(buf,"\n\rYou have %d new note%s waiting.\n\r", count, count > 1 ? "s" : "");
	  	send_to_char(buf,ch);
	}

	if ((count = count_spool(ch,NOTE_CHANGES)) > 0)
	{
	 	found = TRUE;
	  	sprintf(buf,"\n\rThere %s %d change%s waiting to be read.\n\r", count > 1 ? "are" : "is", count, count > 1 ? "s" : "");
	  	send_to_char(buf,ch);
	}

    	if (!found)
		send_to_char("You have no unread notes.\n\r",ch);
}

void do_note(CHAR_DATA *ch,char *argument)
{
    parse_note(ch,argument,NOTE_NOTE);
}

void do_idea(CHAR_DATA *ch,char *argument)
{
    parse_note(ch,argument,NOTE_IDEA);
}

void do_penalty(CHAR_DATA *ch,char *argument)
{
    return;
    parse_note(ch,argument,NOTE_PENALTY);
}

void do_news(CHAR_DATA *ch,char *argument)
{
    parse_note(ch,argument,NOTE_NEWS);
}

void do_changes(CHAR_DATA *ch,char *argument)
{
    parse_note(ch,argument,NOTE_CHANGES);
}

void append_note(NOTE_DATA *pnote)
{
    char query[MSL];
    sprintf(query,"INSERT INTO notes VALUES(%d,\"%s\",'%s',\"%s\",\"%s\",\"%s\",%ld)",
	pnote->type, pnote->sender, pnote->date, pnote->to_list, pnote->subject, escape_string(pnote->text), pnote->date_stamp);
    mysql_query(&conn, query);
}

bool is_note_to( CHAR_DATA *ch, char *sender, char *to_list )
{
    if ( !str_cmp( ch->original_name, sender))
	return TRUE;

    if ( is_name( "all", to_list ))
	return TRUE;

    if ( IS_IMMORTAL(ch) && is_name( "immortal", to_list ) )
	return TRUE;

    if ( IS_HEROIMM(ch) && is_name( "heroimm", to_list ) )
	return TRUE;

    if (ch->cabal && is_name(cabal_table[ch->cabal].name,to_list))
	return TRUE;

    if (is_name(ch->original_name, to_list))
	return TRUE;

    return FALSE;
}



void note_attach( CHAR_DATA *ch, int type )
{
    NOTE_DATA *pnote;

    if ( ch->pnote != NULL )
	return;

    pnote = new_note();

    pnote->next		= NULL;
    pnote->sender	= str_dup( ch->original_name );
    pnote->date		= str_dup( "" );
    pnote->to_list	= str_dup( "" );
    pnote->subject	= str_dup( "" );
    pnote->text		= str_dup( "" );
    pnote->type		= type;
    ch->pnote		= pnote;
    return;
}

bool hide_note (CHAR_DATA *ch, MYSQL_ROW row)
{
    time_t last_read;

    if (IS_NPC(ch))
	return TRUE;

    switch (atoi(row[0]))
    {
	default:
	    return TRUE;
	case NOTE_NOTE:
	    last_read = ch->pcdata->last_note;
	    break;
	case NOTE_IDEA:
	    last_read = ch->pcdata->last_idea;
	    break;
	case NOTE_PENALTY:
	    last_read = ch->pcdata->last_penalty;
	    break;
	case NOTE_NEWS:
	    last_read = ch->pcdata->last_news;
	    break;
	case NOTE_CHANGES:
	    last_read = ch->pcdata->last_changes;
	    break;
    }
    
    if (atol(row[6]) <= last_read)
	return TRUE;

    if (!str_cmp(ch->name,row[1]))
	return TRUE;

    if (!is_note_to(ch,row[1],row[3]))
	return TRUE;

    return FALSE;
}

void update_read(CHAR_DATA *ch, long stamp, int type)
{

    if (IS_NPC(ch))
	return;
    switch (type)
    {
        default:
            return;
        case NOTE_NOTE:
	    ch->pcdata->last_note = UMAX(ch->pcdata->last_note,stamp);
            break;
        case NOTE_IDEA:
	    ch->pcdata->last_idea = UMAX(ch->pcdata->last_idea,stamp);
            break;
        case NOTE_PENALTY:
	    ch->pcdata->last_penalty = UMAX(ch->pcdata->last_penalty,stamp);
            break;
        case NOTE_NEWS:
	    ch->pcdata->last_news = UMAX(ch->pcdata->last_news,stamp);
            break;
        case NOTE_CHANGES:
	    ch->pcdata->last_changes = UMAX(ch->pcdata->last_changes,stamp);
            break;
    }
}

void parse_note( CHAR_DATA *ch, char *argument, int type )
{
    BUFFER *buffer;
    char buf[MAX_STRING_LENGTH];
    char arg[MAX_INPUT_LENGTH];
    MYSQL_RES *res;
    MYSQL_ROW row;
    char *list_name;
    int vnum;
    int anum;

    if ( IS_NPC(ch) )
	return;

    switch(type)
    {
	default:
	    return;
        case NOTE_NOTE:
	    list_name = "notes";
            break;
        case NOTE_IDEA:
	    list_name = "ideas";
            break;
        case NOTE_PENALTY:
	    list_name = "penalties";
            break;
        case NOTE_NEWS:
	    list_name = "news";
            break;
        case NOTE_CHANGES:
	    list_name = "changes";
            break;
    }

    argument = one_argument( argument, arg );
    smash_tilde( argument );

    if ( arg[0] == '\0' || !str_prefix( arg, "read" ) )
    {
        bool fAll;
 
        if ( !str_cmp( argument, "all" ) )
        {
            fAll = TRUE;
            anum = 0;
        }
 
        else if ( argument[0] == '\0' || !str_prefix(argument, "next"))
        /* read next unread note */
        {
            vnum = 0;
   	    mysql_safe_query("SELECT * FROM notes WHERE type=%d ORDER BY timestamp ASC", type);
	    res	= mysql_store_result(&conn);
            while((row=mysql_fetch_row(res)))
            {
                if (!hide_note(ch,row))
                {
                    sprintf( buf, "[%3d] %s: %s\n\r%s\n\rTo: %s\n\r",
                        vnum, row[1], row[4], row[2], row[3]);
                    send_to_char( buf, ch );
                    page_to_char( row[5], ch );
                    update_read(ch,atol(row[6]),atoi(row[0]));
		    mysql_free_result(res);
                    return;
                }
		else if(is_note_to(ch,row[1],row[3]))
		    vnum++;
            }
	    sprintf(buf,"You have no unread %s.\n\r",list_name);
	    send_to_char(buf,ch);
	    mysql_free_result(res);
            return;
        }
 
        else if ( is_number( argument ) )
        {
            fAll = FALSE;
            anum = atoi( argument );
        }
        else
        {
            send_to_char( "Read which number?\n\r", ch );
            return;
        }
 
        vnum = 0;
	mysql_safe_query("SELECT * FROM notes WHERE type=%d ORDER BY timestamp ASC",type);
	res = mysql_store_result(&conn);
        while((row=mysql_fetch_row(res)))
        {
            if (is_note_to(ch,row[1],row[3]) && (vnum++ == anum))
            {
                sprintf( buf, "[%3d] %s: %s\n\r%s\n\rTo: %s\n\r",
                        anum, row[1], row[4], row[2], row[3]);
                send_to_char( buf, ch );
                page_to_char( row[5], ch );
		update_read(ch,atol(row[6]),atoi(row[0]));
		mysql_free_result(res);
                return;
            }
        }
 
	sprintf(buf,"There aren't that many %s.\n\r",list_name);
	send_to_char(buf,ch);
	mysql_free_result(res);
        return;
    }

    if ( !str_prefix( arg, "list" ) )
    {
	vnum = 0;
	mysql_safe_query("SELECT * FROM notes WHERE type=%d ORDER BY timestamp ASC",type);
	res = mysql_store_result(&conn);

        while((row=mysql_fetch_row(res)))
	{
	    if (is_note_to(ch,row[1],row[3]))
	    {
		sprintf( buf, "[%3d%s] %s: %s\n\r",
		    vnum, hide_note(ch,row) ? " " : "N", 
		    row[1], row[4]);
		send_to_char( buf, ch );
		vnum++;
	    }
	}
	if (!vnum)
	{
	    switch(type)
	    {
		case NOTE_NOTE:	
		    send_to_char("There are no notes for you.\n\r",ch);
		    break;
		case NOTE_IDEA:
		    send_to_char("There are no ideas for you.\n\r",ch);
		    break;
		case NOTE_PENALTY:
		    send_to_char("There are no penalties for you.\n\r",ch);
		    break;
		case NOTE_NEWS:
		    send_to_char("There is no news for you.\n\r",ch);
		    break;
		case NOTE_CHANGES:
		    send_to_char("There are no changes for you.\n\r",ch);
		    break;
	    }
	}
	mysql_free_result(res);
	return;
    }

    if ( !str_prefix( arg, "remove" ) )
    {
        if ( !is_number( argument ) )
            return send_to_char( "Note remove which number?\n\r", ch );

 
        anum = atoi( argument );
        vnum = 0;
	mysql_safe_query("SELECT * FROM notes WHERE type=%d ORDER BY timestamp ASC",type);
	res =  mysql_store_result(&conn);
        while((row=mysql_fetch_row(res)))
	{
            if (!str_cmp(ch->original_name, row[1]) && vnum++ == anum )
            {
		mysql_safe_query("DELETE FROM notes WHERE timestamp=%s AND sender=\"%s\"", row[6], row[1]);
                send_to_char( "Ok.\n\r", ch );
		mysql_free_result(res);
                return;
            }
        }
 
	send_to_char("You must provide the number of a note you have written to remove.\n\r",ch);
	mysql_free_result(res);
        return;
    }
 
    if ( !str_prefix( arg, "delete" ) && get_trust(ch) >= MAX_LEVEL - 2)
    {
        if ( !is_number( argument ) )
            return send_to_char( "Note delete which number?\n\r", ch );
 
        anum = atoi( argument );
        vnum = 0;
	mysql_safe_query("SELECT * FROM notes WHERE type=%d ORDER BY timestamp ASC",type);
	res	= mysql_store_result(&conn);
        while((row=mysql_fetch_row(res)))
	{
            if ( is_note_to( ch,row[1],row[3] ) && vnum++ == anum )
            {
		mysql_safe_query("DELETE FROM notes WHERE timestamp=%s AND sender=\"%s\"", row[6], row[1]);
		send_to_char("Ok.\n\r",ch);
		mysql_free_result(res);
		return;
            }
        }

 	sprintf(buf,"There aren't that many %s.",list_name);
	send_to_char(buf,ch);
	mysql_free_result(res);
        return;
    }

    /* below this point only certain people can edit notes */
    if ((type == NOTE_NEWS && !IS_TRUSTED(ch,ANGEL))
    ||  (type == NOTE_CHANGES && !IS_TRUSTED(ch,CREATOR)))
    {
	sprintf(buf,"You aren't high enough level to write %s.",list_name);
	send_to_char(buf,ch);
	return;
    }

    if ( !str_cmp( arg, "+" ) )
    {
	note_attach( ch,type );
	if (ch->pnote->type != type)
	    return send_to_char("You already have a different note in progress.\n\r",ch);

	if (strlen(ch->pnote->text)+strlen(argument) >= 4096)
	    return send_to_char( "Note too long.\n\r", ch );

 	buffer = new_buf();

	add_buf(buffer,ch->pnote->text);
	add_buf(buffer,argument);
	add_buf(buffer,"\n\r");
	free_string( ch->pnote->text );
	ch->pnote->text = str_dup( buf_string(buffer) );
	free_buf(buffer);
	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if (!str_cmp(arg,"-"))
    {
 	int len;
	bool found = FALSE;

	note_attach(ch,type);
        if (ch->pnote->type != type)
            return send_to_char("You already have a different note in progress.\n\r",ch);

	if (ch->pnote->text == NULL || ch->pnote->text[0] == '\0')
	    return send_to_char("No lines left to remove.\n\r",ch);

	strcpy(buf,ch->pnote->text);

	for (len = strlen(buf); len > 0; len--)
 	{
	    if (buf[len] == '\r')
	    {
		if (!found)  /* back it up */
		{
		    if (len > 0)
			len--;
		    found = TRUE;
		}
		else /* found the second one */
		{
		    buf[len + 1] = '\0';
		    free_string(ch->pnote->text);
		    ch->pnote->text = str_dup(buf);
		    return;
		}
	    }
	}
	buf[0] = '\0';
	free_string(ch->pnote->text);
	ch->pnote->text = str_dup(buf);
	return;
    }

    if ( !str_prefix( arg, "subject" ) )
    {
	note_attach( ch,type );
        if (ch->pnote->type != type)
            return send_to_char("You already have a different note in progress.\n\r",ch);

	free_string( ch->pnote->subject );
	ch->pnote->subject = str_dup( argument );
	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if ( !str_prefix( arg, "to" ) )
    {
	note_attach( ch,type );
        if (ch->pnote->type != type)
            return send_to_char("You already have a different note in progress.\n\r",ch);

	if (is_name("all", argument)
	&& !IS_IMMORTAL(ch)
	&& !IS_HEROIMM(ch)
	&& !(ch->pcdata->induct == CABAL_LEADER)
	&& !(ch->pcdata->empire >= EMPIRE_SLEADER))
	{
		send_to_char("Sorry, you can't do that!\n\r",ch);
		return;
	}
	free_string( ch->pnote->to_list );
	ch->pnote->to_list = str_dup( argument );
	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if ( !str_prefix( arg, "clear" ) )
    {
	if ( ch->pnote != NULL )
	{
	    free_note(ch->pnote);
	    ch->pnote = NULL;
	}

	send_to_char( "Ok.\n\r", ch );
	return;
    }

    if ( !str_prefix( arg, "show" ) )
    {
	if ( ch->pnote == NULL )
	    return send_to_char( "You have no note in progress.\n\r", ch );

	if (ch->pnote->type != type)
	    return send_to_char("You aren't working on that kind of note.\n\r",ch);

	sprintf( buf, "%s: %s\n\rTo: %s\n\r",
	    ch->pnote->sender,
	    ch->pnote->subject,
	    ch->pnote->to_list
	    );
	send_to_char( buf, ch );
	send_to_char( ch->pnote->text, ch );
	return;
    }

    if ( !str_prefix( arg, "post" ) || !str_prefix(arg, "send"))
    {
	char *strtime;

	if ( ch->pnote == NULL )
	    return send_to_char( "You have no note in progress.\n\r", ch );

        if (ch->pnote->type != type)
            return send_to_char("You aren't working on that kind of note.\n\r",ch);

	if (!str_cmp(ch->pnote->to_list,""))
	    return send_to_char("You need to provide a recipient (name, all, cabal, or immortal).\n\r", ch);

	if (!str_cmp(ch->pnote->subject,""))
	    return send_to_char("You need to provide a subject.\n\r",ch);

	ch->pnote->next			= NULL;
	strtime				= ctime( &current_time );
	strtime[strlen(strtime)-1]	= '\0';
	ch->pnote->date			= str_dup( strtime );
	ch->pnote->date_stamp		= current_time;

	append_note(ch->pnote);
	ch->pnote = NULL;
	send_to_char("Note sent.\n\r",ch);
	return;
    }

    send_to_char( "You can't do that.\n\r", ch );
    return;
}