#!/usr/bin/perl

###############################################################################
# Greymatter 1.7.3                           
# Copyright (c)2000-2007, The Greymatter team 
# http://greymatterforum.proboards82.com/     
# By possessing this software, you agree not to hold the author responsible for 
# any problems that may arise from your installation or usage of Greymatter 
# itself, or from any content generated by yourself or others through the use of 
# this program.  You <I>may</I> freely modify and redistribute this program, so 
# long as every copyright notice (including in this manual and in the Greymatter 
# code) remains fully intact.  Finally, you may <I>not</I> sell or in any way 
# make a financial profit from this program, either in original or modified form.
# Your possession of this software signifies that you agree to these terms; 
# please delete your copy of this software if you don't agree to these terms.
# Original Creators Noah Grey
###############################################################################

## Gm Storage
# This package groups functions that deal with miscelaneous and various functionality.
# Not all functions have to be exported, but some very very very common ones.
# 
# CONVENTIONS
# 1. Return a string rather than printing, this is just more elegant.  Leave prints
#   to the calling subroutine
# 2. Private subroutines should start with the '_' character.  By private I mean
#   it will never be called outside of this package.
# 3. If you have more than 1 or 2 parameters, especially if they are not required,
#   use named parameters such as in createRadioButton.  By putting stuff in a 
#   hash we gain the flexibility to add more optional parameters without having
#   to pass in '' placeholders or modify existing code.
# 6. Use ' and " where appropriate.  If you don't have any variables or newlines
# then use ', its quicker and cleaner.  
# 7. Don't put all text on one huge long line.  It messes with some programs
# that don't do line wraps. 

# use strict;
# use warnings;
# TODO: use taint mode!!!

eval {
	($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1");
	($0 =~ m,(.*)\\[^\\]+,) && unshift (@INC, "$1");
};

use lib 'libs';

use CGI::Carp qw(fatalsToBrowser);
use Gm_Constants;

require "gm-library.cgi";

# ----------------------------------------
# gathering the input & checking for login
# ----------------------------------------


$logindeletednotice = "";

%IN = %{Gm_Web::getWebParams( errHandler=>\&Gm_Web::displayAdminErrorExit )};

&gm_readconfig; # TODO COORDINATE SO ONLY DONE ONCE PER CALL
## TODO, get rid of and use Gm_Storage::getConfigs, have to get rid of uses here
#&gm_bancheck; #### REDUNDANT, done immediatly by gm_validate

## Generisize to an html safe method, should this be after validate?? or is it XSS protection, should be in 
## logic that actually logs username/pw
$IN{'authorname'} =~ s/</\&lt\;/g;
$IN{'authorname'} =~ s/>/\&gt\;/g;
$IN{'authorpassword'} =~ s/</\&lt\;/g;
$IN{'authorpassword'} =~ s/>/\&gt\;/g;


#my %AUTHOR = %{ &gm_validate };  ## redo to auth, returning hash for global author variable
my %AUTHOR = %{ Gm_Security::auth( webparams=>\%IN,
	errHandler=>\&Gm_Web::displayAdminErrorExit ) };
#warn join( ', ', map { $_="$_=$AUTHOR{$_}" } keys( %AUTHOR ) );
## TEMPORARY until refactor out depenance on YES, NO, etc.
# 	if ($AUTHOR{'postnew'} eq Gm_Constants::Y ) { $gmentryaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'editentries'} eq Gm_Constants::Y ) { $gmentryeditaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'editentries'} eq 'O') { $gmentryeditaccess = 'mineonly'; }
# 	if ($AUTHOR{'editconfigs'} eq Gm_Constants::Y ) { $gmconfigurationaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'edittemplates'} eq Gm_Constants::Y ) { $gmtemplateaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'edittemplates'} eq 'O') { $gmtemplateaccess = 'hfsonly'; }
# 	if ($AUTHOR{'editauthors'} eq Gm_Constants::Y ) { $gmauthoraccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'rebuild'} eq Gm_Constants::Y ) { $gmrebuildaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'viewcplog'} eq Gm_Constants::Y ) { $gmcplogaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'bookmarklets'} eq Gm_Constants::Y ) { $gmbookmarkletaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'upload'} eq Gm_Constants::Y ) { $gmuploadaccess = Gm_Constants::YES; }
# 	if ($AUTHOR{'viewadmin'} eq Gm_Constants::Y ) { $gmloginaccess = Gm_Constants::YES; }

### New pattern for handling these requests
handleRequest();



# if ($IN{'thomas'} eq Gm_Constants::EMPTY) { &gm_login; }
# if ($IN{'thomas'} eq 'Re-Login') { &gm_login; }

## CAN BE ERRASED ONCE KNOW THAT NO ONE USES gm_login
# if ($IN{'thomas'} eq 'login' || $IN{'login'}) {
# 	&gm_writetocplog("<B>$IN{'authorname'} logged in</B>");
# 	&gm_versioncheck;
# 	&gm_readcounter;
# 	$statusnote = '<span class="status_msg">Welcome, '.$IN{'authorname'}.'.</span><P>';
# 	if ($newentrynumber eq '0') {
# 			$cploglines = Gm_Storage::getCplog( errHandler=>\&Gm_Web::displayAdminErrorExit );
# 			
# 			$cplogtext = join (' ', @$cploglines);
# 			unless ($cplogtext =~ /successfully performed diagnostics/) {
# 			$statusnote = '<span class="status_msg">Welcome to Greymatter!  Please enter '.
# 				'Configuration first, check your paths,<BR>and run Diagnostics & Repair to '.
# 				'validate your installation.</span><P>';
# 		}
# 	}
# 	frontPage( $statusnote );
# }

print Gm_Web::createRequestHeader();  ## Wrong Place



if ($IN{'thomas'} eq "rebuildupdate") { &gm_rebuildupdate; }

if ($IN{'thomas'} eq "Update Now") { &gm_versionupgrading; }

if ($IN{'thomas'} eq "gmbmpost") { &gm_addentrypopup; }

if ($IN{'thomas'} eq "Return To Main Menu") { frontPage(); }  # This should be the fall through case

### Once we have redone everything else, this can be removed since we have redone the Frontpage
if ($IN{'thomas'} eq "Add A New Entry") { &gm_addentry; }
if ($IN{'thomas'} eq "Edit An Entry") { &gm_editentryselection; }
if ($IN{'thomas'} eq "Configuration") { &gm_configuration; }
if ($IN{'thomas'} eq "Edit Templates") { &gm_edittemplates; }
# if ($IN{'thomas'} eq "Edit Authors") { &gm_editauthors; }
# if ($IN{'thomas'} eq "Edit Banned IP List") { &gm_editbanlist; }
if ($IN{'thomas'} eq "Add Bookmarklets") { &gm_addbookmarklets; }
if ($IN{'thomas'} eq "Upload Files") { &gm_uploadfiles; }
if ($IN{'thomas'} eq "Rebuild Files") { &gm_rebuildfilesmenu; }
#if ($IN{'thomas'} eq "View Control Panel Log") { &gm_viewcplog; }

if ($IN{'thomas'} eq "Add This Entry") { &gm_savenewentry; }
if ($IN{'thomas'} eq "Preview Before Posting") { &gm_previewentry; }

if ($IN{'thomas'} eq "Re-Edit This Entry") {
	if ($IN{'gmbmspecial'} eq "popupblog") { &gm_addentrypopup; } else { &gm_addentry; }
}

if ($IN{'thomas'} eq "Change View") { &gm_editentryselection; }
if ($IN{'thomas'} eq "Search") { &gm_editentryselection; }

if ($IN{'thomas'} eq "Edit Selected Entry") { &gm_editthisentry; }
if ($IN{'thomas'} eq "Open/Close Selected Entry") { &gm_changeentryopenstatus; }
if ($IN{'thomas'} eq "Search And Replace Across All Entries") { &gm_editentrysearchandreplace; }

if ($IN{'thomas'} eq "Edit Selected Comment") { &gm_editselectedcomment; }
if ($IN{'thomas'} eq "Delete Selected Comment") { &gm_deleteselectedcomment; }
if ($IN{'thomas'} eq "Delete All Selected Comments") { &gm_DeleteAllSelectedComments; }
if ($IN{'thomas'} eq "Save Changes To This Entry") { &gm_saveentrychanges; }
if ($IN{'thomas'} eq "Select Another Entry") { &gm_editentryselection; }

if ($IN{'thomas'} eq "Return To Entry Selection") { &gm_editentryselection; }

if ($IN{'thomas'} eq "Perform Search And Replace") { &gm_performsearchandreplace; }

if ($IN{'thomas'} eq "Save Changes To This Comment") { &gm_savecommentchanges; }
if ($IN{'thomas'} eq "Return To Entry Editing") { &gm_editthisentry; }

# if ($IN{'thomas'} eq "Add New IP") { &gm_addbannedip; }
# if ($IN{'thomas'} eq "Delete Selected IP") { &gm_deletebannedip; }

if ($IN{'thomas'} eq "Diagnostics & Repair") { &gm_diagnosticscheck; }
if ($IN{'thomas'} eq "Save Configuration") { &gm_saveconfiguration; }

if ($IN{'thomas'} eq "Perform Diagnostics & Repair") { &gm_diagnosticsperform; }
if ($IN{'thomas'} eq "Return To Configuration") { &gm_configuration; }

if ($IN{'thomas'} eq "Edit Main Index-Related Templates") { &gm_editmainindextemplates; }
if ($IN{'thomas'} eq "Edit Archive-Related Templates") { &gm_editarchivetemplates; }
if ($IN{'thomas'} eq "Edit Entry Page-Related Templates") { &gm_editentrypagetemplates; }
if ($IN{'thomas'} eq "Edit Karma & Comments-Related Templates") { &gm_editkarmacommentstemplates; }
if ($IN{'thomas'} eq "Edit Header, Footer & Sidebar Templates") { &gm_editheaderfootertemplates; }
if ($IN{'thomas'} eq "Edit Miscellaneous Templates") { &gm_editmisctemplates; }

if ($IN{'thomas'} eq "Return To Templates Menu") { &gm_edittemplates; }
if ($IN{'thomas'} eq "Save Template Changes") { &gm_savetemplatechanges; }

#if ($IN{'thomas'} eq "Edit Selected Author") { &gm_editselectedauthor; }
#if ($IN{'thomas'} eq "Delete Selected Author") { &gm_deleteselectedauthor; }
#if ($IN{'thomas'} eq "Create New Author") { &gm_createnewauthor; }

#if ($IN{'thomas'} eq "Save Changes To This Author") { &gm_saveauthorchanges; }
#if ($IN{'thomas'} eq "Return To Author Panel") { &gm_editauthors; }

if ($IN{'thomas'} eq "Upload This File") { &gm_processupload; }

if ($IN{'thomas'} eq "Rebuild Last Entry Page Only") { &gm_rebuildlastentrypageonly; }
if ($IN{'thomas'} eq "Rebuild Main Index File") { &gm_rebuildmainindexfile; }
if ($IN{'thomas'} eq "Rebuild Main Entry Pages") { &gm_rebuildmainentrypages; }
if ($IN{'thomas'} eq "Rebuild Archive Master Index") { &gm_rebuildarchivemasterindex; }
if ($IN{'thomas'} eq "Rebuild Archive Log Indexes") { &gm_rebuildarchivelogindexes; }
if ($IN{'thomas'} eq "Rebuild Archive Entry Pages") { &gm_rebuildarchiveentrypages; }
if ($IN{'thomas'} eq "Rebuild All Entry Pages") { &gm_rebuildallentrypages; }
if ($IN{'thomas'} eq "Rebuild Connected Files") { &gm_rebuildconnectedfilescheck; }
if ($IN{'thomas'} eq "Rebuild Everything") { &gm_rebuildeverything; }

if ($IN{'thomas'} eq "Clear And Exit") {
	unlink ("$EntriesPath/gmrightclick-$IN{'usethisauthorname'}.reg");
	&gm_frontpage;
}

#if ($IN{'thomas'} eq "Reset The Control Panel Log") { &gm_resetcplog; }

if ($IN{'thomas'} eq "Include This Image In A New Entry") { &gm_addentry; }
if ($IN{'thomas'} eq "Include In Entry As A Popup Window") {
	$IN{'newentrymaintext'} = $IN{'newentrypopuptext'};
	&gm_addentry;
}
if ($IN{'thomas'} eq "Include This Link In A New Entry") { &gm_addentry; }

exit;

### This is the requst handler.  We are migrating away from looking at a 
# 'thomas' variable to determine what should be done.  Also, instead of a lot of
# if statements (which makes it hard to tell which one is executed if the variable
# is messed with) the new logic is that each area of the Admin Application will
# have a 'section' parameter and then each section will denote an 'action' such
# as 'edit', 'delete', etc.
sub handleRequest {

	if( $IN{'section'} eq 'cplog' || $IN{'cplog'} ){
		## The Control Panel Log
		$IN{'section'} = 'cplog';
		## Once navigation is by links, not buttons, can get rid of the or clause
		doCplog();
	
	} elsif( $IN{'section'} eq 'banip' || $IN{'banip'} ){
		## The Control Panel Log
		$IN{'section'} = 'banip';
		## Once navigation is by links, not buttons, can get rid of the or clause
		doBanip();
	
	} elsif( $IN{'section'} eq 'relogin' || $IN{'relogin'} ){
		## Re Authing
		$IN{'section'} = 'relogin';
		## Once navigation is by links, not buttons, can get rid of the or clause

		%AUTHOR = %{ Gm_Security::auth( webparams=>\%IN, reauth=>1,
			errHandler=>\&Gm_Web::displayAdminErrorExit ) };
	
	} elsif( $IN{'section'} eq 'login' || $IN{'login'} ){
		## just logged in
		$IN{'login'} = 'login';
		doLogin();
		
	} elsif( $IN{'section'} eq 'authors' || $IN{'authors'} ){
		## Editing Authors
		$IN{'section'} = 'authors';
		doAuthors();	

	} 

	#frontPage(); # eventually we are going to default to the menu or login,
	# but it would mess without fall through, where we do new stuff first and old if nothing else
}


## Front Page
# Will display the main page of Greymatter
# (opt) ARG1: Message to display to user, could be error or confirmation of action
sub frontPage {
	my $message = shift( @_ ) || Gm_Constants::EMPTY;
	
	#&gm_readconfig; ## already done above ...

## TODO: understand path code, move or refactor out of script
## TODO: no font tags in main menu and strip table of formatting, layout

## Checking if a bunch of paths are empty, why? - MOVED to doLogin
# 	if( ($cgilocalpath eq Gm_Constants::EMPTY) || 
# 		($cgiwebpath eq Gm_Constants::EMPTY) || ($LogPath eq Gm_Constants::EMPTY) || 
# 		($EntriesPath eq Gm_Constants::EMPTY) || ($LogWebPath eq Gm_Constants::EMPTY) || 
# 		($EntriesWebPath eq Gm_Constants::EMPTY) ){
# 
# 		if( ($cgilocalpath eq Gm_Constants::EMPTY) && ($LogPath ne Gm_Constants::EMPTY) ){ 
# 			$cgilocalpath = $LogPath; 
# 		}
# 		if( ($cgiwebpath eq Gm_Constants::EMPTY) && ($LogWebPath ne Gm_Constants::EMPTY) ){ 
# 			$cgiwebpath = $LogWebPath; 
# 		}
# 
# 		if( $cgilocalpath eq Gm_Constants::EMPTY ){
# 			if( $ENV{'SCRIPT_FILENAME'} ){ 
# 				$cgilocalpath = $ENV{'SCRIPT_FILENAME'}; 
# 			} elsif( $ENV{'PATH_TRANSLATED'} ){
# 				$cgilocalpath = $ENV{'PATH_TRANSLATED'};
# 				$cgilocalpath =~ s/\\/\//g; 
# 			}
# 			@cgilocalpathtemp = split(/\//, $cgilocalpath);
# 			pop(@cgilocalpathtemp);
# 			$cgilocalpath = join("\/", @cgilocalpathtemp);
# 
# 			$loglocalpath = $cgilocalpath;
# 			$loglocalpath =~ s/\/cgi-bin//g;
# 		}
# 
# 		@cgipath = split(/\//, $cgilocalpath);
# 		$cgiwebpathextension = pop(@cgipath);
# 
# 		@logpath = split(/\//, $loglocalpath);
# 		$logwebpathextension = pop(@logpath);
# 		
# 		if( $logwebpathextension eq "public_html" ){ 
# 			$logwebpathextensionnew = Gm_Constants::EMPTY; }
# 		 else { 
# 			 $logwebpathextensionnew = "/";
# 			 $logwebpathextensionnew .= $logwebpathextension;
# 		 }
# 	
# 		if( $cgiwebpath eq Gm_Constants::EMPTY ){ 
# 			$cgiwebpath = "http://$ENV{'HTTP_HOST'}/$cgiwebpathextension"; 
# 		}
# 	
# 		if( $LogPath eq Gm_Constants::EMPTY ){ 
# 			$LogPath = $loglocalpath; 
# 		}
# 		if( $EntriesPath eq Gm_Constants::EMPTY ){ 
# 			$EntriesPath = ("$loglocalpath" . "/archives"); 
# 		}
# 		if( $LogWebPath eq Gm_Constants::EMPTY ){ 
# 			$LogWebPath = "http://$ENV{'HTTP_HOST'}$logwebpathextensionnew"; 
# 		}
# 		if( $EntriesWebPath eq Gm_Constants::EMPTY ){ 
# 			$EntriesWebPath = "http://$ENV{'HTTP_HOST'}$logwebpathextensionnew/archives"; 
# 		}
# 	
# 		&gm_writeconfig;
# 
# 	}
##  END of path changes

#&gm_validate; ## already done, equiv to gm_auth

# 	if( $gmloginaccess ne Gm_Constants::YES ){
	## this is taken care of by the auth mechanism, but we are double checking anyway
	if( $AUTHOR{'viewadmin'} ne Gm_Constants::Y ){
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::LOGIN_NO_ACCESS, { AUTHOR=>$AUTHOR{'author'} } ));
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::LOGIN_ACCESS_DENY ).'</span><br />';
		#&gm_login; ## this will be auth( revalidate=>1, $message );, no, they don't have access, and they weren't prompted to give credentials?
		Gm_Web::displayAdminErrorExit( $message );
	}

