<?vsp
--
--  $Id$
--
--  This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
--  project.
--
--  Copyright (C) 1998-2018 OpenLink Software
--
--  This project is free software; you can redistribute it and/or modify it
--  under the terms of the GNU General Public License as published by the
--  Free Software Foundation; only version 2 of the License, dated June 1991.
--
--  This program is distributed in the hope that it will be useful, but
--  WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
--  General Public License for more details.
--
--  You should have received a copy of the GNU General Public License along
--  with this program; if not, write to the Free Software Foundation, Inc.,
--  51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
--
--
 adm_pre_page(lines);

  declare step_t, _ns_id, _server, _port, _user, _pass, _srv_name varchar;
  declare serv, _nm_id, del_srv varchar;
  declare _u_id, _expand integer;
  declare own varchar;
  declare action_info varchar;
  declare nn_port integer;

  _u_id := db.dba.adm_dav_check_auth (lines, 1);
  if (_u_id < 1)
    {
      http_request_status ('HTTP/1.1 401 Unauthorized');
      http ( concat ('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">',
            '<HTML><HEAD>',
            '<TITLE>401 Unauthorized</TITLE>',
            '</HEAD><BODY><H1>Unauthorized</H1>',
            'Access to page is forbidden.</BODY></HTML>'));
      return (0);
    }
  else
    select U_NAME into own from WS.WS.SYS_DAV_USER where U_ID = _u_id;

  serv := atoi (get_keyword ('serv', params, ''));
  step_t := get_keyword ('step_t', params, '');
  _expand := atoi(get_keyword('expand', params, '0'));


  if ('' <> get_keyword ('nn_port_sub', params, ''))
    {
      nn_port := atoi(get_keyword('nn_port_val', params));
    }

  if ('' <> get_keyword ('btn_remove_confirmed', params, ''))
    {
      del_srv := atoi (get_keyword ('remove_id', params, ''));
      DB.DBA.vt_batch_update ('DB.DBA.NEWS_MSG', 'OFF', 0);
      for (select NG_GROUP, NG_NAME from DB.DBA.NEWS_GROUPS where NG_SERVER = del_srv) do
	{
--	   delete from DB.DBA.SYS_SCHEDULED_EVENT
--	     where SE_NAME = concat ('UPDATE_NEWSGROUP_', cast (NG_NAME as varchar));
	   whenever not found goto nf;
	   declare cr cursor for select NM_KEY_ID from DB.DBA.NEWS_MULTI_MSG where NM_GROUP = NG_GROUP;
	   open cr (exclusive, prefetch 1);
	   while (1)
	     {
	       fetch cr into _nm_id;
	       delete from DB.DBA.NEWS_MULTI_MSG where NM_KEY_ID = _nm_id;
	       delete from DB.DBA.NEWS_MSG where NM_ID = _nm_id;
	     }
	   nf:
	   close cr;
	   commit work;
	}
      delete from DB.DBA.NEWS_GROUPS where NG_SERVER = del_srv;
      delete from DB.DBA.NEWS_SERVERS where NS_ID = del_srv;
      DB.DBA.vt_batch_update ('DB.DBA.NEWS_MSG', 'ON', 0);

      action_info := concat('<TR><TD CLASS="statdata">Server ',get_keyword ('_rmv_address', params, ''),' removed.</TD></TR>');

    }

  if ('' <> get_keyword ('save', params, ''))
    update DB.DBA.NEWS_SERVERS set
	NS_PORT = atoi (get_keyword ('port', params, '')),
	NS_USER = get_keyword ('user', params, ''),
	NS_PASS = get_keyword ('pass', params, '')
	where NS_ID = atoi (get_keyword ('server_id', params, ''));
?>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="<?=adm_what_css()?>">
    <title>NNTP Administration</title>
    <meta name="AUTHOR" content="OpenLink Software">
    <meta name="DESCRIPTION" content="Virtuoso News Server Administration pages">
  </head>
