diff options
Diffstat (limited to 'help.c')
| -rw-r--r-- | help.c | 217 | 
1 files changed, 217 insertions, 0 deletions
| @@ -0,0 +1,217 @@ +  /********************************************************************\ +  * BitlBee -- An IRC to other IM-networks gateway                     * +  *                                                                    * +  * Copyright 2002-2010 Wilmer van der Gaast and others                * +  \********************************************************************/ + +/* Help file control                                                    */ + +/* +  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. + +  This program is distributed in the hope that it will be useful, +  but WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +  GNU General Public License for more details. + +  You should have received a copy of the GNU General Public License with +  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; +  if not, write to the Free Software Foundation, Inc., 59 Temple Place, +  Suite 330, Boston, MA  02111-1307  USA +*/ + +#define BITLBEE_CORE +#include "bitlbee.h" +#include "help.h" +#undef read  +#undef write + +#define BUFSIZE 1100 + +help_t *help_init( help_t **help, const char *helpfile ) +{ +	int i, buflen = 0; +	help_t *h; +	char *s, *t; +	time_t mtime; +	struct stat stat[1]; +	 +	*help = h = g_new0 ( help_t, 1 ); +	 +	h->fd = open( helpfile, O_RDONLY +#ifdef _WIN32 +				  | O_BINARY +#endif +				  ); +	 +	if( h->fd == -1 ) +	{ +		g_free( h ); +		return( *help = NULL ); +	} +	 +	if( fstat( h->fd, stat ) != 0 ) +	{ +		g_free( h ); +		return( *help = NULL ); +	} +	mtime = stat->st_mtime; +	 +	s = g_new (char, BUFSIZE + 1 ); +	s[BUFSIZE] = 0; +	 +	while( ( ( i = read( h->fd, s + buflen, BUFSIZE - buflen ) ) > 0 ) || +	       ( i == 0 && strstr( s, "\n%\n" ) ) ) +	{ +		buflen += i; +		memset( s + buflen, 0, BUFSIZE - buflen ); +		if( !( t = strstr( s, "\n%\n" ) ) || s[0] != '?' ) +		{ +			/* FIXME: Clean up */ +			help_free( help ); +			g_free( s ); +			return NULL; +		} +		i = strchr( s, '\n' ) - s; +		 +		if( h->title ) +		{ +			h = h->next = g_new0( help_t, 1 ); +		} +		h->title = g_new ( char, i ); +		 +		strncpy( h->title, s + 1, i - 1 ); +		h->title[i-1] = 0; +		h->fd = (*help)->fd; +		h->offset.file_offset = lseek( h->fd, 0, SEEK_CUR ) - buflen + i + 1; +		h->length = t - s - i - 1; +		h->mtime = mtime; +		 +		buflen -= ( t + 3 - s ); +		t = g_strdup( t + 3 ); +		g_free( s ); +		s = g_renew( char, t, BUFSIZE + 1 ); +		s[BUFSIZE] = 0; +	} +	 +	g_free( s ); +	 +	return( *help ); +} + +void help_free( help_t **help ) +{ +	help_t *h, *oh; +	int last_fd = -1; /* Weak de-dupe */ +	 +	if( help == NULL || *help == NULL ) +		return; +	 +	h = *help; +	while( h ) +	{ +		if( h->fd != last_fd ) +		{ +			close( h->fd ); +			last_fd = h->fd; +		} +		g_free( h->title ); +		h = (oh=h)->next; +		g_free( oh ); +	} +	 +	*help = NULL; +} + +char *help_get( help_t **help, char *title ) +{ +	time_t mtime; +	struct stat stat[1]; +	help_t *h; + +	for( h = *help; h; h = h->next ) +	{ +		if( h->title != NULL && g_strcasecmp( h->title, title ) == 0 ) +			break; +	} +	if( h && h->length > 0 ) +	{ +		char *s = g_new( char, h->length + 1 ); +		 +		s[h->length] = 0; +		if( h->fd >= 0 ) +		{ +			if( fstat( h->fd, stat ) != 0 ) +			{ +				g_free( s ); +				return NULL; +			} +			mtime = stat->st_mtime; +		 +			if( mtime > h->mtime ) +			{ +				g_free( s ); +				return NULL; +			} +			 +			if( lseek( h->fd, h->offset.file_offset, SEEK_SET ) == -1 || +			    read( h->fd, s, h->length ) != h->length ) +				return NULL; +		} +		else +		{ +			strncpy( s, h->offset.mem_offset, h->length ); +		} +		return s; +	} +	 +	return NULL; +} + +int help_add_mem( help_t **help, const char *title, const char *content ) +{ +	help_t *h, *l = NULL; +	 +	for( h = *help; h; h = h->next ) +	{ +		if( g_strcasecmp( h->title, title ) == 0 ) +			return 0; +		 +		l = h; +	} +	 +	if( l ) +		h = l->next = g_new0( struct help, 1 ); +	else +		*help = h = g_new0( struct help, 1 ); +	h->fd = -1; +	h->title = g_strdup( title ); +	h->length = strlen( content ); +	h->offset.mem_offset = g_strdup( content ); +	 +	return 1; +} + +char *help_get_whatsnew( help_t **help, int old ) +{ +	GString *ret = NULL; +	help_t *h; +	int v; +	 +	for( h = *help; h; h = h->next ) +		if( h->title != NULL && strncmp( h->title, "whatsnew", 8 ) == 0 && +		    sscanf( h->title + 8, "%x", &v ) == 1 && v > old ) +		{ +			char *s = help_get( &h, h->title ); +			if( ret == NULL ) +				ret = g_string_new( s ); +			else +				g_string_append_printf( ret, "\n\n%s", s ); +			g_free( s ); +		} +	 +	return ret ? g_string_free( ret, FALSE ) : NULL; +} | 