# 	if( $statusnote eq Gm_Constants::EMPTY ){ 
# 		$statusnote = qq(<B><FONT COLOR="#000000">Main Menu</FONT></B><P>); 
# 	}
	my $page = "<span class=\"section_title\">".Gm_Core::text( Gm_Constants::FRONTPAGE_TITLE ).
		"</span><br /><p>$message</p><p class=\"text_left\">\n";

# 	if( ($IN{'authorname'} eq "Alice" ) && ($IN{'authorpassword'} eq "wonderland") ){
	if( ($AUTHOR{'author'} eq 'Alice' ) && ($AUTHOR{'password'} eq 'woCCASD0Wk0IA') ){
		$setnameandpwcookie = "<SCRIPT TYPE=\"text/javascript\" ".
			"LANGUAGE=\"JavaScript\">\n<!--//\n".
			"deleteCookie(\"gmcookiename\" );\n".
			"deleteCookie(\"$cookiename\" );\n//-->\n</SCRIPT>";
	} else {
		## TODO: FIX THIS, AUTHOR CREDENTIALS ARE THE PROVIDENCE OF GM_SECURITY
		# REMEMBER LOGIN SHOULD BE DONE BY GM_SECURITY
		$setnameandpwcookie = "<SCRIPT TYPE=\"text/javascript\" ".
			"LANGUAGE=\"JavaScript\">\n<!--//\nvar now = new Date();\n".
			"fixDate(now);\nnow.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);\n".
			"setCookie(\"gmcookiename\", \"$IN{'loginname'}\", now);\n".
			"setCookie(\"$cookiename\", \"$IN{'loginpw'}\", now);\n//-->\n</SCRIPT>";
	}
	
	if ($cookiesallowed eq Gm_Constants::NO || !$IN{'login'} ) {
		$setnameandpwcookie = Gm_Constants::EMPTY;
	}


	$page .= $setnameandpwcookie;
	$page .= '<form action="gm.cgi" method=post>'.
		Gm_Security::getFormAuth( author=>\%AUTHOR );
		
	my @actions = ();
	my $item = Gm_Constants::EMPTY;
	
	## Alice should not have 'Post New' by default
	if( $AUTHOR{'postnew'} eq Gm_Constants::Y ){	
		$item = '<input type=submit class="button" name="thomas" '.
			'value="'.Gm_Core::text( Gm_Constants::FRONTPAGE_ADDNEW ).'" style="background: #D0FFD0;" '.
			'><br />'.Gm_Core::text( Gm_Constants::FRONTPAGE_ADDNEW_DESC );
		push( @actions, $item );
	}
	
	#	my $visityoursitelink = Gm_Constants::EMPTY;	
	# THIS SHOULD BE LINK THAT LOOKS LIKE BUTTON, SEE MULTIEDIT
	## TODO this should be an action that can be pushed onto actions, 
	# but because of form, no can do for now
	unless( ! -e "$LogPath/$indexfilename"  ){
		&gm_readcounter;
		unless( $newentrynumber eq '0' ){
			$indexfilenamesmartcheck = "/$indexfilename";
			$indexfilenameprefix = substr($indexfilename, 0, 6);
			if( $indexfilenameprefix eq 'index.' ) { 
				$indexfilenamesmartcheck = "/"; 
			}
				
			$item = '<a href="'.$LogWebPath.$indexfilenamesmartcheck.'" target="NEW" '.
				'class="link_button" STYLE="background: #D0FFD0; padding: 3px 5em 3px 5em">'.
				Gm_Core::text( Gm_Constants::FRONTPAGE_VISIT ).'</a>'.
				'<br />'.Gm_Core::text( Gm_Constants::FRONTPAGE_VISIT_DESC );
			push( @actions, $item );
		}
	}

	if( $AUTHOR{'editconfigs'} eq Gm_Constants::Y ){	
		$item = '<input type=submit class="button" name="thomas" '.
			'value="'.Gm_Core::text( Gm_Constants::FRONTPAGE_CONFIG ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_CONFIG_DESC );
		push( @actions, $item );
	}

	## Alice should not have 'Post New' by default
	if( $AUTHOR{'editentries'} eq Gm_Constants::Y || $AUTHOR{'editentries'} eq 'O' ){	
		$item = '<input type=submit class="button" name="thomas" '.
			'value="'.Gm_Core::text( Gm_Constants::FRONTPAGE_EDIT ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_EDIT_DESC );
		push( @actions, $item );
	}
	
	if( $AUTHOR{'edittemplates'} eq Gm_Constants::Y || $AUTHOR{'edittemplates'} eq 'O' ){	
		$item = '<input type=submit class="button" name="thomas" '.
			'value="'.Gm_Core::text( Gm_Constants::FRONTPAGE_TEMPL ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_TEMPL_DESC );
		push( @actions, $item );
	}

	if( $AUTHOR{'editauthors'} eq Gm_Constants::Y ){	
		$item = '<input type=submit class="button" name="authors" '.
			'value="'.Gm_Core::text( Gm_Constants::FRONTPAGE_AUTHORS ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_AUTHORS_DESC );
		push( @actions, $item );
	}
	
	if( $AUTHOR{'rebuild'} eq Gm_Constants::Y ){	
		$item = '<input type=submit class="button" name="thomas" '.
			'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_REBUILD ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_REBUILD_DESC );
		push( @actions, $item );
	}

	if( $AUTHOR{'viewcplog'} eq Gm_Constants::Y ){	
		$item = '<INPUT TYPE=SUBMIT CLASS="button" NAME="cplog" '.
			'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_CPLOG ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_CPLOG_DESC );
		push( @actions, $item );
	}

	## Alice should not have 'Post New' by default
	if( $AUTHOR{'bookmarklets'} eq Gm_Constants::Y ){	
		$item = '<INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" '.
		'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_BMLETS ).'"><BR>'.
		Gm_Core::text( Gm_Constants::FRONTPAGE_BMLETS_DESC );
		push( @actions, $item );
	}
	
	if( $AUTHOR{'upload'} eq Gm_Constants::Y ){	
		$item = '<INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" '.
			'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_UPLOAD ).'"><br />'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_UPLOAD_DESC );
		push( @actions, $item );
	}
	
	if( $AUTHOR{'editconfigs'} eq Gm_Constants::Y ){	
		$item = '<INPUT TYPE=SUBMIT CLASS="button" NAME="banip" '.
			'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_BANNED ).'"><BR>'.
			Gm_Core::text( Gm_Constants::FRONTPAGE_BANNED_DESC );
		push( @actions, $item );
	}

	$item = '<INPUT TYPE=SUBMIT CLASS="button" NAME="relogin" '.
		'VALUE="'.Gm_Core::text( Gm_Constants::FRONTPAGE_RELOGIN ).'"><BR>'.
		Gm_Core::text( Gm_Constants::FRONTPAGE_RELOGIN_DESC ).'</FONT></FONT>';
	push( @actions, $item );
	
	$page .= '<table border="0" cellpadding="10" cellspacing="0" width="80%">';
	while( @actions ){
		my $actOne = shift( @actions );
		my $actTwo = shift( @actions );
		
		$page .= '<tr><td style="	font-size: smaller;	margin: 5px;" valign="top" width="50%">'.$actOne.
			'</td><td style="	font-size: smaller;	margin: 5px;" valign="top" width="50%">';
		if( $actTwo ){
			$page .= $actTwo;
		} else {
			$page .= '&nbsp;';
		}
		$page .= '</td></tr>';
	
	}
	$page .= '</FORM></table></p>';

	Gm_Web::displayAdminPageExit( $page );
	## NAVIGATION SHOULD BE DE-BUTTONED
	exit(0); ## will never get here, in theory
}