<?vsp adm_page_header('NNTP Server Administration', 'nntpadminsvr'); ?>
<?include ../adm_js_check.vsp ?>
<?vsp

declare prop_of, _serverid integer;

action_info := '';

-- ngprops saved
	if ('' <> get_keyword ('ngproperties', params, ''))
	{
		update DB.DBA.NEWS_GROUPS set
			NG_UP_INT = atoi(get_keyword('ngupint',params, '30')),
			NG_PASS = atoi(get_keyword('ngupmess',params, '30'))
		where NG_GROUP = atoi(get_keyword('ngproperties',params, '30'));

		action_info := concat(action_info, '<TR><TD CLASS="statdata">Properties saved for ',get_keyword('ngprop_name', params, ''),' newsgroup.</TD></TR>');
	}

-- remove group
	if ('' <> get_keyword ('ngremove', params, ''))
	{
	        declare _ng_g_id integer;
		declare _nm_m_id varchar;
	        _ng_g_id := atoi(get_keyword('ngremove',params, ''));
		delete from DB.DBA.NEWS_GROUPS
		where NG_GROUP = _ng_g_id;
                declare nmc cursor for select NM_KEY_ID from DB.DBA.NEWS_MULTI_MSG where NM_GROUP = _ng_g_id;
--                DB.DBA.vt_batch_update ('DB.DBA.NEWS_MSG', 'ON', 0);
		whenever not found goto endf;
		open nmc (exclusive, prefetch 1);
		while (1)
		  {
		    fetch nmc into _nm_m_id;
		    delete from DB.DBA.NEWS_MULTI_MSG where current of nmc;
		    if (not exists (select 1 from DB.DBA.NEWS_MULTI_MSG where NM_KEY_ID = _nm_m_id))
		      delete from DB.DBA.NEWS_MSG where NM_ID = _nm_m_id;
		  }
endf:
		close nmc;
--		DB.DBA.vt_batch_update ('DB.DBA.NEWS_MSG', 'OFF', 0);
		commit work;
--		DB.DBA.vt_inc_index_DB_DBA_NEWS_MSG ();

		action_info := concat(action_info, '<TR><TD CLASS="statdata">Newsgroup removed.</TD></TR>');
	}

-- apply changes to server
	if ('' <> get_keyword ('btn_apply', params, ''))
	{
		-- updating record
		update DB.DBA.NEWS_SERVERS set
			NS_SERVER = get_keyword ('_prop_address', params, ''),
			NS_PORT = atoi (get_keyword ('_prop_port', params, '')),
			NS_USER = get_keyword ('_prop_user', params, ''),
			NS_PASS = get_keyword ('_prop_pass', params, '')
			where NS_ID = atoi (get_keyword ('serverid', params, ''));

		action_info := concat(action_info, '<TR><TD CLASS="statdata">',get_keyword ('_prop_address', params, ''),' server details updated.</TD></TR>');
	}

-- apply new server details
	if ( '' <> get_keyword('btn_addapply', params, ''))
	{
		if (NOT EXISTS(select "NS_SERVER" FROM "DB"."DBA"."NEWS_SERVERS" where NS_SERVER = get_keyword('_add_address', params, '')))
		{
		  	declare n_ns_name varchar;
			_serverid := get_keyword ('serverid', params, '');
			n_ns_name := trim (get_keyword ('_add_address', params, ''));

			-- adding record
			if (n_ns_name <> '')
			  {
			     insert into DB.DBA.NEWS_SERVERS (NS_SERVER, NS_PORT, NS_USER, NS_PASS)
				values (get_keyword ('_add_address', params, ''), atoi (get_keyword ('_add_port', params, '')),
				get_keyword ('_add_user', params, ''), get_keyword ('_add_pass', params, ''));

			action_info := concat(action_info, '<TR><TD CLASS="statdata">New server reference defined for: ',get_keyword ('_add_address', params, ''),'.</TD></TR>');
			  }
			else
			  {
			     action_info := concat(action_info, '<TR><TD CLASS="statdata">The news server address is empty.</TD></TR>');
			  }
		}

	}

