/***************************************************************************
* 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( ¤t_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;
}