## LOGIN SECTION #################################################
## Handle all requests regarding logging in
sub doLogin {

	# TODO: SHOULD WE BE CHECKING PERMS IF AUTHOR CAN EVEN ACCESS ADMIN SCREEN?
	# ITS HANDLED IN MENU, BUT THAT SEEMS LAME?

#	&gm_writetocplog("<B>$IN{'authorname'} logged in</B>");
	Gm_Core::writeToCplog( '<span class="status_msg">'.
		Gm_Core::text( Gm_Constants::LOGIN_LOG, { AUTHOR=>$AUTHOR{'author'} } ).'</span>' );
	&gm_versioncheck;
#	&gm_readcounter;
	my $gmcounters = Gm_Storage::getCounters( errHandler=>\&Gm_Web::displayAdminErrorExit );


## Checking if a bunch of paths are empty and setting them up
	if( ($cgilocalpath eq Gm_Constants::EMPTY) || 
		($cgiwebpath eq Gm_Constants::EMPTY) || ($LogPath eq Gm_Constants::EMPTY) || 
		($EntriesPath eq Gm_Constants::EMPTY) || ($LogWebPath eq Gm_Constants::EMPTY) || 
		($EntriesWebPath eq Gm_Constants::EMPTY) || $emoticonspath eq Gm_Constants::EMPTY ){

		if( ($cgilocalpath eq Gm_Constants::EMPTY) && ($LogPath ne Gm_Constants::EMPTY) ){ 
			$cgilocalpath = $LogPath; 
		}
		if( ($cgiwebpath eq Gm_Constants::EMPTY) && ($LogWebPath ne Gm_Constants::EMPTY) ){ 
			$cgiwebpath = $LogWebPath; 
		}

		if( $cgilocalpath eq Gm_Constants::EMPTY ){
			if( $ENV{'SCRIPT_FILENAME'} ){ 
				$cgilocalpath = $ENV{'SCRIPT_FILENAME'}; 
			} elsif( $ENV{'PATH_TRANSLATED'} ){
				$cgilocalpath = $ENV{'PATH_TRANSLATED'};
				$cgilocalpath =~ s/\\/\//g; 
			}
		
			@cgilocalpathtemp = split(/\//, $cgilocalpath);
			pop(@cgilocalpathtemp);
			$cgilocalpath = join("\/", @cgilocalpathtemp);

			$loglocalpath = $cgilocalpath;
			$loglocalpath =~ s/\/cgi-bin//g;
		}

		@cgipath = split(/\//, $cgilocalpath);
		$cgiwebpathextension = pop(@cgipath);

		@logpath = split(/\//, $loglocalpath);
		$logwebpathextension = pop(@logpath);
		
		if( $logwebpathextension eq "public_html" ){ 
			$logwebpathextensionnew = Gm_Constants::EMPTY; 
		} else { 
			 $logwebpathextensionnew = '/';
			 $logwebpathextensionnew .= $logwebpathextension;
		 }
	
		if( $LogPath eq Gm_Constants::EMPTY ){ 
			$LogPath = $loglocalpath; 
		}
		if( $EntriesPath eq Gm_Constants::EMPTY ){ 
			$EntriesPath = ("$loglocalpath" . "/archives"); 
		}

		my $basewebpath = '/';
		my $basewebcgipath = '/cgi-bin/';
		if( $ENV{'HTTP_HOST'} && $ENV{'SCRIPT_URL'} ){
			$basewebpath = "http://$ENV{'HTTP_HOST'}$ENV{'SCRIPT_URL'}";
			my @bwp = split( '\/', $basewebpath );
			pop( @bwp ); # should be script
			$basewebcgipath = join( '/', @bwp );
			pop( @bwp ); # should be cgi-bin
			$basewebpath = join( '/', @bwp );
		} elsif( $ENV{'SCRIPT_URI'} ){
			$basewebpath = $ENV{'SCRIPT_URI'};
			my @bwp = split( '\/', $basewebpath );
			pop( @bwp ) if( scalar( @bwp ) > 1 ); # should be script
			$basewebcgipath = join( '/', @bwp );
			pop( @bwp ) if( scalar( @bwp ) > 1 ); # should be cgi-bin
			$basewebpath = join( '/', @bwp );
		} elsif( $ENV{'HTTP_HOST'} ){
			$basewebpath = "http://$ENV{'HTTP_HOST'}/$logwebpathextensionnew";
			$basewebcgipath = "http://$ENV{'HTTP_HOST'}/$cgiwebpathextension";		
		}
	
		if( $cgiwebpath eq Gm_Constants::EMPTY ){ 
			$cgiwebpath = $basewebcgipath; 
		}		
		
		if( $LogWebPath eq Gm_Constants::EMPTY ){ 
			$LogWebPath = $basewebpath; 
		}
		if( $EntriesWebPath eq Gm_Constants::EMPTY ){ 
			$EntriesWebPath = "$basewebpath/archives"; 
		}
		if( $emoticonspath eq Gm_Constants::EMPTY ){ 
			$emoticonspath = "$basewebpath/emotions"; 
		}
		
		&gm_writeconfig;

	}
##  END of path changes
	
	
	my $statusnote = '<span class="status_msg">'.
		Gm_Core::text( Gm_Constants::LOGIN_WELCOME, { AUTHOR=>$AUTHOR{'author'} } ).'</span><p>';
#	if ($newentrynumber eq '0') {
	if( $gmcounters->{'entrytotal'} < 1 ){
			my $cploglines = Gm_Storage::getCplog( errHandler=>\&Gm_Web::displayAdminErrorExit );
			
			my $cplogtext = join (' ', @$cploglines);
			unless ($cplogtext =~ /successfully performed diagnostics/) {
			$statusnote = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::LOGIN_FIRST ).'</span><p>';
		}
	}
	frontPage( $statusnote );
	
	exit(0);
}


## CPLOG SECTION #################################################
## Handle all requests from the control panel page
## and verify that author can access this section
sub doCplog {

	## Checking authorization of author, since cplog has no granularity, can check here
	### TODO: CALL AUTH WITH FLAG TO WORK ON CPLOG, OR CHECK AUTHOR PERMS
	## TODO: Move this to auth, auth should return users perms, or it should take a flag to 
	# indicate which perms to check with this being handed off to a generic permDenied func
	if( $AUTHOR{'viewcplog'} ne Gm_Constants::Y ){
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::CPLOG_NO_ACCESS, { AUTHOR=>$AUTHOR{'author'} } ));
		my $statusnote = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::CPLOG_ACCESS_DENY ).
			'</span><br />';
		frontPage( $statusnote );
	}


	my $status = Gm_Constants::EMPTY;
	
	if( $IN{'reset'} ){
		## clear - Should return message for frontpage, or to cplog?
		$status = resetCpLog();
		
	}

	## should this be else or should in fact be last command, taking a 'message' argument,
	# that could have been set by other calls to previous subroutines?
	viewCpLog( $status );


}


## View Cp Log
# Will display the control panel log
# (opt) ARG1: Message to display to user, could be error or confirmation of action
sub viewCpLog {
	my $message = shift( @_ ) || Gm_Constants::EMPTY;
	
	my $page = "<span class=\"section_title\">".Gm_Core::text( Gm_Constants::CPLOG_TITLE ).
		"</span><br /><p>$message</p><p class=\"text_left\">\n";
	
	my $gmlogfile = Gm_Storage::getCplog( errHandler=>\&Gm_Web::displayAdminErrorExit );
	
	my $base = '?section=cplog&'.Gm_Security::getUrlAuth( author=>\%AUTHOR );
	my ($page_nav, $short_logfile ) = Gm_Web::createPaging( data=>$gmlogfile,
		baseurl=>$base , webparams=>\%IN );
	
	$page .= join( "<br />\n", @{$short_logfile} );
	$page .= "<div class='pagenav'>$page_nav</div>\n";
	
	
	my ($gmdate) = Gm_Utils::getStdDate( $serveroffset );
	&gm_readcounter;  ## use storage call, which this does, but we should call right one...

	my $newalltimetotalkarmanumber = 0;
	my $newalltimetotalkarmavotes = 0;
	my $entriesonmainnumber = 0;
	my $karmavotesonaverage = 0;
	my $commentspostedonaverage = 0;	
	if ($newentrynumber ne '0') {
		$newalltimetotalkarmanumber = $newalltimepktotalnumber - $newalltimenktotalnumber;
		$newalltimetotalkarmavotes = $newalltimepktotalnumber + $newalltimenktotalnumber;
		$entriesonmainnumber = $newentrynumber - $newarchivenumber;
		$karmavotesonaverage = Gm_Utils::toFirstDec( ($newalltimetotalkarmavotes / $newentrynumber));
		$commentspostedonaverage = Gm_Utils::toFirstDec( ($newalltimecommentstotalnumber / $newentrynumber));
	
	}

	my $totalclosedentries = $newalltimeclosedentriesnumber;
	if( $newalltimeclosedentriesnumber < 1 ){
		$totalclosedentries = 0;
	}

	$page .= '<br /><div class="info_box"><span class="info_title">'.
		Gm_Core::text( Gm_Constants::CPLOG_INFO_TITLE, { DATE=>$gmdate } ).'</span>';

	$page .= '<p>'.Gm_Core::text( Gm_Constants::CPLOG_INFO1, { ENTRYNUMBER=>$newentrynumber,
		ENTRYOPEN=>$newalltimeopenentriesnumber, ENTRYCLOSED=>$totalclosedentries, 
		ENTRYARCHIVE=>$newarchivenumber, ENTRYCURRENT=>$entriesonmainnumber } ).'<BR>';

	$page .= Gm_Core::text( Gm_Constants::CPLOG_INFO2, { KARMAVOTES=>$newalltimetotalkarmavotes,
		KARMAAVERAGE=>$karmavotesonaverage, KARMAPOS=>$newalltimepktotalnumber, 
		KARMANEG=>$newalltimenktotalnumber, KARMATOTAL=>$newalltimetotalkarmanumber } ).'<BR>';

	$page .= Gm_Core::text( Gm_Constants::CPLOG_INFO3, { COMMENTTOTAL=>$newalltimecommentstotalnumber,
		COMMENTAVERAGE=>$commentspostedonaverage } ).'</p></div>';
		
	$page .= '<br /><form action="gm.cgi" method="post">'.
		'<input type="hidden" name="section" value="'.$IN{'section'}.'">'.
		Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<input type="submit" class="button" name="reset" style="background: #FFD0D0" '.
		'value="'.Gm_Core::text( Gm_Constants::CPLOG_RESET ).'"></form><p>';
	$page .= '<form action="gm.cgi" method="post">'.Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<input type=SUBMIT class="button" name="thomas" value="'.
		Gm_Core::text( Gm_Constants::RETURN_MAIN_MENU ).'" style="background: #C0C0C0"></form>';
	Gm_Web::displayAdminPageExit( $page );
	## NAVIGATION SHOULD BE DE-BUTTONED
	exit(0);
}

## Reset Cp Log
# Will reset the control panel log
# RETURNS: A message to display on the view page
sub resetCpLog {
	my $message = Gm_Constants::EMPTY;
	
	Gm_Storage::setCplog( log=>[], errHandler=>\&Gm_Web::displayAdminErrorExit );
	
	Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::CPLOG_CLEARED, { AUTHOR=>$AUTHOR{'author'} } ));
	
	$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::CPLOG_CLEAR_CONFIRM ).'</span><p>';
	
	return $message;
}


## Ban Ip SECTION #################################################
## Handle all requests from the Ban Iplist
## and verify that author can access this section
sub doBanip {

	## Access to Banip is global, no need for granularity
	### TODO: CALL AUTH WITH FLAG TO WORK ON Banip, OR CHECK AUTHOR PERMS
	## TODO: Move this to auth, auth should return users perms, or it should take a flag to 
	# indicate which perms to check with this being handed off to a generic permDenied func
	if( $AUTHOR{'editconfigs'} ne Gm_Constants::Y ){
#if ($gmconfigurationaccess ne Gm_Constants::YES) {
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::BANIP_NO_ACCESS, { AUTHOR=>$AUTHOR{'author'} } ));
		my $statusnote = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::BANIP_ACCESS_DENY ).
			'</span><br />';
		frontPage( $statusnote );
	}
	
	my $status = Gm_Constants::EMPTY;