-- start updating a group
	if ('' <> get_keyword('ngupdate', params, ''))
	{
		declare _ngupdate, new_news integer;
		declare state, msg, meta any;
		state := '00000';
		_ngupdate := atoi(get_keyword('ngupdate', params, ''));
--		new_news := new_news(_ngupdate);
		exec ('select new_news (?)', state, msg, vector (_ngupdate), 100, meta, new_news);

		if (state = '00000')
		  {
		     new_news := aref (aref (new_news, 0), 0);
		     action_info := concat(action_info, '<TR><TD CLASS="statdata">Newsgroup updated, ',
		        cast(coalesce(new_news,0) as varchar),' messages retrieved.</TD></TR>');
		  }
		else
		  action_info := concat(action_info, '<TR><TD CLASS="statdata">Error:', msg, '</TD></TR>');
	}

-- start updating selected groups
	if ('' <> get_keyword('updateselected', params, ''))
	{
		_expand := atoi(get_keyword('updateselected', params, ''));
		declare idx, current_item_id, new_news, new_newst integer;
		declare current_item varchar;

		new_news := 0;
		new_newst := 0;
		idx := 0;

		while (idx < length(params))
		{
		   declare state, msg, meta any;
		   current_item := aref(params, idx);
		   if ('CH_' = left(current_item, 3))
		     {
		        current_item_id := atoi(ltrim(current_item, 'CH_'));
			state := '00000';
			exec ('select new_news (?)', state, msg, vector (current_item_id), 100, meta, new_newst);
			if (state = '00000')
			  {
			     new_news := new_news + aref (aref (new_newst, 0), 0);
			  }
			else
			  {
			     action_info := concat(action_info, '<TR><TD CLASS="statdata">Error:',
				msg, '</TD></TR>');
			     idx:= length(params);
			     goto end_loop;
			  }
		     }
		   idx := idx + 2;
		}
		action_info := concat(action_info, '<TR><TD CLASS="statdata">Newsgroup(s) updated.  ',cast(new_news as varchar),' total message retrieved.</TD></TR>');
end_loop:;
	}

-- do main newsgroup status page

if ('' <> action_info)
{
	http('<TABLE CLASS="genlist" BORDER="0" CELLPADDING="2" CELLSPACING="0"><TR><TD CLASS="statlistheadt">Status:</TD></TR>');
	http(action_info);
	http('</TABLE><BR />');
}
	http('<TABLE BORDER="0" CELLPADDING="2" CELLSPACING="0">');
		if (0 = cfg_item_value (virtuoso_ini_path(),'HTTPServer','NewsServerPort'))
                  {


		if ('' <> get_keyword ('nn_port_sub', params, ''))
		  {
	            cfg_write (virtuoso_ini_path(), 'HTTPServer', 'NewsServerPort', cast (nn_port as varchar));
		    http (sprintf ('<TR><TD CLASS="statdata">NewsServerPort = %i  is added to Virtuoso.ini</TD></TR><TR><TD CLASS="statdata">You must restart Virtuoso server for the changes to take effect</TD></TR>', nn_port));
		  }
		else
		  {
		    http('<TR><TD ALIGN="left" VALIGN="top" COLSPAN="1" WIDTH="450px"><p><b>Warning:&nbsp;</b><b class="status_err">The NNTP server is stopped.</b><br /><small> To enable it, enter the NNTP port and then press \'Enable NNTP\'. Restart the Virtuoso server.</small></p>');
		    http('</TD><TD COLSPAN="2">&nbsp;</TD></TR>');
		    http('<TR><FORM method="POST" action="news_server_list.vsp"><TD>NNTP port:<INPUT type="text" name="nn_port_val" value="1235" size="4">&nbsp;');
		    http('<INPUT type="submit" name="nn_port_sub" value="Enable NNTP"></TD></FORM></TR>');
		  }
		  }

	declare str_srv, str_name varchar;

  -- first do localhost which is special NULL case in news_groups

		http('<TR><TD ALIGN="left" VALIGN="top">');
		http('<TABLE CLASS="genlist" CELLPADDING="0" CELLSPACING="2" BORDER="0">');

		if ('localhost' = get_keyword('expand', params, ''))
			http('<TR><TD><A HREF="news_server_list.vsp#localhost"><IMG BORDER="0" src="../images/minus.jpg" /></A></TD><TD CLASS="genhead" WIDTH="450px" COLSPAN="4"><A NAME="localhost"> Local Virtuoso Server</A></TD>');
		else
			http('<TR><TD><A HREF="news_server_list.vsp?expand=localhost#localhost"><IMG BORDER="0" src="../images/plus.jpg" /></A></TD><TD CLASS="genhead" WIDTH="450px" COLSPAN="4"><A NAME="localhost"> Local Virtuoso Server</A></TD>');

		http('</TR>');
		http('\r\n<TR><TD CLASS="AdmBorders" COLSPAN="5"><IMG SRC="../images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR>');

