2023-09-03 16:32:21 +02:00
< ? php
/*
* This script allows importing a group . db3 file from a backup
* or another rslight site , and other features .
*
* Use - help to see other features .
*
* To import a group db3 file :
* Place the article database file group . name - articles . db3 in
* your spool directory , and change user / group to your web user .
2024-07-02 08:50:31 +02:00
* Run this script as your web user :
2023-09-22 12:48:43 +02:00
* php $config_dir / scripts / maintenance - import group . name
2023-09-03 16:32:21 +02:00
*
* This will create the overview files necessary to import the group
* into your site .
* Next : Add the group to the groups . txt file of the section you wish
* it to appear :
* $config_dir /< section >/ groups . txt
*/
2024-10-03 14:13:03 +02:00
include ( " paths.inc.php " );
2024-07-01 11:12:12 +02:00
chdir ( $spoolnews_path );
2023-09-03 16:32:21 +02:00
include " config.inc.php " ;
2024-10-03 14:13:03 +02:00
include ( " $file_newsportal " );
2024-11-15 16:13:10 +01:00
include " spool-lib.php " ;
2023-09-03 16:32:21 +02:00
2024-11-15 00:38:09 +01:00
if ( ! isset ( $argv [ 1 ])) {
$argv [ 1 ] = " -help " ;
}
2024-10-03 14:13:03 +02:00
if ( $argv [ 1 ] != '-newsection' ) {
// Change to webserver user if root
$uinfo = posix_getpwnam ( $CONFIG [ 'webserver_user' ]);
/* Change to non root user */
change_identity ( $uinfo [ " uid " ], $uinfo [ " gid " ]);
$processUser = posix_getpwuid ( posix_geteuid ());
if ( $processUser [ 'name' ] != $CONFIG [ 'webserver_user' ]) {
echo " You are running as: " . $processUser [ 'name' ] . " \n " ;
echo 'Please run this scripts as: ' . $CONFIG [ 'webserver_user' ] . " \n " ;
exit ();
}
/* Everything below runs as $CONFIG['webserver_user'] */
2024-11-15 16:13:10 +01:00
echo " You are running as user: " . $processUser [ 'name' ] . " \n " ;
2024-07-26 17:31:40 +02:00
2024-10-03 14:13:03 +02:00
$processUser = posix_getpwuid ( posix_geteuid ());
if ( $processUser [ 'name' ] != $CONFIG [ 'webserver_user' ]) {
echo " You are running as: " . $processUser [ 'name' ] . " \n " ;
echo 'Please run this scripts as: ' . $CONFIG [ 'webserver_user' ] . " \n " ;
exit ();
}
2024-07-01 11:12:12 +02:00
2024-10-03 14:13:03 +02:00
$logfile = $logdir . '/import.log' ;
2023-09-03 16:32:21 +02:00
2024-10-03 14:13:03 +02:00
$lockfile = $lockdir . '/' . $config_name . '-spoolnews.lock' ;
2023-09-17 14:56:24 +02:00
2024-10-03 14:13:03 +02:00
$pid = file_get_contents ( $lockfile );
if ( posix_getsid ( $pid ) === false || ! is_file ( $lockfile )) {
print " Starting Import... \n " ;
file_put_contents ( $lockfile , getmypid ()); // create lockfile
} else {
print " Import currently running \n " ;
exit ();
}
2023-09-03 16:32:21 +02:00
}
if ( $argv [ 1 ][ 0 ] == '-' ) {
switch ( $argv [ 1 ]) {
case " -version " :
echo 'Version ' . $rslight_version . " \n " ;
break ;
2024-11-15 16:13:10 +01:00
case " -clear-diskcache " :
clear_disk_cache ();
break ;
case " -refill " :
if ( ! isset ( $argv [ 2 ]) || ! isset ( $argv [ 3 ])) {
echo " Please provide a group name followed by number of articles to poll \n " ;
exit ;
}
echo " Refilling: " . $argv [ 2 ] . " going back " . $argv [ 3 ] . " articles \n " ;
refill_group ( $argv [ 2 ], $argv [ 3 ]);
break ;
2023-09-03 16:32:21 +02:00
case " -remove " :
echo " Removing: " . $argv [ 2 ] . " \n " ;
remove_articles ( $argv [ 2 ]);
reset_group ( $argv [ 2 ], 1 );
break ;
case " -reset " :
echo " Reset: " . $argv [ 2 ] . " \n " ;
remove_articles ( $argv [ 2 ]);
reset_group ( $argv [ 2 ], 0 );
break ;
2024-11-15 00:38:09 +01:00
case " -reset-section " :
if ( ! isset ( $argv [ 2 ])) {
echo " Please provide a section name \n " ;
exit ;
}
echo " Reset Section: " . $argv [ 2 ] . " \n " ;
reset_section ( $argv [ 2 ]);
break ;
2023-09-03 16:32:21 +02:00
case " -import " :
if ( isset ( $argv [ 2 ])) {
import ( $argv [ 2 ]);
} else {
import ();
}
break ;
2024-10-03 14:13:03 +02:00
case " -newsection " :
if ( ! isset ( $argv [ 2 ])) {
echo " Please provide a section name \n " ;
exit ;
}
echo " Creating section: " . $argv [ 2 ] . " \n " ;
echo create_section ( $argv [ 2 ]);
break ;
2023-09-03 16:32:21 +02:00
case " -clean " :
clean_spool ();
break ;
default :
echo " -help: This help page \n " ;
echo " -version: Display version \n " ;
2024-06-11 12:22:21 +02:00
echo " ******************* IMPORTANT ************************** \n " ;
echo " *** PLEASE DISABLE cron.php WHEN RUNNING THIS SCRIPT *** \n " ;
echo " ******************************************************** \n " ;
2023-09-03 16:32:21 +02:00
echo " -clean: Remove extraneous group db3 files \n " ;
2024-11-15 16:13:10 +01:00
echo " -clear-diskcache: Remove all cache files if using Disk Caching \n " ;
2023-09-03 16:32:21 +02:00
echo " -import: Import articles from a .db3 file (-import alt.test-articles) \n " ;
echo " You must first add group name to <config_dir>/<section>/groups.txt manually \n " ;
2024-10-03 14:13:03 +02:00
echo " -newsection: Create a new section for groups \n " ;
2024-11-15 16:13:10 +01:00
echo " -refill: Go back x articles and retrieve missing from remote server \n " ;
echo " -refill alt.test 3000 will retrive missing articles for alt.test \n " ;
echo " starting 3000 articles earlier than latest remote article number \n " ;
2023-09-03 16:32:21 +02:00
echo " -remove: Remove all data for a group (-remove alt.test) \n " ;
echo " You must also remove group name from <config_dir>/<section>/groups.txt manually \n " ;
echo " -reset: Reset a group to restart from zero messages (-reset alt.test) \n " ;
2024-11-15 00:38:09 +01:00
echo " -reset-section: Reset ALL GROUPS in a Section to restart from zero messages \n " ;
echo " (-reset-section rocksolid) THIS CAN TAKE A LOT OF TIME TO RUN \n " ;
2023-09-03 16:32:21 +02:00
break ;
}
exit ();
} else {
exit ();
}
2024-11-15 16:13:10 +01:00
function clear_disk_cache ()
{
global $config_dir ;
if ( file_exists ( $config_dir . '/cache.inc.php' )) {
include $config_dir . '/cache.inc.php' ;
} else {
echo " Disk Cache not configured in " . $config_dir . '/cache.inc.php' . " \n " ;
exit ;
}
if ( $enable_cache != 'diskcache' || ! isset ( $cache_dir )) {
echo " Disk Cache not configured in " . $config_dir . '/cache.inc.php' . " \n " ;
exit ;
}
echo " Clearing Disk Cache in " . $cache_dir . " \n " ;
foreach ( glob ( $cache_dir . " /* " ) as $filename ) {
if ( is_file ( $filename )) {
echo " Deleting " . $filename . " \n " ;
unlink ( $filename );
} else {
echo " NOT Deleting: " . $filename . " \n " ;
}
}
}
2024-10-03 14:13:03 +02:00
function create_section ( $section = false )
{
global $spooldir , $config_dir , $spoolnews_path , $CONFIG ;
$menufile = $config_dir . '/menu.conf' ;
if ( ! isset ( $section )) {
return " Please include a section name \n " ;
}
$uinfo = posix_getpwnam ( $CONFIG [ 'webserver_user' ]);
$spoolsection = $spooldir . '/' . $section ;
$configsection = $config_dir . '/' . $section ;
$websectionarray = explode ( '/' , $spoolnews_path );
$websectionpath = substr ( $spoolnews_path , 0 , strlen ( $spoolnews_path ) - 9 );
$websection = $websectionpath . $section ;
$websection = $websectionpath . '/' . $section ;
if ( ! file_exists ( $websection . '/newsportal.php' )) {
echo " Creating symlinks " . $websection . " \n " ;
mkdir ( $websection );
exec ( " ln -s " . $websectionpath . '/rocksolid/*' . ' ' . $websection );
}
if ( ! file_exists ( $configsection . '/groups.txt' )) {
mkdir ( $configsection );
echo 'Creating ' . $configsection . '/groups.txt' . " \n " ;
touch ( $configsection . '/groups.txt' );
}
$menuexists = false ;
$menudata = file ( $config_dir . '/menu.conf' );
2024-10-14 11:40:42 +02:00
$newmenu = array ();
2024-10-03 14:13:03 +02:00
foreach ( $menudata as $menuentry ) {
2024-11-15 16:13:10 +01:00
if ( trim ( $menuentry ) == '' ) {
2024-10-14 11:40:42 +02:00
continue ;
}
2024-10-03 14:13:03 +02:00
if ( strpos ( $menuentry , $section ) !== false ) {
2024-10-14 11:40:42 +02:00
echo " Menu entry already exists for: " . $section . " \n " ;
2024-10-03 14:13:03 +02:00
$menuexists = true ;
break ;
}
2024-10-14 11:40:42 +02:00
$newmenu [] = $menuentry ;
2024-10-03 14:13:03 +02:00
}
if ( ! $menuexists ) {
2024-10-14 11:40:42 +02:00
echo " Adding menu entry to " . $config_dir . " menu.conf \n " ;
2024-10-14 11:42:25 +02:00
$newmenu [] = $section . " :1:1 \n " ;
2024-10-14 11:40:42 +02:00
$newmenu = implode ( $newmenu );
file_put_contents ( $config_dir . 'menu.conf' , $newmenu );
2024-10-03 14:13:03 +02:00
}
echo 'Please now edit ' . $configsection . " /groups.txt to add groups to this section \n " ;
}
2023-09-03 16:32:21 +02:00
function clean_spool ()
{
global $logfile , $workpath , $spooldir ;
$workpath = $spooldir . " / " ;
$path = $workpath . " articles/ " ;
$group_list = get_group_list ();
$group = trim ( $group );
$group_files = scandir ( $workpath );
foreach ( $group_files as $this_file ) {
if ( strpos ( $this_file , '-articles.db3' ) === false ) {
continue ;
}
$group = preg_replace ( '/-articles.db3/' , '' , $this_file );
if ( in_array ( $group , $group_list )) {
continue ;
} else {
echo " Removing: " . $this_file . " \n " ;
remove_articles ( $group );
reset_group ( $group , 1 );
}
}
echo " \n Import Done \r \n " ;
}
function import ( $group = '' )
{
global $logfile , $workpath , $spooldir ;
$workpath = $spooldir . " / " ;
$path = $workpath . " articles/ " ;
$group_list = get_group_list ();
$group = trim ( $group );
if ( $group == '' ) {
$group_files = scandir ( $workpath );
foreach ( $group_files as $this_file ) {
if ( strpos ( $this_file , '-articles.db3' ) === false ) {
continue ;
}
$group = preg_replace ( '/-articles.db3/' , '' , $this_file );
if ( in_array ( $group , $group_list )) {
echo " Importing: " . $group . " \n " ;
import_articles ( $group );
} else {
echo " Removing: " . $group . " \n " ;
remove_articles ( $group );
reset_group ( $group , 1 );
}
}
} else {
echo " Importing: " . $group . " \n " ;
import_articles ( $group );
}
echo " \n Import Done \r \n " ;
}
function get_group_list ()
{
global $config_dir ;
$grouplist = array ();
$menulist = file ( $config_dir . " menu.conf " , FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
foreach ( $menulist as $menu ) {
if ( $menu [ 0 ] == '#' ) {
continue ;
}
$menuitem = explode ( ':' , $menu );
if ( $menuitem [ 2 ] == '0' ) {
continue ;
}
$glist = file ( $config_dir . $menuitem [ 0 ] . " /groups.txt " );
foreach ( $glist as $gl ) {
if ( $gl [ 0 ] == ':' ) {
continue ;
}
$group_name = preg_split ( " /( | \t )/ " , $gl , 2 );
$grouplist [] = trim ( $group_name [ 0 ]);
}
}
return $grouplist ;
}
2024-11-15 16:13:10 +01:00
function refill_group ( $group , $start )
{
global $spooldir , $config_dir , $remote_groups_array_file , $workpath , $CONFIG , $config_name , $path ;
$logfile = $spooldir . '/log/import.log' ;
$workpath = $spooldir . " / " ;
$path = $workpath . " articles/ " ;
$config_name = get_section_by_group ( $group );
if ( file_exists ( $config_dir . $config_name . '.inc.php' )) {
$config_file = $config_dir . $config_name . '.inc.php' ;
} else {
$config_file = $config_dir . 'rslight.inc.php' ;
}
$CONFIG = include ( $config_file );
$remote_groups_array_file = $spooldir . " / " . $config_name . " / " . $CONFIG [ 'remote_server' ] . " : " . $CONFIG [ 'remote_port' ] . " -remote_groups.dat " ;
if ( file_exists ( $remote_groups_array_file )) {
$remote_groups_array = unserialize ( file_get_contents ( $remote_groups_array_file ));
} else {
$remote_groups_array = array ();
}
foreach ( $remote_groups_array as $key => $value ) {
if ( $key == $group ) {
$newarray [ $key ] = $remote_groups_array [ $key ] - $start ;
} else {
$newarray [ $key ] = $remote_groups_array [ $key ];
}
}
file_put_contents ( $remote_groups_array_file , serialize ( $newarray ));
$ns = nntp2_open ( $CONFIG [ 'remote_server' ], $CONFIG [ 'remote_port' ]);
if ( $ns == false ) {
file_put_contents ( $logfile , " \n " . format_log_date () . " " . $config_name . " Failed to connect to " . $CONFIG [ 'remote_server' ] . " : " . $CONFIG [ 'remote_port' ], FILE_APPEND );
exit ();
}
echo " Finding missing articles from Remote Server for: " . $group . " starting - " . $start . " articles \n " ;
get_articles ( $ns , $group , $start );
}
function reset_section ( $section = " " )
{
2024-11-15 00:38:09 +01:00
global $config_dir ;
$section = trim ( $section );
$gldata = file ( $config_dir . $section . " /groups.txt " );
2024-11-15 16:13:10 +01:00
foreach ( $gldata as $gl ) {
if (( $gl [ 0 ] == ':' ) || ( trim ( $gl ) == " " )) {
continue ;
2024-11-15 00:38:09 +01:00
}
2024-11-15 16:13:10 +01:00
$group_name = preg_split ( " /( | \t )/ " , $gl , 2 );
$group = trim ( $group_name [ 0 ]);
echo " START Reset " . $group . " \n " ;
remove_articles ( $group );
reset_group ( $group , 0 );
}
2024-11-15 00:38:09 +01:00
}
2023-09-03 16:32:21 +02:00
function reset_group ( $group , $remove = 0 )
{
global $config_dir , $spooldir ;
$group = trim ( $group );
if ( ! $section = get_section_by_group ( $group )) {
return false ;
}
$config_location = $spooldir . '/' . $section ;
$config_files = array_diff ( scandir ( $config_location ), array (
'..' ,
2024-06-11 12:22:21 +02:00
'.' ,
'outgoing'
2023-09-03 16:32:21 +02:00
));
foreach ( $config_files as $config_file ) {
2024-10-08 13:57:01 +02:00
if ( ! str_ends_with ( $config_file , '_groups.dat' )) {
continue ;
}
$groups_array = unserialize ( file_get_contents ( $config_location . '/' . $config_file ));
if ( isset ( $groups_array [ $group ])) {
echo " Current group pointer for " . $group . " : " . $groups_array [ $group ] . " \n " ;
$groups_array [ $group ] = '1' ;
echo " New group pointer for " . $group . " : " . $groups_array [ $group ] . " \n " ;
2023-09-03 16:32:21 +02:00
}
2024-10-08 13:57:01 +02:00
file_put_contents ( $config_location . '/' . $config_file , serialize ( $groups_array ));
2023-09-03 16:32:21 +02:00
}
}
function remove_articles ( $group )
{
global $spooldir , $CONFIG , $workpath , $path , $config_name , $logfile ;
$group = trim ( $group );
# Overview
2024-06-11 12:22:21 +02:00
$overview_dbh = overview_db_open ( $spooldir . '/articles-overview.db3' );
2023-09-03 16:32:21 +02:00
2024-06-11 12:22:21 +02:00
$fetch_stmt = $overview_dbh -> prepare ( " SELECT msgid FROM overview WHERE newsgroup=:group " );
$fetch_stmt -> bindParam ( ':group' , $group );
$fetch_stmt -> execute ();
$del_array = array ();
while ( $row = $fetch_stmt -> fetch ()) {
if ( isset ( $row [ 'msgid' ])) {
$del_array [] = $row [ 'msgid' ];
}
}
$overview_dbh = null ;
2024-10-03 14:13:03 +02:00
foreach ( $del_array as $delme ) {
2024-06-11 12:22:21 +02:00
delete_message ( $delme , $group );
echo " Deleting " . $delme . " from " . $group . " \n " ;
}
2023-09-03 16:32:21 +02:00
2024-06-11 14:28:56 +02:00
# History
$history_dbh = history_db_open ( $spooldir . '/history.db3' );
$clear_stmt = $history_dbh -> prepare ( " DELETE FROM history WHERE newsgroup=:group " );
$clear_stmt -> bindParam ( ':group' , $group );
$clear_stmt -> execute ();
$history_dbh = null ;
2024-10-03 14:13:03 +02:00
2024-10-08 13:57:01 +02:00
@ rename ( $spooldir . '/' . $group . '-articles.db3' , $spooldir . '/' . $group . '-articles.db3-removed' );
@ unlink ( $spooldir . '/' . $group . '-data.db3' );
@ unlink ( $spooldir . '/' . $group . '-info.txt' );
@ unlink ( $spooldir . '/' . $group . '-cache.txt' );
@ unlink ( $spooldir . '/' . $group . '-lastarticleinfo.dat' );
@ unlink ( $spooldir . '/' . $group . '-overboard.dat' );
2023-09-03 16:32:21 +02:00
}
function import_articles ( $group )
{
global $spooldir , $CONFIG , $workpath , $path , $config_name , $logfile ;
# Prepare databases
// Overview db
$new_article_dbh = article_db_open ( $spooldir . '/' . $group . '-articles.db3-new' );
$new_article_sql = 'INSERT OR IGNORE INTO articles(newsgroup, number, msgid, date, name, subject, article, search_snippet) VALUES(?,?,?,?,?,?,?,?)' ;
$new_article_stmt = $new_article_dbh -> prepare ( $new_article_sql );
$database = $spooldir . '/articles-overview.db3' ;
$table = 'overview' ;
2023-11-15 12:55:08 +01:00
$overview_dbh = overview_db_open ( $database , $table );
$clear_stmt = $overview_dbh -> prepare ( " DELETE FROM overview WHERE newsgroup=:group " );
2023-09-03 16:32:21 +02:00
$clear_stmt -> bindParam ( ':group' , $group );
$clear_stmt -> execute ();
clear_history_by_group ( $group );
2023-11-15 12:55:08 +01:00
$overview_sql = 'INSERT OR IGNORE INTO overview(newsgroup, number, msgid, date, datestring, name, subject, refs, bytes, lines, xref) VALUES(?,?,?,?,?,?,?,?,?,?,?)' ;
$overview_stmt = $overview_dbh -> prepare ( $overview_sql );
2023-09-03 16:32:21 +02:00
// Incoming db
$article_dbh = article_db_open ( $spooldir . '/' . $group . '-articles.db3' );
$article_stmt = $article_dbh -> query ( 'SELECT DISTINCT * FROM articles' );
while ( $row = $article_stmt -> fetch ()) {
$local = $row [ 'number' ];
$this_article = preg_split ( " / \r \n | \n | \r / " , $row [ 'article' ]);
$lines = 0 ;
$bytes = 0 ;
$ref = 0 ;
$banned = 0 ;
$is_header = 1 ;
$body = " " ;
foreach ( $this_article as $response ) {
$bytes = $bytes + mb_strlen ( $response , '8bit' );
if ( trim ( $response ) == " " || $lines > 0 ) {
$is_header = 0 ;
2024-10-03 14:13:03 +02:00
$lines ++ ;
2023-09-03 16:32:21 +02:00
}
if ( $is_header == 1 ) {
$response = str_replace ( " \t " , " " , $response );
2024-01-03 22:57:27 +01:00
if ( strpos ( $response , ': ' ) !== false ) {
$ref = 0 ;
}
2023-09-03 16:32:21 +02:00
// Find article date
if ( stripos ( $response , " Date: " ) === 0 ) {
$finddate = explode ( ': ' , $response , 2 );
}
// Get overview data
$mid [ 1 ] = $row [ 'msgid' ];
$from [ 1 ] = $row [ 'name' ];
$subject [ 1 ] = $row [ 'subject' ];
$article_date = $row [ 'date' ];
if ( stripos ( $response , " Content-Type: " ) === 0 ) {
preg_match ( '/.*charset=.*/' , $response , $te );
2024-10-03 14:13:03 +02:00
if ( isset ( $te [ 0 ])) {
$content_type = explode ( " Content-Type: text/plain; charset= " , $te [ 0 ]);
}
2023-09-03 16:32:21 +02:00
}
if ( stripos ( $response , " References: " ) === 0 ) {
$this_references = explode ( 'References: ' , $response );
$references = $this_references [ 1 ];
$ref = 1 ;
}
2024-01-03 22:57:27 +01:00
if ( preg_match ( '/^\s/' , $response ) && $ref == 1 ) {
$references = $references . $response ;
2023-09-03 16:32:21 +02:00
}
$response = str_replace ( " \n " , " " , str_replace ( " \r " , " " , $response ));
} else {
$body .= $response . " \n " ;
}
}
$lines = $lines - 1 ;
$bytes = $bytes + ( $lines * 2 );
// add to database
// CREATE SEARCH SNIPPET
$this_snippet = get_search_snippet ( $body , $content_type [ 1 ]);
2024-10-03 14:13:03 +02:00
$xref = create_xref_from_msgid ( $mid [ 1 ], $group , $local );
2023-09-03 16:32:21 +02:00
$new_article_stmt -> execute ([
$group ,
$local ,
$mid [ 1 ],
$article_date ,
$from [ 1 ],
$subject [ 1 ],
$row [ 'article' ],
$this_snippet
]);
2023-11-15 12:55:08 +01:00
$overview_stmt -> execute ([
2023-09-03 16:32:21 +02:00
$group ,
$local ,
$mid [ 1 ],
$article_date ,
$finddate [ 1 ],
$from [ 1 ],
$subject [ 1 ],
$references ,
$bytes ,
$lines ,
$xref
]);
$status = " respooled " ;
$statusdate = time ();
$statusreason = " repair " ;
2024-10-03 14:13:03 +02:00
$statusnotes = '' ;
2023-09-03 16:32:21 +02:00
add_to_history ( $group , $local , $mid [ 1 ], $status , $statusdate , $statusreason , $statusnotes );
echo " \n Imported: " . $group . " " . $local ;
file_put_contents ( $logfile , " \n " . format_log_date () . " " . $config_name . " Imported: " . $group . " : " . $local , FILE_APPEND );
2024-10-03 14:13:03 +02:00
$i ++ ;
2023-09-03 16:32:21 +02:00
$references = " " ;
}
$new_article_dbh = null ;
$article_dbh = null ;
2023-11-15 12:55:08 +01:00
$overview_dbh = null ;
2023-09-03 16:32:21 +02:00
unlink ( $spooldir . '/' . $group . '-articles.db3' );
rename ( $spooldir . '/' . $group . '-articles.db3-new' , $spooldir . '/' . $group . '-articles.db3' );
unlink ( $spooldir . '/' . $group . '-info.txt' );
unlink ( $spooldir . '/' . $group . '-cache.txt' );
unlink ( $spooldir . '/' . $group . '-lastarticleinfo.dat' );
unlink ( $spooldir . '/' . $group . '-overboard.dat' );
reset_group ( $group );
}