# TODO, SHOULD THESE BE USING CONSTANTS?
	if( $IN{'delete'} ){
		## clear - Should return message for frontpage, or to cplog?
		$status = deleteBannedIp();
		
	} elsif( $IN{'add'} ){
		## clear - Should return message for frontpage, or to cplog?
		$status = addBannedIp();
		
	}

	## should this be else or should in fact be last command, taking a 'message' argument,
	# that could have been set by other calls to previous subroutines?
	viewBanList( $status );

}


## View Banned IP List
# View the list of banned IP addresses
# (opt) ARG1: Message to display to user, could be error or confirmation of action
sub viewBanList {
	my $message = shift( @_ ) || Gm_Constants::EMPTY;
	
	if( $message eq Gm_Constants::EMPTY ){ 
		$message = '<div class="info_text">'.Gm_Core::text( Gm_Constants::BANIP_INFO ).'</div>'; 
	}
	
	my $page = '<span class="section_title">'.Gm_Core::text( Gm_Constants::BANIP_TITLE ).
		"</span><br /><p>$message</p><p class=\"text_left\">\n";	
	$page .= '<FORM ACTION="gm.cgi" METHOD="post"> '.
		Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<table width="80%" class="info_table"><tr><th>'.Gm_Core::text( Gm_Constants::BANIP_IP ).
		'</th><th>'.Gm_Core::text( Gm_Constants::BANIP_HOST ).'</th><th>'.
		Gm_Core::text( Gm_Constants::NAME ).'</th><th width="20%">'.
		Gm_Core::text( Gm_Constants::ACTION ).'</td></tr>';

	my $gmbanlist = Gm_Storage::getBanlist( errHandler=>\&Gm_Web::displayAdminErrorExit );

	my @banlist_array = sort { $gmbanlist->{$a}{'ip'} cmp $gmbanlist->{$b}{'ip'} } keys(%$gmbanlist);

	my $base = '?section='.$IN{'section'}.'&'.Gm_Security::getUrlAuth( author=>\%AUTHOR );
	my ($page_nav, $short_banlist ) = Gm_Web::createPaging( data=>\@banlist_array,
		baseurl=>$base, webparams=>\%IN, pagesize=>(Gm_Constants::GM_PAGE_SIZE/5) );

	my $rowcolor = Gm_Web::altRowColor();
	foreach $gmbanlistline ( @{$short_banlist} ) {
		($gmbannedip, $gmbannediphost, $gmbannedperson) = 
			($gmbanlist->{$gmbanlistline}{'ip'}, $gmbanlist->{$gmbanlistline}{'host'}, 
			 $gmbanlist->{$gmbanlistline}{'label'} );
	
		$gmbannedperson =~ s/</\&lt;/g;
		$gmbannedperson =~ s/>/\&gt;/g;
		$gmbannedperson =~ s/"/\&quot;/g;
	
		$rowcolor = Gm_Web::altRowColor( $rowcolor );
		$page .= "<tr $rowcolor><td>$gmbannedip</td><td>$gmbannediphost</td><td>";
		if ($gmbannedperson ne Gm_Constants::EMPTY) { 
			$page .= " ($gmbannedperson)"; 
		}
		$page .= '&nbsp</td><td>'.
		'<a href="'.$ENV{SCRIPT_NAME}.'?section='.$IN{'section'}.'&delete=1&'.
		'editedbanlist='.$gmbannedip.
		'&'.Gm_Security::getUrlAuth( author=>\%AUTHOR ).
		'" class="link_button" STYLE="background: #FFD0D0">'.
		Gm_Core::text( Gm_Constants::DELETE ).'</a>'.
		'</td></tr>'."\n";
	}


	$page .= "</table><div class='pagenav'>$page_nav</div><br />\n";	
	## TODO: THESE ELEMENTS SHOULD BE REVALIDATED BEFORE DOING ANYTHING WITH, LIKE IN ADDBANIP
	$page .= '<div class="info_box"><span class="info_title">'.Gm_Core::text( Gm_Constants::BANIP_ADD_TITLE ).
		'</span><br /><table width="80%" class="form_table">'.
		'<tr><th><label for="banip">'.Gm_Core::text( Gm_Constants::BANIP_IP ).
		':</label></th><td><input type="text" value="'.$IN{'editednewbannedip'}.'"'.
		'class="inputfield" maxlength="15" name="editednewbannedip" size="15" id="banip"></td></tr>';
	$page .= '<tr><th><label for="banname">'.Gm_Core::text( Gm_Constants::BANIP_ADD_NAME ).':</label></th><td>'.
		'<input type=TEXT class="inputfield" maxlength="15" name="editednewbannedperson" '.
		'size="15" id="banname" value="'.$IN{'editednewbannedperson'}.'"></td></tr>';
	$page .= '<tr><th>&nbsp</th><td> <INPUT TYPE=HIDDEN NAME="section" VALUE="'.$IN{'section'}.'">'.
		'<input type=SUBMIT class="button" name="add" '.
		'STYLE="background: #D0FFD0" value="'.Gm_Core::text( Gm_Constants::ADD ).
		'"></td></tr></table></div></form>';
		
	$page .= '<FORM ACTION="gm.cgi" METHOD=POST> '.Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<p><INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" '.
		'VALUE="'.Gm_Core::text( Gm_Constants::RETURN_MAIN_MENU ).
		'" STYLE="background: #C0C0C0"></p></FORM><br />';
	## NAVIGATION SHOULD BE DE-BUTTONED
	
	Gm_Web::displayAdminPageExit( $page );
	exit(0);
}


## Add Banned Ip
# adds a given ip to the banlist of ip's
# RETURNS: A message to display on the view page
sub addBannedIp {
	my $message = Gm_Constants::EMPTY;
	
	$IN{'editednewbannedip'} =~ s/\n//g;
	$IN{'editednewbannedip'} =~ s/\|//g;
	$IN{'editednewbannedperson'} =~ s/\n//g;
	$IN{'editednewbannedperson'} =~ s/\|//g;
	
	if ($IN{'editednewbannedip'} eq Gm_Constants::EMPTY) {
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::BANIP_ENTER_IP ).'</span>';
#		&gm_editbanlist;
		viewBanList( $message );
	}
	
	my $gmbanlist = Gm_Storage::getBanlist( errHandler=>\&Gm_Web::displayAdminErrorExit );
	
	foreach my $gmbanlistline ( keys(%$gmbanlist)) {
		($checkthisip, $checkthisiphost, $checkthisperson) = 
			($gmbanlist->{$gmbanlistline}{'ip'}, $gmbanlist->{$gmbanlistline}{'host'}, 
			 $gmbanlist->{$gmbanlistline}{'label'} );
			 
		if ($checkthisip eq $IN{'editednewbannedip'}) {
			$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::BANIP_DUPE_IP ).'</span>';
#			&gm_editbanlist;
			viewBanList( $message );
		}
	}
	
	Gm_Storage::addBanlist( ip=>$IN{'editednewbannedip'}, host=>$IN{'editednewbannedip'}, 
		label=>$IN{'editednewbannedperson'}, errHandler=>\&Gm_Web::displayAdminErrorExit );
	
	if( $keeplog eq Gm_Constants::YES ){

		my $who_banned = '';
		if( $IN{'editednewbannedperson'} ne Gm_Constants::EMPTY ){ 
			$who_banned = ", \"$IN{'editednewbannedperson'}\""; 
		}
		my $cpMsg = Gm_Core::text( Gm_Constants::BANIP_ADDED, { AUTHOR=>$AUTHOR{'author'},
			IP=>$IN{'editednewbannedip'}, NAME=>$who_banned } );
		Gm_Core::writeToCplog( $cpMsg );
	}
	
	$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::BANIP_ADD_CONFIRM, 
		{ IP=>$IN{'editednewbannedip'} } ).'</span><p>';
#	&gm_editbanlist;

	## Don't need once Add is seperate screen
	$IN{'editednewbannedip'} = Gm_Constants::EMPTY;
	$IN{'editednewbannedperson'} = Gm_Constants::EMPTY;

	return( $message );
}


## Delete Banned Ip
# Delete the given ip|host combination from the banlist
# RETURNS: A message to display on the view page
sub deleteBannedIp {
	my $message = Gm_Constants::EMPTY;
	
	chomp($IN{'editedbanlist'});
	
	## Any other validation?
	if ($IN{'editedbanlist'} eq Gm_Constants::EMPTY) {
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::BANIP_SELECT_IP ).'</span>';
#		&gm_editbanlist;
		viewBanList( $message );
	}
	
# 	my ($banIp, $banHost) = split( '\|', $IN{'editedbanlist'});
	my $banIp = $IN{'editedbanlist'};
	
	# Since ip is the primary key
	my $deleted = Gm_Storage::deleteBanlist( ip=>$banIp, errHandler=>\&Gm_Web::displayAdminErrorExit );
	my $banLabel = $deleted->{'label'} ? ", \"$deleted->{'label'}\"" : ''; 
	
	if ($keeplog eq Gm_Constants::YES) {
		my $cpMsg = Gm_Core::text( Gm_Constants::BANIP_DELETED, { AUTHOR=>$AUTHOR{'author'},
			IP=>$banIp, LABEL=>$banLabel } );
		
		Gm_Core::writeToCplog( $cpMsg );
	}
	
	$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::BANIP_DELETE_CONFIRM,
		{ IP=>$banIp } ).'</span>';

	return( $message );
}


## Manage Authors SECTION #################################################
## Handle all requests for managing authors
## and verify that author can access this section
## TODO: Each author should be able to change own data, including password, so there
## should be a check that the author can edit their own info.
sub doAuthors {

	## Access to Banip is global, no need for granularity
	### TODO: CALL AUTH WITH FLAG TO WORK ON Banip, OR CHECK AUTHOR PERMS
	## TODO: Move this to auth, auth should return users perms, or it should take a flag to 
	# indicate which perms to check with this being handed off to a generic permDenied func
	if( $AUTHOR{'editauthors'} ne Gm_Constants::Y ){
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::AUTHORS_NO_ACCESS, { AUTHOR=>$AUTHOR{'author'} } ));
		my $statusnote = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_ACCESS_DENY ).
			'</span><br />';
		frontPage( $statusnote );
	}
	
	my $status = Gm_Constants::EMPTY;
# TODO, SHOULD THESE BE USING CONSTANTS?
	if( $IN{'delete'} ){
		$status = deleteAuthor();
		
	} elsif( $IN{'add'} ){
		$status = addAuthor();
		
	} elsif( $IN{'view'} ){
		$status = viewAuthor();
		
	} elsif( $IN{'update'} ){
		## TODO:  ADD IS SAME AS UPDATE, EXCEPT FROM SCRATCH?
		$status = updateAuthor();
		
	}

	## should this be else or should in fact be last command, taking a 'message' argument,
	# that could have been set by other calls to previous subroutines?
	viewAuthorList( $status );

}