if ('localhost' = get_keyword('expand',params,''))
{
		http('<TR><TD CLASS="genlistheadt">&nbsp</TD>');
		http('<TD CLASS="genlistheadt">Newsgroup Name</TD>');
		http('<TD CLASS="genlistheadt">Msgs</TD>');
		http('<TD CLASS="genlistheadt">Actions</TD>');
		http('</TR>');

			for (SELECT NG_GROUP, NG_NAME, NG_DESC, NG_UP_TIME, NG_UP_INT, NG_CLEAR_INT,
				NG_STAT, NG_UP_MESS, NG_NUM FROM DB.DBA.NEWS_GROUPS
				WHERE NG_SERVER IS NULL ORDER BY NG_GROUP) do
			{
			  	ns_up_num (NG_GROUP);
				str_name := coalesce(NG_NAME, '');
				if (length(str_name) > 40) {str_name := concat(substring(str_name, 1, 35), '...'); }
				http(sprintf('<TR TITLE="%s - \n %s\nLast Updated:%s\nUpdate Interval: %d minutes\nClear Interval: %d days"><TD><INPUT type="hidden" name="CH_%i"></TD><TD CLASS="gendata"><A HREF="news_frames.vsp?Group=%i">%s</A></TD>',
					coalesce(NG_NAME, ''), coalesce(NG_DESC, ''), coalesce(CAST (NG_UP_TIME AS VARCHAR), '0'),
					coalesce(NG_UP_INT, 0), coalesce(NG_CLEAR_INT, 0), NG_GROUP, NG_GROUP, str_name));
				http(sprintf('<TD CLASS="gendata">%i</TD>', coalesce(NG_NUM, 0)));
				http(sprintf('<TD CLASS="gendata"><A CLASS="tablelistaction" HREF="news_server_list.vsp?ngremove=%i&expand=localhost">Remove</A></TD></TR>', NG_GROUP));
				http('</TR>');
			}

		http(sprintf('<TR><TD>&nbsp;</TD><TD CLASS="gendata" ALIGN="right"><A CLASS="tablelistaction" HREF="newsgroups_add.vsp?sel_serv=%s">Add Newsgroups</A></TD>', 'localhost'));
		http('<TD COLSPAN="3" CLASS="gendata">&nbsp;</TD></TR>');
}
		http('</TABLE></TD><TD COLSPAN="2">&nbsp;</TD></TR><TR><TD COLSPAN="3">&nbsp;</TD></TR>');

  -- get list of remote servers
	http('<FORM NAME="group_detail" METHOD="POST" ACTION="news_server_list.vsp">');

	for (SELECT NS_ID, NS_SERVER, NS_PORT, NS_USER, NS_PASS FROM DB.DBA.NEWS_SERVERS WHERE NS_ID IS NOT NULL ORDER BY NS_ID) do
	{
		http('<TR><TD ALIGN="left" VALIGN="top">');
		http('<TABLE CLASS="genlist" CELLPADDING="0" CELLSPACING="2" BORDER="0">');

		str_srv := cast(NS_SERVER as varchar);  -- casting in case an integer gets in there
		if (coalesce(NS_PORT, -1) <> -1) str_srv := sprintf('%s:%i', str_srv, NS_PORT);
		if (coalesce(NS_USER, '') <> '') str_srv := sprintf('%s (User: %s)', str_srv, NS_USER);

if (_expand = NS_ID)
		http(sprintf('<TR><TD><A HREF="news_server_list.vsp#%i"><IMG SRC="../images/minus.jpg" BORDER="0" /></TD><TD CLASS="genhead" WIDTH="450px" COLSPAN="4"><A NAME="%i">%s</A></TD>', NS_ID, NS_ID, str_srv));
else
		http(sprintf('<TR><TD><A HREF="news_server_list.vsp?expand=%i#%i"><IMG SRC="../images/plus.jpg" BORDER="0" /></A></TD><TD CLASS="genhead" WIDTH="450px" COLSPAN="4"><A NAME="%i">%s</A></TD>', NS_ID, NS_ID, NS_ID, str_srv));

		http(sprintf('\r\n<TD CLASS="genlistheadt"><A CLASS="tablelistaction" HREF="#" onClick="window.open (\'news_available_update_frame.vsp?nsupdate=%i&serv_name=%s\', \'window\', \'scrollbars=no, menubar=no, height=400, width=500 \');">Update</A></TD>', NS_ID, str_srv));
		http(sprintf('\r\n<TD CLASS="genlistheadt"><A CLASS="tablelistaction" HREF="news_server_config.vsp?nsproperties=%i">Properties</A></TD>', NS_ID));
		http(sprintf('\r\n<TD CLASS="genlistheadt"><A CLASS="tablelistaction" HREF="news_server_config.vsp?nsremove=%i">Remove</A></TD></TR>', NS_ID));

		http('\r\n<TR><TD CLASS="admborders" COLSPAN="8"><IMG SRC="../images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR>');

  -- get list of newsgroups for particular server

if (_expand = NS_ID)
{
		http('<TR><TD CLASS="genlistheadt">&nbsp;</TD>');
		http('<TD CLASS="genlistheadt">Newsgroup Name</TD>');
		http('<TD CLASS="genlistheadt">Msgs</TD>');
		http('<TD CLASS="genlistheadt" TITLE="Last Transfer Set">LTS</TD>');
		http('<TD CLASS="genlistheadt">Status</TD>');
		http('<TD CLASS="genlistheadt" COLSPAN="3">Actions</TD></TR>');

		IF ('localhost' <> NS_SERVER)
			for (SELECT NG_GROUP, NG_NAME, NG_DESC, NG_UP_TIME, NG_UP_INT, NG_CLEAR_INT,
				NG_STAT, NG_UP_MESS, NG_NUM FROM DB.DBA.NEWS_GROUPS
				WHERE NG_SERVER=NS_ID ORDER BY NG_GROUP) do
			{
				str_name := coalesce(NG_NAME, '');
				if (length(str_name) > 40) {str_name := concat(substring(str_name, 1, 35), '...'); }
				http(sprintf('<TR TITLE="%s - \n %s\nLast Updated:%s\nUpdate Interval: %d minutes\nClear Interval: %d days"><TD><INPUT type="checkbox" name="CH_%i"></TD><TD CLASS="gendata"><A HREF="news_frames.vsp?Group=%i">%s</A></TD>',
					coalesce(NG_NAME, ''), coalesce(NG_DESC, ''), coalesce(CAST (NG_UP_TIME AS VARCHAR), 0),
					coalesce(NG_UP_INT, 0), coalesce(NG_CLEAR_INT, 0), NG_GROUP, NG_GROUP, str_name));
				http(sprintf('<TD CLASS="gendata">%i</TD>', coalesce(NG_NUM, 0)));
				http(sprintf('<TD CLASS="gendata">%i</TD>', coalesce(NG_UP_MESS, 0)));
				http(sprintf('<TD CLASS="gendata">%s</TD>', adm_news_status(NG_STAT)));
				http(sprintf('<TD CLASS="gendata"><A CLASS="tablelistaction" HREF="news_server_list.vsp?ngupdate=%i&expand=%i">Update</A></TD>', NG_GROUP, NS_ID));
				http(sprintf('<TD CLASS="gendata"><A CLASS="tablelistaction" HREF="news_group_detail.vsp?ngproperties=%i&expand=%i">Properties</A></TD>', NG_GROUP, NS_ID));
				http(sprintf('<TD CLASS="gendata"><A CLASS="tablelistaction" HREF="news_server_list.vsp?ngremove=%i&expand=%i">Remove</A></TD></TR>', NG_GROUP, NS_ID));
			}

		http(sprintf('<TR><TD>&nbsp;</TD><TD CLASS="gendata" ALIGN="right"><A CLASS="tablelistaction" HREF="newsgroups_add.vsp?sel_serv=%s">Add Newsgroups</A></TD>', NS_SERVER));
		http(sprintf('<TD COLSPAN="3" CLASS="gendata">&nbsp;</TD><TD CLASS="gendata" COLSPAN="3"><INPUT TYPE="hidden" NAME="updateselected" VALUE="%i" /><A CLASS="tablelistaction" onClick="javascript:document.group_detail.submit();" HREF="#">Update Selected</A></TD></TR>', NS_ID));

		declare _total, _updating, _completed, _current_server integer;
		_current_server := NS_ID;
		SET ISOLATION = 'uncommitted';
		if (exists(select 1 from "DB"."DBA"."NEWS_GROUPS_AVAILABLE"
			where "UPDATED" = 'N' AND "NS_ID" = _current_server AND "NS_ID" IS NOT NULL))
		{
			http('<TR><TD COLSPAN="8" CLASS="genlistheadt">');
			select count("NAME") into _updating from "DB"."DBA"."NEWS_GROUPS_AVAILABLE" where "UPDATED" = 'Y' AND "NS_ID" = _current_server;
			select count("NAME") into _total from "DB"."DBA"."NEWS_GROUPS_AVAILABLE" where "NS_ID" = _current_server;
			_updating := coalesce (_updating, 0);
			_total := coalesce (_total, 0);
			if (_total = 0) _completed := 100; else _completed := cast(coalesce(((cast(_updating as decimal)/ _total)*100), 100) as integer);
			http(sprintf('Currently updating available newsgroups list, %i%% (%i of %i) complete',_completed, _updating, _total));
			http('</TD></TR>');
		}
		if ((select "SE_LAST_COMPLETED" from "DB"."DBA"."SYS_SCHEDULED_EVENT"
			where "SE_NAME" = concat('UPD_Avail_Grps_', NS_SERVER)) is NULL)
		{
			select count(A."NS_ID") into _total FROM "DB"."DBA"."NEWS_GROUPS_AVAILABLE" as A WHERE "NS_ID" = _current_server;
			http(sprintf('<TR><TD COLSPAN="8" CLASS="genlistheadt">Waiting to fetch list of groups... %i so far.', coalesce(_total, 0)));
		}

}
		http('</TABLE></TD><TD COLSPAN="2">&nbsp;</TD></TR><TR><TD COLSPAN="3">&nbsp;</TD></TR>');
	}
?>
<TR><TD ALIGN="right"></FORM><FORM METHOD="POST" NAME="addserver" action="news_server_config.vsp"><INPUT type="submit" name="btn_addsrv", value="Add Remote News Server"></FORM></TD><TD COLSPAN="2">&nbsp;</TD></TR>
</TABLE>

<?vsp adm_page_footer(); ?>
</HTML>
