/****************************************************************************
* ResortMUD Version 5.0 was mainly programmed by Ntanel, Garinan, Josh, *
* Badastaz, Digifuzz, Senir, Kratas, Scion, Shogar and Tagith. *
* ResortMud Version 5.0b programed By Badastaz and Garinan
* ------------------------------------------------------------------------ *
* Copyright (C) 1996 - 2001 Haslage Net Electronics: MudWorld of Lorain, *
* Ohio. ALL RIGHTS RESERVED See /doc/RMLicense.txt for more details. *
****************************************************************************/
/*****************************************************
** _________ __ **
** \_ ___ \_____|__| _____ ________ ___ **
** / \ \/_ __ \ |/ \/ ___/_ \/ \ **
** \ \___| | \/ | | | \___ \ / ) | \ **
** \______ /__| |__|__|_| /____ \__/__| / **
** ____\/____ _ \/ ___ \/ \/ **
** \______ \ |_____ __| _/___ **
** | | _/ |\__ \/ __ | __ \ **
** | | \ |_/ __ \ / | ___/_ **
** |_____ /__/____ /_ /___ / **
** \/Antipode\/ \/ \/ **
******************************************************
** Crimson Blade Codebase (CbC) **
** (c) 2000-2002 John Bellone (Noplex) **
** Coders: Noplex, Krowe **
** http://www.crimsonblade.org **
*****************************************************/
/*
* File: news.c
* Name: Extended News (v3.03)
* Author: John 'Noplex' Bellone (jbellone@comcast.net)
* Terms:
* If this file is to be re-disributed; you must send an email
* to the author. All headers above the #include calls must be
* kept intact. All license requirements must be met. License
* can be found in the included license.txt document or on the
* website.
* Description:
* This is Crimson Blade's extended news module. It allows for news
* cataglories to be created; each having it's own different filesystem
* where news can be posted. It also allows for each to be specified a
* specific path and filename where the news-textdump of HTML can be
* sent to.
* The news commands are tied directly into the command interpreter; so
* news-types are instantaniously added; removed; and edited.
*/
#include <time.h>
#include "mud.h"
#ifndef FCLOSE
#define FCLOSE(fp) fclose(fp); fp=NULL;
#endif
#ifndef NULLSTR
#define NULLSTR(str) (!str || str[0] == '\0')
#endif
/* locals */
static char local_buf[MAX_INPUT_LENGTH];
static char *news_file_version;
static int top_news_type;
/* the lovely; and useful; command table */
char *news_command_table[NEWS_MAX_TYPES];
/* olc editnews command */
void do_editnews( CHAR_DATA * ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
if( IS_NPC( ch ) || !IS_IMMORTAL( ch ) )
{
send_to_char( "Huh?\r\n", ch );
return;
}
switch ( ch->substate )
{
default:
break;
case SUB_NEWS_POST:
{
NEWS *news = NULL;
NEWS_TYPE *type = NULL;
news = ch->dest_buf;
type = news->temp;
STRFREE( news->post );
news->post = copy_buffer( ch );
stop_editing( ch );
LINK( news, type->first_news, type->last_news, next, prev );
ch->substate = ch->tempnum;
news->temp = NULL;
renumber_news( );
save_news( );
return;
}
break;
case SUB_NEWS_EDIT:
{
NEWS *news = NULL;
news = ch->dest_buf;
STRFREE( news->post );
news->post = copy_buffer( ch );
stop_editing( ch );
ch->substate = ch->tempnum;
renumber_news( );
save_news( );
return;
}
break;
}
argument = one_argument( argument, arg );
if( NULLSTR( arg ) )
{
send_to_char( "Syntax: editnews addtype <name>\r\n"
" editnews addnews <type> <subject>\r\n"
" editnews removetype <number>\r\n"
" editnews removenews <type> <number>\r\n"
" editnews edittype <field> <value>\r\n"
" editnews editnews <type> <number> <new subject [optional]>\r\n"
" Fields being one of the following:\r\n"
"name header cmd_name lock org_name org_type\r\n"
"post_level view_level owner addposter remposter\r\n"
"html_max_view html_news_path html_txt_filename\r\n", ch );
return;
}
if( !str_cmp( arg, "addtype" ) )
{
NEWS_TYPE *type = NULL;
int i;
if( NULLSTR( argument ) )
{
send_to_char( "Syntax: editnews addtype <name>\r\n", ch );
return;
}
if( top_news_type >= NEWS_MAX_TYPES )
{
send_to_char( "There are too many news types.\r\n", ch );
return;
}
CREATE( type, NEWS_TYPE, 1 );
type->name = STRALLOC( argument );
type->cmd_name = STRALLOC( argument );
type->owner = STRALLOC( "" );
type->org_name = STRALLOC( "" );
for( i = 0; i < MAX_POSTERS; i++ )
type->posters[i] = NULL;
type->html_news_path = STRALLOC( "" );
type->html_txt_fname = STRALLOC( "" );
type->vnum = top_news_type++;
type->html_max_view = -1;
news_command_table[type->vnum] = STRALLOC( type->cmd_name );
LINK( type, first_news_type, last_news_type, next, prev );
send_to_char( "Done.\r\n", ch );
return;
}
if( !str_cmp( arg, "removetype" ) )
{
NEWS_TYPE *type = NULL;
int i;
if( NULLSTR( argument ) )
{
send_to_char( "Syntax: editnews removetype <name>\r\n", ch );
return;
}
if( ( type = figure_type( argument ) ) == NULL )
{
send_to_char( "Invaild news-type.\r\n", ch );
return;
}
/*
* forgot about this... 00ps!
*/
if( !NULLSTR( type->owner ) && ( str_cmp( type->owner, ch->name ) && get_trust( ch ) < LEVEL_IMPLEMENTOR ) )
{
send_to_char( "You don't have ownership of this news-type.\r\n", ch );
return;
}
UNLINK( type, first_news_type, last_news_type, next, prev );
if( !NULLSTR( type->name ) )
STRFREE( type->name );
if( !NULLSTR( type->header ) )
STRFREE( type->header );
if( !NULLSTR( type->cmd_name ) )
STRFREE( type->cmd_name );
if( !NULLSTR( type->org_name ) )
STRFREE( type->org_name );
if( !NULLSTR( type->owner ) )
STRFREE( type->owner );
if( !NULLSTR( type->html_news_path ) )
STRFREE( type->html_news_path );
if( !NULLSTR( type->html_txt_fname ) )
STRFREE( type->html_txt_fname );
if( !NULLSTR( news_command_table[type->vnum] ) )
STRFREE( news_command_table[type->vnum] );
{
NEWS *news = NULL;
void *next;
for( news = type->first_news; news; news = next )
{
next = news->next;
UNLINK( news, type->first_news, type->last_news, next, prev );
if( news->name )
STRFREE( news->name );
if( news->title )
STRFREE( news->title );
if( news->date )
STRFREE( news->date );
if( news->post )
STRFREE( news->post );
DISPOSE( news );
}
}
for( i = 0; i < MAX_POSTERS; i++ )
STRFREE( type->posters[i] );
DISPOSE( type );
top_news_type--;
renumber_news( );
save_news( );
send_to_char( "Done.\r\n", ch );
return;
}
if( !str_cmp( arg, "edittype" ) )
{
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
NEWS_TYPE *type = NULL;
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if( NULLSTR( arg2 ) || NULLSTR( arg3 ) )
{
send_to_char( "Syntax: editnews edittype <type> <field> <value>\r\n", ch );
send_to_char( "Fields being one of the following:\r\n"
"name header cmd_name lock org_name org_type\r\n"
"post_level view_level owner addposter remposter\r\n"
"html_max_view html_news_path html_txt_filename\r\n", ch );
return;
}
if( ( type = figure_type( arg2 ) ) == NULL )
{
send_to_char( "Invaild news-type.\r\n", ch );
return;
}
if( !NULLSTR( type->owner ) && ( str_cmp( type->owner, ch->name ) && get_trust( ch ) < LEVEL_IMPLEMENTOR ) )
{
send_to_char( "You don't have ownership of this news-type.\r\n", ch );
return;
}
if( !str_cmp( arg3, "cmd_name" ) )
{
type->cmd_name = STRALLOC( argument );
news_command_table[type->vnum] = STRALLOC( type->cmd_name );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
else if( !str_cmp( arg3, "name" ) )
{
type->name = STRALLOC( argument );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
else if( !str_cmp( arg3, "header" ) )
{
sprintf( local_buf, "%s\r\n", argument );
type->header = STRALLOC( local_buf );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
else if( !str_cmp( arg3, "owner" ) )
{
if( NULLSTR( argument ) )
{
send_to_char( "Syntax: editnews edittype <type> owner <clear/name>\r\n", ch );
return;
}
if( !str_cmp( argument, "none" ) || !str_cmp( argument, "clear" ) )
type->owner = STRALLOC( "" );
else
type->owner = STRALLOC( argument );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
else if( !str_cmp( arg3, "post_level" ) )
{
if( !str_cmp( argument, "clear" ) || !str_cmp( argument, "none" ) )
type->post_level = -1;
else
{
if( type->post_level > get_trust( ch ) )
{
send_to_char( "You cannot make an post-level higher than your own.\r\n", ch );
return;
}
if( type->post_level > MAX_LEVEL )
{
pager_printf_color( ch, "The post-level must be between 0 - %d.", MAX_LEVEL );
return;
}
type->post_level = atoi( argument );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
}
else if( !str_cmp( arg3, "view_level" ) )
{
if( !str_cmp( argument, "clear" ) || !str_cmp( argument, "none" ) )
type->view_level = -1;
else
{
if( type->view_level > get_trust( ch ) )
{
send_to_char( "You cannot make an view-level higher than your own.\r\n", ch );
return;
}
if( type->view_level > MAX_LEVEL )
{
pager_printf_color( ch, "The view-level must be between 0 - %d.", MAX_LEVEL );
return;
}
type->view_level = atoi( argument );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
}
else if( !str_cmp( arg3, "remposter" ) )
{
int i;
if( !type->locked )
{
send_to_char( "This news-type isn't locked.\r\n", ch );
send_to_char( "Use 'editnews <type> lock' to toggle lock mode.\r\n", ch );
return;
}
for( i = 0; i < MAX_POSTERS; i++ )
if( !str_cmp( type->posters[i], argument ) )
{
STRFREE( type->posters[i] );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
send_to_char( "No such poster.\r\n", ch );
return;
}
else if( !str_cmp( arg3, "addposter" ) )
{
int i;
if( !type->locked )
{
send_to_char( "This news-type isn't locked.\r\n", ch );
send_to_char( "Use 'editnews <type> lock' to toggle lock mode.\r\n", ch );
return;
}
for( i = 0; i < MAX_POSTERS; i++ )
if( type->posters[i] == '\0' )
{
type->posters[i] = STRALLOC( argument );
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
send_to_char( "Poster slots are full.\r\n", ch );
return;
}
else if( !str_cmp( arg3, "lock" ) )
{
type->locked = !type->locked;
if( !type->locked )
{
int i;
for( i = 0; type->posters[i] != '\0'; i++ )
STRFREE( type->posters[i] );
}
send_to_char( "Done.\r\n", ch );
save_news( );
return;
}
else if( !str_cmp( arg3, "org_type" ) )
{
if( NULLSTR( argument ) )
{
send_to_char( "Organization types are:\r\n" "clan guild order\r\n", ch );
return;
}
if( !str_cmp( argument, "clan" ) )
{
type->org_type = CLAN_PLAIN;
send_to_char( "Done.\r\n", ch );
}
else if( !str_cmp( argument, "guild" ) )
{
type->org_type = CLAN_GUILD;
send_to_char( "Done.\r\n", ch );
}
else if( !str_cmp( argument, "order" ) )
{
type->org_type = CLAN_ORDER;
send_to_char( "Done.\r\n", ch );
}
else if( !str_cmp( argument, "council" ) )
{
type->org_type = CLAN_COUNCIL;
send_to_char( "Done.\r\n", ch );
}
save_news( );
return;
}
else if( !str_cmp( arg3, "org_name" ) )
{
if( type->org_type == -1 )
{
send_to_char( "You must first sent an organization type.\r\n", ch );
return;
}
if( NULLSTR( argument ) || !str_cmp( argument, "clear" ) || !str_cmp( argument, "none" ) )
type->org_name[0] = '\0';
else
type->org_name = STRALLOC( argument );
send_to_char( "Done.\r\n", ch );
return;
}
else
{
send_to_char( "Syntax: editnews edittype <type> <field> <value>\r\n", ch );
send_to_char( "Fields being one of the following:\r\n"
"name header cmd_name lock org_name org_type\r\n"
"post_level view_level owner addposter remposter\r\n", ch );
return;
}
}
if( !str_cmp( arg, "addnews" ) )
{
char arg2[MAX_INPUT_LENGTH];
NEWS_TYPE *type = NULL;
NEWS *news = NULL;
argument = one_argument( argument, arg2 );
if( NULLSTR( arg2 ) || NULLSTR( argument ) )
{
send_to_char( "Syntax: editnews addnews <type> <subject>\r\n", ch );
return;
}
if( ( type = figure_type( arg2 ) ) == NULL )
{
send_to_char( "Invaild news-type. Use 'newstypes' to get a vaild listing.\r\n", ch );
return;
}
if( !can_post_news( ch, type ) )
{
send_to_char( "You cannot add-news to this news-type.\r\n", ch );
return;
}
CREATE( news, NEWS, 1 );
news->title = STRALLOC( argument );
news->name = STRALLOC( ch->name );
news->date = STRALLOC( stamp_time( ) );
news->post = STRALLOC( "" );
/*
* pop character into a writing buffer
*/
if( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_NEWS_POST;
news->temp = type;
ch->dest_buf = news;
start_editing( ch, news->post );
return;
}
if( !str_cmp( arg, "editnews" ) )
{
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
NEWS *news = NULL;
NEWS_TYPE *type = NULL;
argument = one_argument( argument, arg2 );
argument = one_argument( argument, arg3 );
if( NULLSTR( arg2 ) )
{
send_to_char( "Syntax: editnews editnews <type> <number> <new subject [optional]>\r\n", ch );
return;
}
/*
* changed for new -newstype- indexing - 5/5/02
*/
if( ( type = figure_type( arg2 ) ) == NULL )
{
send_to_char( "Invaild news-type. Use 'newstypes' to get a vaild listing.\r\n", ch );
return;
}
if( ( news = grab_news( type, arg3 ) ) == NULL )
{
pager_printf_color( ch, "That's not a vaild news number.\r\nUse '%s' to view the vaild numbers.\r\n",
type->cmd_name );
return;
}
/*
* a changed title
*/
if( !NULLSTR( argument ) )
news->title = STRALLOC( argument );
/*
* new date news was edited
*/
news->date = STRALLOC( stamp_time( ) );
/*
* pop character into a writing buffer
*/
if( ch->substate == SUB_REPEATCMD )
ch->tempnum = SUB_REPEATCMD;
else
ch->tempnum = SUB_NONE;
ch->substate = SUB_NEWS_EDIT;
ch->dest_buf = news;
start_editing( ch, news->post );
return;
}
if( !str_cmp( arg, "removenews" ) )
{
char arg2[MAX_INPUT_LENGTH];
NEWS *news = NULL;
NEWS_TYPE *type = NULL;
argument = one_argument( argument, arg2 );
if( NULLSTR( argument ) || NULLSTR( arg2 ) )
{
send_to_char( "Syntax: editnews remove <number>\r\n", ch );
return;
}
/*
* changed for new -newstype- indexing - 5/5/02
*/
if( ( type = figure_type( arg2 ) ) == NULL )
{
send_to_char( "Invaild news-type. Use 'newstypes' to get a vaild listing.\r\n", ch );
return;
}
if( ( news = grab_news( type, argument ) ) == NULL )
{
send_to_char( "Type 'news' to gain a list of the news numbers.\r\n", ch );
return;
}
UNLINK( news, type->first_news, type->last_news, next, prev );
if( !NULLSTR( news->name ) )
STRFREE( news->name );
if( !NULLSTR( news->title ) )
STRFREE( news->title );
if( !NULLSTR( news->date ) )
STRFREE( news->date );
if( !NULLSTR( news->post ) )
STRFREE( news->post );
DISPOSE( news );
renumber_news( );
save_news( );
send_to_char( "Done.\r\n", ch );
return;
}
}
/* figure the type of a newstype by the vnum
* or by the cmd_name off the news_cmd_table -Nopey */
NEWS_TYPE *figure_type( char *str )
{
if( is_number( str ) )
{
NEWS_TYPE *type = NULL;
int number = atoi( str );
/*
* poll the list for the vnum
*/
for( type = first_news_type; type; type = type->next )
if( type->vnum == number )
return type;
}
else /* a cmd name */
{
NEWS_TYPE *type = NULL;
int i;
/*
* poll the cmd_name array for word
*/
for( i = 0; i < top_news_type; i++ )
if( !str_cmp( str, news_command_table[i] ) )
{
for( type = first_news_type; type; type = type->next )
if( type->vnum == i )
return type;
}
}
return NULL;
}
/* Snatch news up from the linked list */
NEWS *grab_news( NEWS_TYPE * type, char *str )
{
NEWS *news = NULL;
for( news = type->first_news; news; news = news->next )
{
if( news->number == atoi( str ) )
return news;
}
return NULL;
}
/* display a full news to the character */
/* updated for the new display type 5/1/02 */
void display_news( CHAR_DATA * ch, NEWS * news, NEWS_TYPE * type )
{
send_to_pager_color( type->header, ch );
send_to_pager_color( NEWS_HEADER, ch );
pager_printf_color( ch, "&G&Y[&W%2d&Y] &W%-8s &Y@&W%-11s &Y%s&g\r\n", news->number, news->name, news->date,
news->title );
send_to_pager_color( news->post, ch );
return;
}
/* renumber the news */
/* changed for new indexing - 5/5/02 */
void renumber_news( void )
{
NEWS_TYPE *type = NULL;
NEWS *news = NULL;
int i, j;
for( i = 0; i < top_news_type; i++ )
if( news_command_table[i] )
STRFREE( news_command_table[i] );
top_news_type = 0;
for( type = first_news_type; type; type = type->next )
{
type->vnum = top_news_type++;
news_command_table[type->vnum] = STRALLOC( type->cmd_name );
for( j = 0, news = type->first_news; news; news = news->next )
{
j++;
news->number = j;
news->type = type->vnum;
}
}
return;
}
/* save the linked list */
/* changed for new indexing - 5/5/02 */
void save_news( void )
{
NEWS *news = NULL;
NEWS_TYPE *type = NULL;
FILE *fp = NULL;
char filename[256];
int i;
sprintf( filename, "%s%s", SYSTEM_DIR, NEWS_FILE );
if( ( fp = fopen( filename, "w" ) ) == NULL )
{
perror( "save_news(): cannot open file" );
return;
}
fprintf( fp, "#VERSION %s~\n", NEWS_VERSION );
for( type = first_news_type; type; type = type->next )
{
fprintf( fp, "#NEWSTYPE\n" );
fprintf( fp, "Name %s~\n", type->name );
fprintf( fp, "Cmd_Name %s~\n", type->cmd_name );
fprintf( fp, "Header %s~\n", type->header );
if( !NULLSTR( type->org_name ) )
fprintf( fp, "Org_Name %s~\n", type->org_name );
if( !NULLSTR( type->owner ) )
fprintf( fp, "Owner %s~\n", type->owner );
/* if(!NULLSTR(type->html_news_path))
fprintf(fp, "HtmlPath %s~\n", type->html_news_path);
if(!NULLSTR(type->html_txt_fname))
fprintf(fp, "HtmlFname %s~\n", type->html_txt_fname);
fprintf(fp, "HtmlMaxView %d\n", type->html_max_view); */
fprintf( fp, "Org_Type %d\n", type->org_type );
fprintf( fp, "Locked %d\n", type->locked );
fprintf( fp, "Vnum %d\n", type->vnum );
fprintf( fp, "Post_Level %d\n", type->post_level );
fprintf( fp, "View_Level %d\n", type->view_level );
for( i = 0; i < MAX_POSTERS; i++ )
if( !NULLSTR( type->posters[i] ) )
fprintf( fp, "Poster %s~\n", type->posters[i] );
fprintf( fp, "End\n" );
for( news = type->first_news; news; news = news->next )
{
fprintf( fp, "#NEWS\n" );
fprintf( fp, "Title %s~\n", news->title );
fprintf( fp, "Name %s~\n", news->name );
fprintf( fp, "Date %s~\n", news->date );
fprintf( fp, "Type %d\n", news->type );
fprintf( fp, "POST %s~\n", news->post );
fprintf( fp, "End\n" );
}
}
FCLOSE( fp );
/*
* html_news();
*/
return;
}
/* load the linked list from disk */
void load_news( void )
{
FILE *fp = NULL;
char filename[256];
sprintf( filename, "%s%s", SYSTEM_DIR, NEWS_FILE );
if( ( fp = fopen( filename, "r" ) ) == NULL )
{
perror( "load_news(): cannot open file" );
return;
}
for( ;; )
{
NEWS_TYPE *type = NULL;
NEWS *news = NULL;
char *word;
char letter = fread_letter( fp );
if( letter == '*' )
{
fread_to_eol( fp );
continue;
}
if( letter != '#' )
{
bug( "load_news(): # not found (%c)", letter );
break;
}
word = fread_word( fp );
/*
* added for new indexing - 5/5/02
*/
/*
* not used yet -Nopey
*/
if( !str_cmp( word, "VERSION" ) )
{
news_file_version = fread_string( fp );
continue;
}
else if( !str_cmp( word, "NEWSTYPE" ) )
{
CREATE( type, NEWS_TYPE, 1 );
type->org_type = -1;
type->post_level = -1;
type->view_level = -1;
type->html_max_view = -1;
type->locked = 0;
fread_news_type( type, fp );
LINK( type, first_news_type, last_news_type, next, prev );
continue;
}
else if( !str_cmp( word, "NEWS" ) )
{
CREATE( news, NEWS, 1 );
news->type = -1;
fread_news( news, fp );
link_news_to_type( news );
continue;
}
else if( !str_cmp( word, "END" ) )
break;
else
{
bug( "load_news(): unknown section %s", word );
continue;
}
}
FCLOSE( fp );
renumber_news( );
return;
}
/* added for new indexing - 5/5/02 - Nopey */
/* adds the news to to the correct newstype */
void link_news_to_type( NEWS * news )
{
NEWS_TYPE *type = NULL;
sprintf( local_buf, "%d", news->type );
if( ( type = figure_type( local_buf ) ) == NULL )
{
bug( "link_news_to_type(): invaild news->type %d", news->type );
return;
}
LINK( news, type->first_news, type->last_news, next, prev );
return;
}
void fread_news( NEWS * news, FILE * fp )
{
char *word;
bool fMatch;
for( ;; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER( word[0] ) )
{
case '*':
fread_to_eol( fp );
break;
case 'D':
KEY( "Date", news->date, fread_string( fp ) );
break;
case 'E':
if( !str_cmp( word, "END" ) )
{
if( !news->name )
news->name = STRALLOC( "Unknown" );
if( !news->date )
{
news->date = STRALLOC( stamp_time( ) );
}
if( !news->title )
news->title = STRALLOC( "News Post" );
if( news->type <= -1 )
news->type = 0;
return;
}
break;
case 'N':
KEY( "Name", news->name, fread_string( fp ) );
break;
case 'P':
if( !str_cmp( word, "POST" ) )
{
fMatch = TRUE;
news->post = fread_string( fp );
break;
}
break;
case 'T':
KEY( "Title", news->title, fread_string( fp ) );
KEY( "Type", news->type, fread_number( fp ) );
break;
}
if( !fMatch )
bug( "fread_news(): no match: %s", word );
}
}
/* added for new index - 5/5/02 - Nopey */
void fread_news_type( NEWS_TYPE * type, FILE * fp )
{
char *word;
bool fMatch;
for( ;; )
{
word = feof( fp ) ? "End" : fread_word( fp );
fMatch = FALSE;
switch ( UPPER( word[0] ) )
{
case '*':
fread_to_eol( fp );
break;
case 'C':
KEY( "Cmd_Name", type->cmd_name, fread_string( fp ) );
break;
case 'E':
if( !str_cmp( word, "END" ) )
{
if( !NULLSTR( type->name ) )
type->name = STRALLOC( "Unknown" );
if( !NULLSTR( type->owner ) )
type->owner = STRALLOC( "" );
if( !NULLSTR( type->org_name ) )
type->org_name = STRALLOC( "" );
return;
}
break;
case 'H':
KEY( "Header", type->header, fread_string( fp ) );
KEY( "HtmlFname", type->html_txt_fname, fread_string( fp ) );
KEY( "HtmlMaxView", type->html_max_view, fread_number( fp ) );
KEY( "HtmlPath", type->html_news_path, fread_string( fp ) );
break;
case 'L':
KEY( "Locked", type->locked, fread_number( fp ) );
break;
case 'N':
KEY( "Name", type->name, fread_string( fp ) );
break;
case 'O':
KEY( "Org_Name", type->org_name, fread_string( fp ) );
KEY( "Org_Type", type->org_type, fread_number( fp ) );
KEY( "Owner", type->owner, fread_string( fp ) );
break;
case 'P':
if( !str_cmp( word, "Poster" ) )
{
int i;
for( i = 0; type->posters[i] != NULL; i++ )
type->posters[i] = fread_string( fp );
break;
}
KEY( "Post_Level", type->post_level, fread_number( fp ) );
break;
case 'V':
KEY( "View_Level", type->view_level, fread_number( fp ) );
KEY( "Vnum", type->vnum, fread_number( fp ) );
break;
}
if( !fMatch )
bug( "fread_news_type(): no match: %s", word );
}
}
/* stamp date in mm/dd/yy. return string */
char *stamp_time( void )
{
static char buf[128];
struct tm *ntime = localtime( ¤t_time );
sprintf( buf, "%d/%d/%2.2d", ntime->tm_mon + 1, ntime->tm_mday, ntime->tm_year + 1900 );
return buf;
}
/* write html for a specific news-type -Nopey */
void html_news( void )
{
NEWS_TYPE *type = NULL;
FILE *fp = NULL;
for( type = first_news_type; type; type = type->next )
if( !NULLSTR( type->html_news_path ) && !NULLSTR( type->html_txt_fname ) && type->html_max_view > 0 )
{
char filename[256];
sprintf( filename, "%s%s", NEWS_HTML_DIR, type->html_txt_fname );
if( ( fp = fopen( filename, "w" ) ) == NULL )
{
bug( "html_news(): cannot open %s for writing", filename );
return;
}
snarf_news( fp, type );
FCLOSE( fp );
}
return;
}
/*
* rip it apart! =\ -Nopey
*/
void snarf_news( FILE * fp, NEWS_TYPE * type )
{
NEWS *news = NULL;
int i = 0;
for( news = type->last_news; i < type->html_max_view; news = news->prev, i++ )
{
fprintf( fp, "<table align='center' width='399' border='1'><tr><td bgcolor='#990000'>\n" );
fprintf( fp, "<font face='verdana' color='#FFFFFF' size='2'>%s</font></tr></td>\n", news->title );
fprintf( fp, "<tr><td bgcolor='#000000'><font face='verdana' color='#990000' size='1'>\n" );
fprintf( fp, "<div align='center'>» %s posted on %s</font></div></td></tr>\n", news->name, news->date );
fprintf( fp, "<tr><td valign='top' bgcolor='#000000'><font size='2' color='#FFFFFF' face='verdana'>\n" );
fprintf( fp, "%s</font></td></tr></table>\n", news->post );
}
/*
* this must stay here -- line below
*/
fprintf( fp, "<table align='center'><tr><td bgcolor='#990000'><font size='2' color='#FFFFFF' face='verdana'>\n" );
fprintf( fp,
"Extended News is copyright 2001-2002 <a href='mailto:noplex@crimsonblade.org?subject=Extended News'>John 'Noplex' Bellone</a>; <a href='http://www.crimsonblade.org/snippets/' target='new'>download your copy here.</a></font></td></tr></table>\n" );
fprintf( fp,
"<div align='center'><font face='verdana' size='1' color='#FFFFFF'>Extended News v%s. Last updated: %s</font></div>\n",
NEWS_VERSION, ctime( ¤t_time ) );
return;
}
/* news command hook; interp.c -Nopey */
bool news_cmd_hook( CHAR_DATA * ch, char *cmd, char *argument )
{
int i;
for( i = 0; i < top_news_type; i++ )
if( !str_cmp( cmd, news_command_table[i] ) )
{
NEWS_TYPE *type = NULL;
sprintf( local_buf, "%d", i );
if( ( type = figure_type( local_buf ) ) == NULL )
{
bug( "news_cmd_hook(): cannot find type for cmd %s", cmd );
return FALSE;
}
display_news_type( ch, type, argument );
return TRUE;
}
return FALSE;
}
/*
* display the news entry from the command hook -Nopey
*/
void display_news_type( CHAR_DATA * ch, NEWS_TYPE * type, char *argument )
{
/*
* 5/8/02
*/
/*
* moved - 6/30/02
*/
if( !can_read_news( ch, type ) )
{
send_to_char( "Huh?\r\n", ch );
return;
}
/*
* required to stay here; do not remove you may change the
* * colors accordingly to suit your news-types if you wish
*/
if( !str_cmp( argument, "version" ) )
{
pager_printf_color( ch, "&G&YExtended News&W %s&Y. Written by &WNoplex&Y.&g\r\n", NEWS_VERSION );
return;
}
if( !type->first_news )
{
send_to_char( "There is currently no news for this news-type.\r\n", ch );
return;
}
if( NULLSTR( argument ) || !str_cmp( argument, "all" ) )
{
bool all_news = FALSE;
NEWS *news = NULL;
int x = type->last_news->number, y = NEWS_VIEW;
int skipper = ( x - y );
if( !str_cmp( argument, "all" ) )
all_news = TRUE;
send_to_pager_color( NEWS_TOP, ch );
if( type->header )
send_to_pager_color( type->header, ch );
send_to_pager_color( NEWS_HEADER, ch );
for( news = type->first_news; news; news = news->next )
{
if( !all_news )
{
if( skipper > -1 )
{
skipper--;
continue;
}
}
pager_printf_color( ch, "&G&Y[&W%2d&Y] &W%-8s &Y@&W%-11s &Y%s&g\r\n", news->number, news->name, news->date,
news->title );
}
if( !all_news )
pager_printf_color( ch,
"&YThere is currently &W%d&Y news items loaded.\r\nUse '&W%s all&Y' to view all of them.&g\r\n",
type->last_news->number, type->cmd_name );
pager_printf_color( ch, "\r\n&YTo read indiviual news posts type '&W%s <number>&Y'\r\n", type->cmd_name );
return;
}
{
NEWS *news = NULL;
if( ( news = grab_news( type, argument ) ) == NULL )
{
pager_printf_color( ch, "That's not a news post number.\r\nUse '%s' to view them.\r\n", type->cmd_name );
return;
}
display_news( ch, news, type );
return;
}
}
/* decide whether or not the character can read the news -Nopey */
/* most of these features were implemented about ideas spoken
* with Blodkai; or ideas and implemenations that RoD has used with
* this snippet */
bool can_read_news( CHAR_DATA * ch, NEWS_TYPE * type )
{
if( type->org_type > -1 && !NULLSTR( type->org_name ) )
switch ( type->org_type )
{
case CLAN_PLAIN:
if( str_cmp( type->org_name, ch->pcdata->clan_name ) )
return FALSE;
break;
case CLAN_GUILD:
if( str_cmp( type->org_name, class_table[ch->class]->who_name ) )
return FALSE;
break;
case CLAN_ORDER:
if( str_cmp( type->org_name, ch->pcdata->clan_name ) )
return FALSE;
break;
/*
* not sure if this is stock; might have to add it in mud.h
*/
case CLAN_COUNCIL:
if( str_cmp( type->org_name, ch->pcdata->council_name ) )
return FALSE;
break;
}
/*
* minimum view level?
*/
if( type->view_level > get_trust( ch ) )
return FALSE;
return TRUE;
}
/* various checks against not posting news -Nopey */
bool can_post_news( CHAR_DATA * ch, NEWS_TYPE * type )
{
int i;
/*
* posting level; minimum
*/
if( type->view_level > get_trust( ch ) )
return FALSE;
/*
* locked news-types
*/
if( type->locked && ( !NULLSTR( type->owner ) && str_cmp( ch->name, type->owner ) ) )
{
/*
* fixed - 9/13/02
*/
for( i = 0; i < MAX_POSTERS; i++ )
if( !str_cmp( type->posters[i], ch->name ) )
return TRUE;
}
else
return TRUE;
return FALSE;
}