## View Author List
# View the list authors registerd with Gm
# (opt) ARG1: Message to display to user, could be error or confirmation of action
sub viewAuthorList {
	my $message = shift( @_ ) || Gm_Constants::EMPTY;
	
	if( $message eq Gm_Constants::EMPTY ){ 
		$message = '<span class="info_text">'.Gm_Core::text( Gm_Constants::AUTHORS_INFO ).'</span>'; 
	}

# &gm_validate;
# 
# if ($gmauthoraccess ne Gm_Constants::YES) {
# 	gm_writetocplog("$IN{'authorname'} attempted to edit the authors without authorization");
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You don't have access to edit the authors.</FONT></B><P>);
# 	&gm_frontpage;
# }

# if ($statusnote eq Gm_Constants::EMPTY) { 
# 	$statusnote = qq(<B><FONT COLOR="#000000">Author Panel</FONT></B><BR><FONT SIZE=1>Select an author to edit their information and/or access, or to delete them altogether.</FONT><P>); 
# }

	my $page = '<span class="section_title">'.Gm_Core::text( Gm_Constants::AUTHORS_TITLE ).
		"</span><br /><p>$message</p>\n";	
	$page .= '<FORM ACTION="gm.cgi" METHOD="post"> '.
		Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<table width="80%" class="info_table"><tr><th>'.
		Gm_Core::text( Gm_Constants::NAME ).'</th><th>'.
		Gm_Core::text( Gm_Constants::AUTHORS_EMAIL ).'</th><th>'.
		Gm_Core::text( Gm_Constants::AUTHORS_HOMEPAGE ).'</th><th>'.
		Gm_Core::text( Gm_Constants::AUTHORS_PRIVS ).'</th><th width="30%">'.
		Gm_Core::text( Gm_Constants::ACTION ).'</td></tr>';

	my $gmauthors = Gm_Storage::getAuthors( errHandler=>\&Gm_Web::displayAdminErrorExit );

# print<<GMEDITAUTHORBEGINNING;
# 
# $gmheadtag
# 
# $gmframetop
# $statusnote
# <FORM ACTION="gm.cgi" METHOD=POST>
# <INPUT TYPE=HIDDEN NAME="authorname" VALUE="$IN{'authorname'}">
# <INPUT TYPE=HIDDEN NAME="authorpassword" VALUE="$IN{'authorpassword'}">
# <TABLE BORDER=0 CELLPADDING=1 CELLSPACING=0 WIDTH=100% BGCOLOR="#000000"><TR><TD><TABLE BORDER=0 CELLPADDING=4 CELLSPACING=1 WIDTH=100%>
# <TR><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag <FONT SIZE=1><B>Select</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Author<BR>Name</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Can<BR>post?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Can<BR>edit?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Can<BR>config?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Edit<BR>temp's?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Edit<BR>auth's?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Can<BR>reb'ld?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>View<BR>CP log?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Use<BR>b'lets?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Upload<BR>files?</B></FONT></FONT></TD><TD VALIGN=BOTTOM ALIGN=CENTER BGCOLOR="#B0B0D0">$gmfonttag<FONT SIZE=1><B>Can<BR>login?</B></FONT></FONT></TD></TR>
# 
# GMEDITAUTHORBEGINNING

# $alicewarning = Gm_Constants::EMPTY;
# $alternateauthorrowone = "#EEF8FF";
# $alternateauthorrowtwo = "#F8F8FF";
# $alternateauthorrow = $alternateauthorrowone;

	my @authors_array = sort { $gmauthors->{$a}{'author'} cmp $gmauthors->{$b}{'author'} } keys( %$gmauthors );

	my $base = '?section='.$IN{'section'}.'&'.Gm_Security::getUrlAuth( author=>\%AUTHOR );
	my ($page_nav, $short_authorslist ) = Gm_Web::createPaging( data=>\@authors_array,
		baseurl=>$base, webparams=>\%IN, pagesize=>(Gm_Constants::GM_PAGE_SIZE/5) );

	my $rowcolor = Gm_Web::altRowColor();
	foreach $authorListLine ( @{$short_authorslist} ) {
		my ( $author, $password, $email, $homepage, $postnew, $editentries, $editconfigs, 
			$edittemplates, $editauthors, $rebuild, $viewcplog, $bookmarklets, $upload, 
			$viewadmin ) = ( $gmauthors->{$authorListLine}{'author'}, 
			$gmauthors->{$authorListLine}{'password'}, $gmauthors->{$authorListLine}{'email'},
			$gmauthors->{$authorListLine}{'homepage'}, $gmauthors->{$authorListLine}{'postnew'},
			$gmauthors->{$authorListLine}{'editentries'}, $gmauthors->{$authorListLine}{'editconfigs'}, 
			$gmauthors->{$authorListLine}{'edittemplates'}, $gmauthors->{$authorListLine}{'editauthors'}, 
			$gmauthors->{$authorListLine}{'rebuild'}, $gmauthors->{$authorListLine}{'viewcplog'}, 
			$gmauthors->{$authorListLine}{'bookmarklets'}, $gmauthors->{$authorListLine}{'upload'}, 
			$gmauthors->{$authorListLine}{'viewadmin'});
	
		if ( $author eq 'Alice' && ($password eq 'wonderland' || $password eq 'woCCASD0Wk0IA') ){
			$alicewarning = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_ALICE_ALERT ).
			'</span><br />';
		}
	
		$author =~ s/</\&lt;/g;
		$author =~ s/>/\&gt;/g;
		$author =~ s/"/\&quot;/g;
	
		$rowcolor = Gm_Web::altRowColor( $rowcolor );
		
		$page .= "<tr $rowcolor><td>$author</td><td>$email</td><td>$homepage</td>";
		
		## figuring privilages
		my $privs = Gm_Core::text( Gm_Constants::AUTHORS_CUSTOM_ACCESS );
		if( $postnew eq Gm_Constants::Y && $editentries eq Gm_Constants::Y && 
			$editconfigs eq Gm_Constants::Y && $edittemplates eq Gm_Constants::Y && 
			$editauthors eq Gm_Constants::Y && $rebuild eq Gm_Constants::Y && 
			$viewcplog eq Gm_Constants::Y && $bookmarklets eq Gm_Constants::Y && 
			$upload eq Gm_Constants::Y && $viewadmin eq Gm_Constants::Y ){
			$privs = Gm_Core::text( Gm_Constants::AUTHORS_ALL_ACCESS );
			
		} elsif( $postnew eq Gm_Constants::Y && $editentries eq 'O' && 
			$editconfigs eq Gm_Constants::N && $edittemplates eq Gm_Constants::N && 
			$editauthors eq Gm_Constants::N && $rebuild eq Gm_Constants::N && 
			$viewcplog eq Gm_Constants::N && $bookmarklets eq Gm_Constants::Y && 
			$upload eq Gm_Constants::N && $viewadmin eq Gm_Constants::Y ){
			$privs = Gm_Core::text( Gm_Constants::AUTHORS_OWN_SHORT );
			
		} elsif( $postnew eq Gm_Constants::N && $editentries eq Gm_Constants::N && 
			$editconfigs eq Gm_Constants::N && $edittemplates eq Gm_Constants::N && 
			$editauthors eq Gm_Constants::N && $rebuild eq Gm_Constants::N && 
			$viewcplog eq Gm_Constants::N && $bookmarklets eq Gm_Constants::N && 
			$upload eq Gm_Constants::N && $viewadmin eq Gm_Constants::N ){
			$privs = Gm_Core::text( Gm_Constants::AUTHORS_NO_ACCESS );
			
		}
		$page .= "<td>$privs</td><td>\n";
		
		## Edit, Delete buttons
		$page .= '<a href="'.$ENV{SCRIPT_NAME}.'?section='.$IN{'section'}.'&delete=1&'.
		'selectedauthor='.$author.
		'&'.Gm_Security::getUrlAuth( author=>\%AUTHOR ).
		'" class="link_button" STYLE="background: #FFD0D0">'.
		Gm_Core::text( Gm_Constants::DELETE ).'</a>';
		
		$page .= ' &#160; <a href="'.$ENV{SCRIPT_NAME}.'?section='.$IN{'section'}.'&view=1&'.
		'selectedauthor='.$author.
		'&'.Gm_Security::getUrlAuth( author=>\%AUTHOR ).
		'" class="link_button" STYLE="background: #D0FFD0">'.
		Gm_Core::text( Gm_Constants::EDIT ).'</a>';
		
		$page .= '</td></tr>'."\n";
	}

## We are looping through keys of hash (keys are author names) and sorting
# foreach my $author ( sort { $gmauthors->{$a}{'author'} cmp $gmauthors->{$b}{'author'} } keys( %$gmauthors ) ) {
# 	if ($alternateauthorrow eq $alternateauthorrowone) {
# 		$alternateauthorrow = $alternateauthorrowtwo;
# 	} else {
# 		$alternateauthorrow = $alternateauthorrowone;
# 	}
# 
# 	if (($gmauthors->{$author}{'author'} eq 'Alice') && ($gmauthors->{$author}{'password'} eq 'wonderland')) {
# 		$alicewarning = "<P><B>Be sure to create your own author and delete Alice!</B>"
# 	}
# 	println('<TR><TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="'.$alternateauthorrow.'" NOWRAP>'.
# 		'<INPUT TYPE=RADIO NAME="selectedauthor" VALUE="'.$gmauthors->{$author}{'author'}.'">'.
# 		'</TD><TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="'.$alternateauthorrow.'" NOWRAP>'.
# 		$gmfonttag.$gmauthors->{$author}{'author'}.'</FONT></TD>');
# 	## TODO: 
# 	if ($gmauthors->{$author}{'postnew'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'editentries'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} elsif ($gmauthors->{$author}{'editentries'} eq 'O') {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Own</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'editconfigs'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'edittemplates'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} elsif ($gmauthors->{$author}{'edittemplates'} eq 'O') {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag HFS</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'editauthors'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'rebuild'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'viewcplog'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'bookmarklets'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'upload'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	if ($gmauthors->{$author}{'viewadmin'} eq Gm_Constants::Y ) {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag Yes</FONT></TD>);
# 	} else {
# 		print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="$alternateauthorrow" NOWRAP>$gmfonttag No</FONT></TD>);
# 	}
# 	print "</TR>\n";
# }

# print<<GMEDITAUTHORSBOTTOM;
# 
# </TABLE></TD></TR></TABLE>
# <P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" STYLE="background: #D0FFD0" VALUE="Edit Selected Author"> <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" STYLE="background: #FFD0D0" VALUE="Delete Selected Author">
# $alicewarning
# <P>
# <TABLE BORDER=0 cellpadding=1 CELLSPACING=0 BGCOLOR="#000000"><TR><TD><TABLE BORDER=0 CELLPADDING=10 CELLSPACING=0 BGCOLOR="#D0E0FF" WIDTH=680><TR><TD VALIGN=MIDDLE ALIGN=CENTER>$gmfonttag<B>Register A New Author</B><BR><FONT SIZE=1>
# Create a new account for someone to have access to Greymatter with (giving an e-mail or homepage is optional).  You can specify whether the author is created having access to everything, to nothing, or to post & edit their own entries only; you can then customise their access further by editing their account above after it's been created.
# </FONT><P>Name: <INPUT TYPE=TEXT CLASS="textinput" SIZE=25 NAME="newauthorname"> 
# &#160; &#160; Password: <INPUT TYPE=PASSWORD CLASS="textinput" SIZE=25 NAME="newauthorpassword"><P>
# E-Mail: <INPUT TYPE=TEXT CLASS="textinput" SIZE=30 NAME="newauthoremail">
# &#160; &#160; Homepage: <INPUT TYPE=TEXT CLASS="textinput" SIZE=30 NAME="newauthorhomepage" VALUE="http://"><P>
# <B>Default Author Access</B><BR>
# <INPUT TYPE=RADIO NAME="newauthoraccess" VALUE="all" CHECKED> All access &#160; 
# <INPUT TYPE=RADIO NAME="newauthoraccess" VALUE="none"> No access<BR>
# <INPUT TYPE=RADIO NAME="newauthoraccess" VALUE="postedit"> Post & edit their own entries only<P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas"  STYLE="background: #D0FFD0" VALUE="Create New Author"></FONT></TD></TR></TABLE></TD></TR></TABLE>
# <P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" VALUE="Return To Main Menu" STYLE="background: #C0C0C0">
# </FORM>
# <P>
# $gmframebottom
# 
# </BODY>
# </HTML>
# 
# GMEDITAUTHORSBOTTOM
# 
# $statusnote = Gm_Constants::EMPTY;
# 
# exit;

	$page .= "</table><div class='pagenav'>$page_nav</div><br />\n";	
	$page .= "<p>$alicewarning</p>\n";
	
	## TODO: THESE ELEMENTS SHOULD BE REVALIDATED BEFORE DOING ANYTHING WITH
	
	$page .= '<div class="info_box"><span class="info_title">'.Gm_Core::text( Gm_Constants::AUTHORS_ADD_TITLE ).
		'</span><p>'.Gm_Core::text( Gm_Constants::AUTHORS_ADD_INFO ).'</p>';

	$page .= '<table width="80%" class="form_table">'.
		'<tr><th><label for="name">'.Gm_Core::text( Gm_Constants::NAME ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="25" name="newauthorname" size="15" '.
		'id="name" value="'.$IN{'newauthorname'}.'"></td></tr>';
	$page .= '<tr><th><label for="pw">'.Gm_Core::text( Gm_Constants::PW ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="25" name="newauthorpassword" size="15" '.
		'id="pw" value="'.$IN{'newauthorpassword'}.'"></td></tr>';
	$page .= '<tr><th><label for="email">'.Gm_Core::text( Gm_Constants::AUTHORS_EMAIL ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="30" name="newauthoremail" size="15" '.
		'id="email" value="'.$IN{'newauthoremail'}.'"></td></tr>';
	unless( $IN{'newauthorhomepage'} ){ ## setting default value
		$IN{'newauthorhomepage'} = 'http://';
	}
	$page .= '<tr><th><label for="homepage">'.Gm_Core::text( Gm_Constants::AUTHORS_HOMEPAGE ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="30" name="newauthorhomepage" size="15" '.
		'id="homepage" value="'.$IN{'newauthorhomepage'}.'"></td></tr>';		
	
	unless( $IN{'newauthoraccess'} ){
		$IN{'newauthoraccess'} = 'all';
	}
	$page .= '<tr><th>'.Gm_Core::text( Gm_Constants::AUTHORS_DEF_ACCESS ).':</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'newauthoraccess', value=>'all', id=>'all_access',
		checked=>$IN{'newauthoraccess'} ).
#		'<input type="radio" name="newauthoraccess" value="all" id="all_access" CHECKED>'.
		'<label for="all_access">'.Gm_Core::text( Gm_Constants::AUTHORS_ALL_ACCESS ).'</label>&#160; '.
#		'<input type="radio" name="newauthoraccess" value="none" id="no_access">'.
		Gm_Web::createRadioButton( name=>'newauthoraccess', value=>'none', id=>'no_access',
		checked=>$IN{'newauthoraccess'} ).
		'<label for="no_access">'.Gm_Core::text( Gm_Constants::AUTHORS_NO_ACCESS ).'</label><br /> '.
#		'<input type="radio" name="newauthoraccess" value="postedit" id="own_access"> '.
		Gm_Web::createRadioButton( name=>'newauthoraccess', value=>'postedit', id=>'own_access',
		checked=>$IN{'newauthoraccess'} ).
		'<label for="own_access">'.Gm_Core::text( Gm_Constants::AUTHORS_OWN_ACCESS ).'</label>'.
		'</td></tr>';		
		
	$page .= '<tr><th>&nbsp</th><td><INPUT TYPE=HIDDEN NAME="section" VALUE="'.$IN{'section'}.'">'.
		'<input type=SUBMIT class="button" name="add" '.
		'STYLE="background: #D0FFD0" value="'.Gm_Core::text( Gm_Constants::ADD ).
		'"></td></tr></table></div></form>';
		
	$page .= '<FORM ACTION="gm.cgi" METHOD=POST> '.Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<p><INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" '.
		'VALUE="'.Gm_Core::text( Gm_Constants::RETURN_MAIN_MENU ).
		'" STYLE="background: #C0C0C0"></p></FORM><br />';
	## NAVIGATION SHOULD BE DE-BUTTONED
	
	Gm_Web::displayAdminPageExit( $page );
	exit(0);
}


## Add Author
# adds a given author to Greymatter's registered authors list
# RETURNS: A message to display on the view page
## NOTE: should part of this be generized and put in Core?  Something that doesn't presume where its being
# called from so it can be reused with normal user self-registration?
# ALSO:  can this and updateAuthor be abstracted to reduce duplicate error checking?
sub addAuthor {
	my $message = Gm_Constants::EMPTY;
	
# &gm_validate;
# 
# if ($gmauthoraccess ne Gm_Constants::YES) {
# 	gm_writetocplog("$IN{'authorname'} attempted to create a new author without authorization");
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You don't have access to create a new author.</FONT></B><P>);
# 	&gm_frontpage;
# }

	if( ($IN{'newauthorname'} eq Gm_Constants::EMPTY) || 
		($IN{'newauthorpassword'} eq Gm_Constants::EMPTY) ){
#		$message = qq(<B><FONT COLOR="#FF0000">You left either the name or password fields blank.  Please try again.</FONT></B><P>);
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_ENTER_NAME_PW ).'</span>';
#		&gm_editauthors;
		## should this be return?  we are limiting its use to just on web, specically author page.  Make this function generic so users can register?
		viewAuthorList( $message ); 
	}

	if( ($IN{'newauthorname'} =~ /^\s+/) || ($IN{'newauthorpassword'} =~ /^\s+/) || 
		($IN{'newauthorname'} =~ /\s+$/) || ($IN{'newauthorpassword'} =~ /\s+$/) ) {
#		$message = qq(<B><FONT COLOR="#FF0000">You cannot have a space at the beginning or end<BR>of the author name or password.  Please try again.</FONT></B><P>);
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_NOWS_NAME_PW ).'</span>';
		viewAuthorList( $message );
	}

	## We are removing spaces temporily, so that we can use perl regex shorthand 
	$IN{'newauthorname'} =~ s/ /THISISASPACE/g;
	$IN{'newauthorpassword'} =~ s/ /THISISASPACE/g;
	
	if (($IN{'newauthorname'} =~ /\W/) || ($IN{'newauthorpassword'} =~ /\W/)) {
#		$message = qq(<B><FONT COLOR="#FF0000">The author name or password cannot contain non-alphanumeric characters<BR>(characters other than letters, numbers or spaces).  Please try again.</FONT></B><P>);
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_BAD_NAME_PW ).'</span>';
		viewAuthorList( $message );
	}
	## Now we are restoring to proper form
	$IN{'newauthorname'} =~ s/THISISASPACE/ /g;
	$IN{'newauthorpassword'} =~ s/THISISASPACE/ /g;

	$IN{'newauthoremail'} = Gm_Utils::trimFrontWs( $IN{'newauthoremail'} );
	$IN{'newauthoremail'} = Gm_Utils::trimBackWs( $IN{'newauthoremail'} );
	$IN{'newauthorhomepage'} = Gm_Utils::trimFrontWs( $IN{'newauthorhomepage'} );
	$IN{'newauthorhomepage'} = Gm_Utils::trimBackWs( $IN{'newauthorhomepage'} );

	my $gmauthors = Gm_Storage::getAuthors( errHandler=>\&Gm_Web::displayAdminErrorExit );

	## just checking if author name exisits, note this works because of keys we are using
	# would have to change if we made keys a numeric id or something (but name better be unique)
	if ( exists( $gmauthors->{$IN{'newauthorname'}}) ) {
#		Gm_Core::writeToCplog("$IN{'authorname'} attempted to add an author that is already registered ($IN{'newauthorname'})");
		my $cpMsg = Gm_Core::text( Gm_Constants::AUTHORS_DUPE_LOG, { AUTHOR=>$AUTHOR{'author'},
			NAME=>$IN{'newauthorname'} } );
		Gm_Core::writeToCplog( $cpMsg );
#		$message = qq(<B><FONT COLOR="#FF0000">That author is already registered.</FONT></B><P>);
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_DUPE_NAME ).'</span>';
		viewAuthorList( $message );
	}

# 	$temphomepageprefix = substr($IN{'newauthorhomepage'}, 0, 7);
# 	if ($temphomepageprefix ne "http://") { $IN{'newauthorhomepage'} = "http://$IN{'newauthorhomepage'}"; }
	## old code failed to account for https urls
	if( $IN{'newauthorhomepage'} !~ m/^http/i ){ 
		# If it doesn't start with http, lets add it for them
		$IN{'newauthorhomepage'} = "http://$IN{'newauthorhomepage'}"; 
	}

# if ($IN{'newauthorhomepage'} eq "http://") { $IN{'newauthorhomepage'} = Gm_Constants::EMPTY; }
	## default was unchanged, so we just leave as blank
	if( $IN{'newauthorhomepage'} eq 'http://' ){ 
		$IN{'newauthorhomepage'} = Gm_Constants::EMPTY; 
	}

	my ($skip, $wday, $mon, $mday, $JSYear, $hour, $min, $sec, $AMPM ) = 
		Gm_Utils::getStdDate( $serveroffset );
	my $montwo = Gm_Utils::toTwoDigit( $mon );
	my $mdaytwo = Gm_Utils::toTwoDigit( $mday );
	# TODO STANDARDIZE HOW DATES ARE STORED (WITH LEADING 0 OR NOT)

	## This should be abstracted out to security, such as setAuthorCredentials
	## Also, authors should have a field, credential id, that is a unique identifier
	# that is determined by Gm_Security
	$IN{'newauthorpassword'} = crypt($IN{'newauthorpassword'},$IN{'newauthorpassword'});

	my %newAuthor = ();
	$newAuthor{'author'} = $IN{'newauthorname'};
	$newAuthor{'password'} = $IN{'newauthorpassword'};
	$newAuthor{'email'} = $IN{'newauthoremail'};
	$newAuthor{'homepage'} = $IN{'newauthorhomepage'};
	$newAuthor{'created'} = "$montwo\/$mdaytwo\/$JSYear";
	$newAuthor{'posttotal'} = '0';

	if ($IN{'newauthoraccess'} eq Gm_Constants::ALL) {
		$newAuthor{'postnew'} = Gm_Constants::Y;
		$newAuthor{'editentries'} = Gm_Constants::Y;
		$newAuthor{'editconfigs'} = Gm_Constants::Y;
		$newAuthor{'edittemplates'} = Gm_Constants::Y;
		$newAuthor{'editauthors'} = Gm_Constants::Y;
		$newAuthor{'rebuild'} = Gm_Constants::Y;
		$newAuthor{'viewcplog'} = Gm_Constants::Y;
		$newAuthor{'bookmarklets'} = Gm_Constants::Y;
		$newAuthor{'upload'} = Gm_Constants::Y;
		$newAuthor{'viewadmin'} = Gm_Constants::Y;
	} elsif ($IN{'newauthoraccess'} eq 'postedit') {
		# Some perms
		$newAuthor{'postnew'} = Gm_Constants::Y;
		$newAuthor{'editentries'} = 'O';
		$newAuthor{'editconfigs'} = Gm_Constants::N;
		$newAuthor{'edittemplates'} = Gm_Constants::N;
		$newAuthor{'editauthors'} = Gm_Constants::N;
		$newAuthor{'rebuild'} = Gm_Constants::N;
		$newAuthor{'viewcplog'} = Gm_Constants::N;
		$newAuthor{'bookmarklets'} = Gm_Constants::Y;
		$newAuthor{'upload'} = Gm_Constants::N;
		$newAuthor{'viewadmin'} = Gm_Constants::Y;
	} else {
		# No perms
		$newAuthor{'postnew'} = Gm_Constants::N;
		$newAuthor{'editentries'} = Gm_Constants::N;
		$newAuthor{'editconfigs'} = Gm_Constants::N;
		$newAuthor{'edittemplates'} = Gm_Constants::N;
		$newAuthor{'editauthors'} = Gm_Constants::N;
		$newAuthor{'rebuild'} = Gm_Constants::N;
		$newAuthor{'viewcplog'} = Gm_Constants::N;
		$newAuthor{'bookmarklets'} = Gm_Constants::N;
		$newAuthor{'upload'} = Gm_Constants::N;
		$newAuthor{'viewadmin'} = Gm_Constants::N;
	}

	Gm_Storage::addAuthor( %newAuthor, errHandler=>\&Gm_Web::displayAdminErrorExit );

#	Gm_Core::writeToCplog("$IN{'authorname'} registered a new author ($IN{'newauthorname'})");
	Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::AUTHORS_ADD_LOG, { AUTHOR=>$AUTHOR{'author'},
		NAME=>$IN{'newauthorname'} } ) );

#	$message = qq(<B><FONT COLOR="#0000FF">$IN{'newauthorname'} has been added to the author database.</FONT></B><P>);
	$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_ADD_CONFIRM, 
	{ NAME=>$IN{'newauthorname'} } ).'</span><p>';

	$IN{'newauthorname'} = Gm_Constants::EMPTY;
	$IN{'newauthorpassword'} = Gm_Constants::EMPTY;
	$IN{'newauthoremail'} = Gm_Constants::EMPTY;
	$IN{'newauthorhomepage'} = Gm_Constants::EMPTY;

#&gm_editauthors;
	## we are just adding, no control flow
	return( $message );
}


## Delete Author
# Delete the given author from the list of authors
# RETURNS: A message to display on the view page
sub deleteAuthor {
	my $message = Gm_Constants::EMPTY;
	
# &gm_validate;
# 
# if ($gmauthoraccess ne Gm_Constants::YES) {
# 	gm_writetocplog("$IN{'authorname'} attempted to delete an author ($IN{'selectedauthor'}) without authorization");
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You don't have access to delete authors.</FONT></B><P>);
# 	&gm_frontpage;
# }


	my $gmauthors = Gm_Storage::getAuthors( errHandler=>\&Gm_Web::displayAdminErrorExit );

	if( !defined( $IN{'selectedauthor'} ) || !exists( $gmauthors->{$IN{'selectedauthor'}}) ){
#		$statusnote = qq(<B><FONT COLOR="#FF0000">You must select an author first.</FONT></B><P>);
#		&gm_editauthors;
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_SELECT_NAME ).'</span>';
		viewAuthorList( $message );
	}

	if( scalar( keys(%$gmauthors)) == 1 ){
# 		$statusnote = qq(<B><FONT COLOR="#FF0000">You can't delete the only remaining author!</FONT></B><P>);
# 		&gm_editauthors;
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_NO_DELETE ).'</span>';
		viewAuthorList( $message );
	}

	Gm_Storage::deleteAuthor( author=>$IN{'selectedauthor'}, errHandler=>\&Gm_Web::displayAdminErrorExit );

# if ($IN{'selectedauthor'} eq $IN{'authorname'}) {
# 	gm_writetocplog("$IN{'authorname'} deleted himself/herself.");
# } else {
# 	gm_writetocplog("$IN{'authorname'} deleted an author ($IN{'selectedauthor'})");
# }
	Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::AUTHORS_DELETE_LOG, { AUTHOR=>$AUTHOR{'author'},
		NAME=>$IN{'selectedauthor'} } ) );

	if( $IN{'selectedauthor'} eq $AUTHOR{'author'} ){
# 		$loginnotice = qq(<B><FONT COLOR="#0000FF">Please re-enter under your new author name and password.</FONT></B><P>);
# 		&gm_login;
		%AUTHOR = %{ Gm_Security::auth( webparams=>\%IN, reauth=>1,
			errHandler=>\&Gm_Web::displayAdminErrorExit ) };
		} else {
# 		$statusnote = qq(<B><FONT COLOR="#0000FF">$IN{'selectedauthor'} has been deleted.</FONT></B><P>);
# 		&gm_editauthors;
		$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_DELETE_CONFIRM, 
			{ NAME=>$IN{'selectedauthor'} }  ).'</span>';
		viewAuthorList( $message );
	}

}


## View Author
# Edit a particular author
# (opt) ARG1: Message to display to user, could be error or confirmation of action
sub viewAuthor {
	my $message = shift( @_ ) || Gm_Constants::EMPTY;
	
# &gm_validate;
# 
# if ($gmauthoraccess ne Gm_Constants::YES) {
# 	gm_writetocplog("$IN{'authorname'} attempted to edit the authors without authorization");
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You don't have access to edit the authors.</FONT></B><P>);
# 	&gm_frontpage;
# }

my $gmauthors = Gm_Storage::getAuthors( errHandler=>\&Gm_Web::displayAdminErrorExit );

	if ( !defined( $IN{'selectedauthor'} ) || !exists( $gmauthors->{$IN{'selectedauthor'}}) ) {
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You must select an author first.</FONT></B><P>);
# 	&gm_editauthors;
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_SELECT_NAME ).'</span>';
		viewAuthorList( $message );
	}

	my $selectedauthor = $gmauthors->{$IN{'selectedauthor'}};

	if( $selectedauthor->{'homepage'} eq Gm_Constants::EMPTY ){ 
		$selectedauthor->{'homepage'} = "http://"; 
	}

	if( $message eq Gm_Constants::EMPTY ){ 
		$message = '<span class="info_text">'.Gm_Core::text( Gm_Constants::AUTHORS_STATS, 
			{ CREATED=>$selectedauthor->{'created'}, ENTRIES=>$selectedauthor->{'posttotal'} } ).'</span>'; 
	} 
	
	

# print<<GMEDITSELECTEDAUTHORTOP;
# 
# $gmheadtag
# 
# $gmframetop
# $statusnote
# <FORM ACTION="gm.cgi" METHOD=POST>
# <INPUT TYPE=HIDDEN NAME="authorname" VALUE="$IN{'authorname'}">
# <INPUT TYPE=HIDDEN NAME="authorpassword" VALUE="$IN{'authorpassword'}">
# <INPUT TYPE=HIDDEN NAME="authororiginalname" VALUE="$selectedauthor->{'author'}">
# <INPUT TYPE=HIDDEN NAME="authororiginalpassword" VALUE="$selectedauthor->{'password'}">
# <INPUT TYPE=HIDDEN NAME="authororiginaldate" VALUE="$selectedauthor->{'created'}">
# <INPUT TYPE=HIDDEN NAME="authororiginalentries" VALUE="$selectedauthor->{'posttotal'}">
# <INPUT TYPE=HIDDEN NAME="editedauthornumber" VALUE="$selectedauthor->{'author'}">

	my $page = '<span class="section_title">'.Gm_Core::text( Gm_Constants::AUTHORS_EDIT_TITLE, 
			{ AUTHOR=>$selectedauthor->{'author'} } )."</span><br /><p>$message</p>\n";	
			
	$page .= '<form action="gm.cgi" method="post"> '.
		Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<input type="hidden" name="selectedauthor" value="'.$selectedauthor->{'author'}."\">\n".
		'<input type="hidden" name="authororiginalpassword" value="'.$selectedauthor->{'password'}."\">\n".
		'<input type="hidden" name="authororiginaldate" value="'.$selectedauthor->{'created'}."\">\n".
		'<input type="hidden" name="authororiginalentries" value="'.$selectedauthor->{'posttotal'}."\">\n".
		'<input type="hidden" name="editedauthornumber" value="'.$selectedauthor->{'author'}."\">\n";
		


# <TABLE BORDER=0 CELLPADDING=1 CELLSPACING=0 BGCOLOR="#000000"><TR><TD><TABLE BORDER=0 CELLPADDING=7 CELLSPACING=1>
# <TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Name:</FONT></TD><TD VALIGN=MIDDLE ALIGN=LEFT BGCOLOR="#FFFFFF">
#<INPUT TYPE=TEXT CLASS="textinput" NAME="editedname" VALUE="$selectedauthor->{'author'}" SIZE=20></TD></TR>
# <TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Password:</FONT></TD><TD VALIGN=MIDDLE ALIGN=LEFT BGCOLOR="#FFFFFF">
#<INPUT TYPE=PASSWORD CLASS="textinput" NAME="editedpassword" VALUE="$selectedauthor->{'password'}" SIZE=20></TD></TR>
# <TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag E-Mail:</FONT></TD><TD VALIGN=MIDDLE ALIGN=LEFT BGCOLOR="#FFFFFF">
#<INPUT TYPE=TEXT CLASS="textinput" NAME="editedemail" VALUE="$selectedauthor->{'email'}" SIZE=20></TD></TR>
# <TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Homepage:</FONT></TD><TD VALIGN=MIDDLE ALIGN=LEFT BGCOLOR="#FFFFFF">
#<INPUT TYPE=TEXT CLASS="textinput" NAME="editedhomepage" VALUE="$selectedauthor->{'homepage'}" SIZE=20></TD></TR>
# 
# GMEDITSELECTEDAUTHORTOP

	$page .= '<table width="80%" class="form_table">'.
		'<tr><th><label for="name">'.Gm_Core::text( Gm_Constants::NAME ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="25" name="editedname" size="15" '.
		'id="name" value="'.$selectedauthor->{'author'}.'"></td></tr>';
	$page .= '<tr><th><label for="pw">'.Gm_Core::text( Gm_Constants::PW ).':</label></th>'.
		'<td><input type="password" class="inputfield" maxlength="25" name="editedpassword" size="15" '.
		'id="pw" value="'.$selectedauthor->{'password'}.'"></td></tr>';
	$page .= '<tr><th><label for="email">'.Gm_Core::text( Gm_Constants::AUTHORS_EMAIL ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="30" name="editedemail" size="15" '.
		'id="email" value="'.$selectedauthor->{'email'}.'"></td></tr>';
	unless( $selectedauthor->{'homepage'} ){ ## setting default value
		$selectedauthor->{'homepage'} = 'http://';
	}
	$page .= '<tr><th><label for="homepage">'.Gm_Core::text( Gm_Constants::AUTHORS_HOMEPAGE ).':</label></th>'.
		'<td><input type="text" class="inputfield" maxlength="30" name="editedhomepage" size="15" '.
		'id="homepage" value="'.$selectedauthor->{'homepage'}.'"></td></tr>';		
#	$page .= '<tr colspan="2"><td>&#160; </td></tr>';
	
# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can post new entries?:</FONT></TD>);
# if ($selectedauthor->{'postnew'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT 
# 	TYPE=RADIO NAME="editedentryaccess" VALUE="Y" CHECKED> Yes <INPUT TYPE=RADIO 
# 	NAME="editedentryaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO 
# 	NAME="editedentryaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedentryaccess" 
# 	VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_POST ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedentryaccess', value=>'Y', id=>'new_entries_yes',
		checked=>$selectedauthor->{'postnew'} ).
		'<label for="new_entries_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedentryaccess', value=>'N', id=>'new_entries_no',
		checked=>$selectedauthor->{'postnew'} ).
		'<label for="new_entries_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can edit entries?:</FONT></TD>);
# if ($selectedauthor->{'editentries'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="N"> No<BR>
# 	<INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="O"> Only their own entries</FONT></TD></TR>\n);
# } elsif ($selectedauthor->{'editentries'} eq 'O') {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="N"> No<BR><INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="O" CHECKED> Only their own entries</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="N" CHECKED> No<BR><INPUT TYPE=RADIO NAME="editedentryeditaccess" VALUE="O"> Only their own entries</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_EDIT ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedentryeditaccess', value=>'Y', id=>'edit_entries_yes',
		checked=>$selectedauthor->{'editentries'} ).
		'<label for="edit_entries_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedentryeditaccess', value=>'N', id=>'edit_entries_no',
		checked=>$selectedauthor->{'editentries'} ).
		'<label for="edit_entries_no">'.Gm_Core::text( Gm_Constants::NO ).'</label><br /> '.
		Gm_Web::createRadioButton( name=>'editedentryeditaccess', value=>'O', id=>'edit_entries_own',
		checked=>$selectedauthor->{'editentries'} ).
		'<label for="edit_entries_own">'.Gm_Core::text( Gm_Constants::AUTHORS_ONLY_OWN ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can configure?:</FONT></TD>);
# if ($selectedauthor->{'editconfigs'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# <INPUT TYPE=RADIO NAME="editedconfigureaccess" VALUE="Y" CHECKED> Yes 
# <INPUT TYPE=RADIO NAME="editedconfigureaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedconfigureaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedconfigureaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_CONFIG ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedconfigureaccess', value=>'Y', id=>'configure_yes',
		checked=>$selectedauthor->{'editconfigs'} ).
		'<label for="configure_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedconfigureaccess', value=>'N', id=>'configure_no',
		checked=>$selectedauthor->{'editconfigs'} ).
		'<label for="configure_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can edit templates?:</FONT></TD>);
# if ($selectedauthor->{'edittemplates'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# <INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="Y" CHECKED> Yes 
# <INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="N"> No<BR>
# <INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="O"> Only header/footer/sidebar</FONT></TD></TR>\n);
# } elsif ($selectedauthor->{'edittemplates'} eq 'O') {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="N"> No<BR><INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="O" CHECKED> Only header/footer/sidebar</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="N" CHECKED> No<BR><INPUT TYPE=RADIO NAME="editedtemplateaccess" VALUE="O"> Only header/footer/sidebar</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_TEMPLATES ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedtemplateaccess', value=>'Y', id=>'edit_templates_yes',
		checked=>$selectedauthor->{'edittemplates'} ).
		'<label for="edit_templates_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedtemplateaccess', value=>'N', id=>'edit_templates_no',
		checked=>$selectedauthor->{'edittemplates'} ).
		'<label for="edit_templates_no">'.Gm_Core::text( Gm_Constants::NO ).'</label><br /> '.
		Gm_Web::createRadioButton( name=>'editedtemplateaccess', value=>'O', id=>'edit_templates_own',
		checked=>$selectedauthor->{'edittemplates'} ).
		'<label for="edit_templates_own">'.Gm_Core::text( Gm_Constants::AUTHORS_ONLY_HEAD ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can edit authors?:</FONT></TD>);
# if ($selectedauthor->{'editauthors'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedauthoraccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedauthoraccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedauthoraccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedauthoraccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_AUTHORS ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedauthoraccess', value=>'Y', id=>'edit_author_yes',
		checked=>$selectedauthor->{'editauthors'} ).
		'<label for="edit_author_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedauthoraccess', value=>'N', id=>'edit_author_no',
		checked=>$selectedauthor->{'editauthors'} ).
		'<label for="edit_author_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can rebuild files?:</FONT></TD>);
# if ($selectedauthor->{'rebuild'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedrebuildaccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedrebuildaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedrebuildaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedrebuildaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_REBUILD ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedrebuildaccess', value=>'Y', id=>'rebuild_yes',
		checked=>$selectedauthor->{'rebuild'} ).
		'<label for="rebuild_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedrebuildaccess', value=>'N', id=>'rebuild_no',
		checked=>$selectedauthor->{'rebuild'} ).
		'<label for="rebuild_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';	

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can view CP log?:</FONT></TD>);
# if ($selectedauthor->{'viewcplog'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedcplogaccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedcplogaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedcplogaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedcplogaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_CPLOG ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedcplogaccess', value=>'Y', id=>'view_cplog_yes',
		checked=>$selectedauthor->{'viewcplog'} ).
		'<label for="view_cplog_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedcplogaccess', value=>'N', id=>'view_cplog_no',
		checked=>$selectedauthor->{'viewcplog'} ).
		'<label for="view_cplog_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can use bookmarklets?:</FONT></TD>);
# if ($selectedauthor->{'bookmarklets'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedbookmarkletaccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedbookmarkletaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedbookmarkletaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedbookmarkletaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	## TODO: THIS SHOULD BE SAME AS POST ENTRIES, JUST DIFFERENT METHOD, WHY TWO PERMS
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_BM ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedbookmarkletaccess', value=>'Y', id=>'bookmarklets_yes',
		checked=>$selectedauthor->{'bookmarklets'} ).
		'<label for="bookmarklets_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedbookmarkletaccess', value=>'N', id=>'bookmarklets_no',
		checked=>$selectedauthor->{'bookmarklets'} ).
		'<label for="bookmarklets_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can upload files?:</FONT></TD>);
# if ($selectedauthor->{'upload'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# <INPUT TYPE=RADIO NAME="editeduploadaccess" VALUE="Y" CHECKED> Yes 
# <INPUT TYPE=RADIO NAME="editeduploadaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editeduploadaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editeduploadaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr class="form_long"><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_UPLOAD ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editeduploadaccess', value=>'Y', id=>'upload_yes',
		checked=>$selectedauthor->{'upload'} ).
		'<label for="upload_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editeduploadaccess', value=>'N', id=>'upload_no',
		checked=>$selectedauthor->{'upload'} ).
		'<label for="upload_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';

# print qq(<TR><TD VALIGN=MIDDLE ALIGN=RIGHT BGCOLOR="#FFFFFF">$gmfonttag Can login to gm.cgi?:</FONT></TD>);
# if ($selectedauthor->{'viewadmin'} eq Gm_Constants::Y ) {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag
# 	<INPUT TYPE=RADIO NAME="editedloginaccess" VALUE="Y" CHECKED> Yes 
# 	<INPUT TYPE=RADIO NAME="editedloginaccess" VALUE="N"> No</FONT></TD></TR>\n);
# } else {
# 	print qq(<TD VALIGN=MIDDLE ALIGN=CENTER BGCOLOR="#FFFFFF">$gmfonttag<INPUT TYPE=RADIO NAME="editedloginaccess" VALUE="Y"> Yes <INPUT TYPE=RADIO NAME="editedloginaccess" VALUE="N" CHECKED> No</FONT></TD></TR>\n);
# }
	$page .= '<tr><th>'.Gm_Core::text( Gm_Constants::AUTHORS_CAN_LOGIN ).'</th>'.
		'<td>'.Gm_Web::createRadioButton( name=>'editedloginaccess', value=>'Y', id=>'view_admin_yes',
		checked=>$selectedauthor->{'viewadmin'} ).
		'<label for="view_admin_yes">'.Gm_Core::text( Gm_Constants::YES ).'</label>&#160; '.
		Gm_Web::createRadioButton( name=>'editedloginaccess', value=>'N', id=>'view_admin_no',
		checked=>$selectedauthor->{'viewadmin'} ).
		'<label for="view_admin_no">'.Gm_Core::text( Gm_Constants::NO ).'</label>'.
		'</td></tr>';

# print<<GMEDITSELECTEDAUTHORBOTTOM;
# 
# </TABLE></TD></TR></TABLE>
# <P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" STYLE="background: #D0FFD0" VALUE="Save Changes To This Author"> <INPUT TYPE=RESET CLASS="button" STYLE="background: #FFD0D0" VALUE="Undo Changes Since Last Save">
# <P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" VALUE="Return To Author Panel">
# <P>
# <INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" VALUE="Return To Main Menu" STYLE="background: #C0C0C0">
# </FORM>
# <P>
# $gmframebottom
# 
# </BODY>
# </HTML>
# 
# GMEDITSELECTEDAUTHORBOTTOM
# 
# exit;

	$page .= '<tr><th>&nbsp</th><td><INPUT TYPE=HIDDEN NAME="section" VALUE="'.$IN{'section'}.'">'.
		'<input type="submit" class="button" name="update" '.
		'style="background: #D0FFD0" value="'.Gm_Core::text( Gm_Constants::AUTHORS_SAVE_CHANGES ).
		'"></td></tr></table><br /></form>';
		
	$page .= '<FORM ACTION="gm.cgi" METHOD=POST> '.Gm_Security::getFormAuth( author=>\%AUTHOR ).
		'<p><input type="submit" class="button" name="authors" '.
		'value="Return To Author Panel'.
		'" style="background: #C0C0C0"></p><p><INPUT TYPE=SUBMIT CLASS="button" NAME="thomas" '.
		'value="'.Gm_Core::text( Gm_Constants::RETURN_MAIN_MENU ).
		'" style="background: #C0C0C0"></p></FORM><br />';
	## NAVIGATION SHOULD BE DE-BUTTONED
	
	Gm_Web::displayAdminPageExit( $page );
	exit(0);

}


## Update Author
# updates a given author
# RETURNS: A message to display on the view page
## NOTE: should part of this be generized and put in Core?  Something that doesn't presume where its being
# called from so it can be reused with normal user self-registration?
# ALSO:  can this and addAuthor be abstracted to reduce duplicate error checking?
sub updateAuthor {
	my $message = Gm_Constants::EMPTY;
	
# &gm_validate;
# 
# if ($gmauthoraccess ne Gm_Constants::YES) {
# 	gm_writetocplog("$IN{'authorname'} attempted to modify an author ($IN{'authororiginalname'}) without authorization");
# 	$statusnote = qq(<B><FONT COLOR="#FF0000">You don't have access to delete authors.</FONT></B><P>);
# 	&gm_frontpage;
# }

	$IN{'editedname'} =~ s/\|//g;
	$IN{'editedpassword'} =~ s/\|//g;
	$IN{'editedemail'} =~ s/\|//g;
	$IN{'editedhomepage'} =~ s/\|//g;

# $IN{'editedname'} =~ s/^\s+//;
# $IN{'editedname'} =~ s/\s+$//;
# $IN{'editedpassword'} =~ s/^\s+//;
# $IN{'editedpassword'} =~ s/\s+$//;
	$IN{'editedname'} = Gm_Utils::trimFrontWs( $IN{'editedname'} );
	$IN{'editedname'} = Gm_Utils::trimBackWs( $IN{'editedname'} );
	$IN{'editedpassword'} = Gm_Utils::trimFrontWs( $IN{'editedpassword'} );
	$IN{'editedpassword'} = Gm_Utils::trimBackWs( $IN{'editedpassword'} );

## TODO: NAME AND PASSWORD REQUIREMENTS SHOULD BE SAME AS WHEN ADDING, ALSO, LET SOME NON-ALPHANUMS FOR PW

	if (($IN{'editedname'} eq Gm_Constants::EMPTY) || ($IN{'editedpassword'} eq Gm_Constants::EMPTY)) {
# 		$statusnote = qq(<B><FONT COLOR="#FF0000">You left either the name or password fields blank.  Please try again.</FONT></B><P>);
# 		&gm_editauthors;
		## TODO: we should be returning this in a hash { error=>@arry of errors, msg=>@array of messages)
		# then can decide if get errors back, whether to goto list or single view
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_ENTER_NAME_PW ).'</span>';
		viewAuthor( $message );
	}

	my $gmauthors = Gm_Storage::getAuthors( errHandler=>\&Gm_Web::displayAdminErrorExit );

	if( ($IN{'selectedauthor'} ne $IN{'editedname'}) && 
			( exists( $gmauthors->{$IN{'editedname'}} )) ){ 
#		gm_writetocplog("$IN{'authorname'} attempted to change to duplicate of $IN{'editedname'} via $IN{'authororiginalname'}");
		my $cpMsg = Gm_Core::text( Gm_Constants::AUTHORS_OVERWRITE_LOG, { AUTHOR=>$AUTHOR{'author'}, 
			NEWNAME=>$IN{'editedname'}, NAME=>$IN{'selectedauthor'} } );
		Gm_Core::writeToCplog( $cpMsg );
		$message = '<span class="error_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_OVERWRITE_NAME ).'</span>';
		viewAuthor( $message );
	}


# TODO: THIS IN{AUTHORNAME} SHOULD BE AUTHOR{NAME} OR SOMETHING

	if( ($IN{'editedname'} ne $IN{'selectedauthor'}) ){
# 		if ($AUTHOR{'author'} eq $IN{'selectedauthor'}) {
# 			Gm_Core::writeToCplog("$AUTHOR{'author'} changed his/her own name to $IN{'editedname'}");
# 		} else {
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::AUTHORS_NEWNAME_LOG, { AUTHOR=>$AUTHOR{'author'}, 
			NEWNAME=>$IN{'editedname'}, NAME=>$IN{'selectedauthor'} } ) );
# 		}
	}

# 	$temphomepageprefix = substr($IN{'editedhomepage'}, 0, 7);
# 	if ($temphomepageprefix ne "http://") { 
# 		$IN{'editedhomepage'} = "http://$IN{'editedhomepage'}"; 
# 	}
	if( $IN{'editedhomepage'} !~ m/^http/i ){ 
		# If it doesn't start with http, lets add it for them
		$IN{'editedhomepage'} = "http://$IN{'editedhomepage'}"; 
	}
	if( $IN{'editedhomepage'} eq 'http://' ){ 
		$IN{'editedhomepage'} = Gm_Constants::EMPTY; 
	}

	my $selectedauthor = $gmauthors->{$IN{'selectedauthor'}};
	my %updatedInfo = ();

	if( $IN{'editedname'} ne $selectedauthor->{'author'}){
		$updatedInfo{'author'} = $IN{'editedname'};
	}

	if( $IN{'editedpassword'} ne $selectedauthor->{'password'}){
		## TODO: THIS SHOULD BE A SECURITY FUNCTION.  
		$updatedInfo{'password'} = crypt($IN{'editedpassword'},$IN{'editedpassword'});
	}
	
	if( $IN{'editedemail'} ne $selectedauthor->{'email'}){
		$updatedInfo{'email'} = $IN{'editedemail'};
	}
	
	if( $IN{'editedhomepage'} ne $selectedauthor->{'homepage'}){
		$updatedInfo{'homepage'} = $IN{'editedhomepage'};
	}
	
	if( $IN{'editedentryaccess'} ne $selectedauthor->{'postnew'}){
		$updatedInfo{'postnew'} = $IN{'editedentryaccess'};
	}
	
	if( $IN{'editedentryeditaccess'} ne $selectedauthor->{'editentries'}){
		$updatedInfo{'editentries'} = $IN{'editedentryeditaccess'};
	}
	
	if( $IN{'editedconfigureaccess'} ne $selectedauthor->{'editconfigs'}){
		$updatedInfo{'editconfigs'} = $IN{'editedconfigureaccess'};
	}
	
	if( $IN{'editedtemplateaccess'} ne $selectedauthor->{'edittemplates'}){
		$updatedInfo{'edittemplates'} = $IN{'editedtemplateaccess'};
	}
	
	if( $IN{'editedauthoraccess'} ne $selectedauthor->{'editauthors'}){
		$updatedInfo{'editauthors'} = $IN{'editedauthoraccess'};
	}
	
	if( $IN{'editedrebuildaccess'} ne $selectedauthor->{'rebuild'}){
		$updatedInfo{'rebuild'} = $IN{'editedrebuildaccess'};
	}
	
	if( $IN{'editedcplogaccess'} ne $selectedauthor->{'viewcplog'}){
		$updatedInfo{'viewcplog'} = $IN{'editedcplogaccess'};
	}
	
	if( $IN{'editedbookmarkletaccess'} ne $selectedauthor->{'bookmarklets'}){
		$updatedInfo{'bookmarklets'} = $IN{'editedbookmarkletaccess'};
	}
	
	if( $IN{'editeduploadaccess'} ne $selectedauthor->{'upload'}){
		$updatedInfo{'upload'} = $IN{'editeduploadaccess'};
	}
	
	if( $IN{'editedloginaccess'} ne $selectedauthor->{'viewadmin'}){
		$updatedInfo{'viewadmin'} = $IN{'editedloginaccess'};
	}

	if( scalar( keys( %updatedInfo )) < 1 ){
		# hmm, no updates submitted
		$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_NO_CHANGES, 
			{ NAME=>selectedauthor->{'author'} } ).'</span><p>';
	} else {
		Gm_Storage::updateAuthor( key=>$selectedauthor->{'author'}, %updatedInfo, 
			errHandler=>\&Gm_Web::displayAdminErrorExit );
		
		if ($IN{'selectedauthor'} eq $AUTHOR{'author'}) {
			$AUTHOR{'author'} = $IN{'editedname'};
			$AUTHOR{'password'} = $IN{'editedpassword'};
		}
		
# 		if ($AUTHOR{'author'} eq $IN{'editedname'}) {
# 			Gm_Core::writeToCplog( "$AUTHOR{'author'} edited his/her own info/access" );
# 		} else {
		Gm_Core::writeToCplog( Gm_Core::text( Gm_Constants::AUTHORS_EDIT_LOG, 
			{ AUTHOR=>$AUTHOR{'author'}, NAME=>$IN{'editedname'} } )  );
# 		}
		
#		$message = qq(<B><FONT COLOR="#0000FF">$IN{'editedname'}'s info/access has been edited.</FONT></B><P>);
		$message = '<span class="status_msg">'.Gm_Core::text( Gm_Constants::AUTHORS_EDIT_CONFIRM, 
			{ NAME=>$IN{'editedname'} } ).'</span><p>';
	}

#&gm_editauthors;
	## we are just adding, no control flow
	return( $message );
}




