Store thread data in sqlite db instead of file.

This commit is contained in:
Retro_Guy 2023-08-22 05:34:37 -07:00
parent ee6e0f8b24
commit 17ad7a29cf
2 changed files with 978 additions and 985 deletions

View File

@ -1,5 +1,7 @@
<?php
/* rslight NNTP<->HTTP Gateway
/*
* rslight NNTP<->HTTP Gateway
* Download: https://news.novabbs.com/getrslight
*
* Based on Newsportal by Florian Amrhein
@ -26,7 +28,8 @@
* Shows the little menu on the thread.php where you can select the
* different pages with the articles on it
*/
function thread_pageselect($group,$article_count,$first) {
function thread_pageselect($group, $article_count, $first)
{
global $articles_per_page, $file_thread, $file_framethread, $name;
global $text_thread, $thread_show;
$pages = ceil($article_count / $articles_per_page);
@ -35,10 +38,7 @@ function thread_pageselect($group,$article_count,$first) {
for ($i = 0; $i < $pages; $i ++) {
// echo '[';
if ($first != $i * $articles_per_page + 1) {
echo '<a class="np_pages_unselected" href="'.
$file_thread.'?group='.$group.
'&amp;first='.($i*$articles_per_page+1).'&amp;last='.
($i+1)*$articles_per_page.'">';
echo '<a class="np_pages_unselected" href="' . $file_thread . '?group=' . $group . '&amp;first=' . ($i * $articles_per_page + 1) . '&amp;last=' . ($i + 1) * $articles_per_page . '">';
} else {
// echo 'PAGE: '.$i.' OF: '.$pages;
}
@ -65,66 +65,47 @@ function thread_pageselect($group,$article_count,$first) {
*
* returns: an array of headerType containing the thread.
*/
function thread_cache_load($group) {
function thread_cache_load($group)
{
global $spooldir, $compress_spoolfiles;
$filename=$spooldir."/".$group."-data.dat";
$waiting = 0;
$now = time();
while(file_exists($filename."-writing")) {
$waiting = 1;
if(time() > $now + 30) {
unlink($filename."-writing");
return false;
$database = $spooldir . '/' . $group . '-data.db3';
$table = "threads";
if ($dbh = threads_db_open($database, $table)) {
$stmt = $dbh->prepare("SELECT * FROM $table");
$stmt->execute();
while ($row = $stmt->fetch()) {
$headers = unserialize($row['headers']);
break;
}
}
if($waiting == 1) {
sleep(1);
}
if (!file_exists($filename)) return false;
if ($compress_spoolfiles) {
$file=gzopen("$spooldir/$group-data.dat","r");
flock($file, LOCK_SH);
$headers=unserialize(gzread($file,1000000));
flock($file, LOCK_UN);
gzclose($file);
} else {
$file=fopen($filename,"r");
flock($file, LOCK_SH);
$headers=unserialize(fread($file,filesize($filename)));
flock($file, LOCK_UN);
fclose($file);
$dbh = null;
}
return ($headers);
}
/*
* Save the thread to disk
*
* $header: is an array of headerType containing the thread
* $group: name of the newsgroup, is needed to create the filename
*/
function thread_cache_save($headers,$group) {
function thread_cache_save($headers, $group)
{
global $spooldir, $compress_spoolfiles, $logdir, $config_name;
$logfile = $logdir . '/newsportal.log';
if ($compress_spoolfiles) {
$file=gzopen("$spooldir/$group-data.dat-writing","w");
$islock = flock($file, LOCK_EX);
gzputs($file,serialize($headers));
flock($file, LOCK_UN);
gzclose($file);
} else {
$file=fopen("$spooldir/$group-data.dat-writing","w");
if($file===false) {
die('The spool-directory is not writeable. Please change the user '.
'permissions to give the webserver write-access to it.');
}
$islock = flock($file, LOCK_EX);
fputs($file,serialize($headers));
flock($file, LOCK_UN);
fclose($file);
rename("$spooldir/$group-data.dat-writing", "$spooldir/$group-data.dat");
file_put_contents($logfile, "\n".format_log_date()." ".$config_name." Locking status: ".$islock." for ".$group, FILE_APPEND);
$database = $spooldir . '/' . $group . '-data.db3';
$table = "threads";
if ($dbh = threads_db_open($database, $table)) {
$drop = 'DROP TABLE IF EXISTS '. $table;
$drop_stmt = $dbh->prepare($drop);
$drop_stmt->execute();
$dbh = null;
$dbh = threads_db_open($database, $table);
$sql = 'INSERT INTO ' . $table . '(headers) VALUES(?)';
$stmt = $dbh->prepare($sql);
$stmt->execute([
serialize($headers)
]);
$dbh = null;
}
}
@ -135,11 +116,13 @@ function thread_cache_save($headers,$group) {
* the message_read function can now call this function to remove
* the article.
*/
function thread_cache_removearticle($group,$id) {
function thread_cache_removearticle($group, $id)
{
global $logdir, $config_name;
$logfile = $logdir . '/newsportal.log';
$thread = thread_cache_load($group);
if(!$thread) return false;
if (! $thread)
return false;
$changed = false;
foreach ($thread as $value) {
if (($value->number == $id) || ($value->id == $id)) {
@ -165,17 +148,18 @@ function thread_cache_removearticle($group,$id) {
break;
}
}
if($changed) thread_cache_save($thread,$group);
if ($changed)
thread_cache_save($thread, $group);
}
/*
function readArticles(&$ns,$groupname,$articleList) {
for($i = 0; $i <= count($articleList)-1 ; $i++) {
$temp=read_header($ns,$articleList[$i]);
$articles[$temp->id] = $temp;
}
return $articles;
}
* function readArticles(&$ns,$groupname,$articleList) {
* for($i = 0; $i <= count($articleList)-1 ; $i++) {
* $temp=read_header($ns,$articleList[$i]);
* $articles[$temp->id] = $temp;
* }
* return $articles;
* }
*/
/*
@ -189,7 +173,8 @@ function readArticles(&$ns,$groupname,$articleList) {
*
* returns: headerType containing the data
*/
function thread_overview_interpret($line,$overviewformat,$groupname) {
function thread_overview_interpret($line, $overviewformat, $groupname)
{
$return = "";
$overviewfmt = explode("\t", $overviewformat);
echo " "; // keep the connection to the webbrowser alive
@ -221,7 +206,8 @@ function thread_overview_interpret($line,$overviewformat,$groupname) {
$article->name = $fromline[0]["personal"];
}
}
if ($overviewfmt[$i]=="Message-ID:") $article->id=$over[$i+1];
if ($overviewfmt[$i] == "Message-ID:")
$article->id = $over[$i + 1];
if (($overviewfmt[$i] == "References:") && ($over[$i + 1] != "")) {
$article->references = explode(" ", $over[$i + 1]);
}
@ -240,7 +226,8 @@ function thread_overview_interpret($line,$overviewformat,$groupname) {
* read the overview-format from the newsserver. This data is used
* by thread_overview_interpret
*/
function thread_overview_read(&$ns) {
function thread_overview_read(&$ns)
{
$overviewfmt = array();
fputs($ns, "LIST overview.fmt\r\n"); // find out the format of the
$tmp = line_read($ns); // xover-command
@ -258,21 +245,30 @@ function thread_overview_read(&$ns) {
// some stupid newsservers, like changi, don't send their overview
// format
// let's hope, that the format is like that from INN
$overviewfmt=array("Subject:","From:","Date:","Message-ID:",
"References:","Bytes:");
$overviewfmt = array(
"Subject:",
"From:",
"Date:",
"Message-ID:",
"References:",
"Bytes:"
);
}
$overviewformat = implode("\t", $overviewfmt);
return $overviewformat;
}
function thread_mycompare($a,$b) {
function thread_mycompare($a, $b)
{
global $thread_sort_order, $thread_sort_type;
if ($thread_sort_type != "thread") {
$r = ($a->date < $b->date) ? - 1 : 1;
if ($a->date==$b->date) $r=0;
if ($a->date == $b->date)
$r = 0;
} else {
$r = ($a->date_thread < $b->date_thread) ? - 1 : 1;
if ($a->date_thread==$b->date_thread) $r=0;
if ($a->date_thread == $b->date_thread)
$r = 0;
}
return $r * $thread_sort_order;
}
@ -292,16 +288,16 @@ function thread_mycompare($a,$b) {
* means, that it also read every article from the newsserver.
* This makes only sense if the article cache is activated
*/
function thread_load_newsserver(&$ns,$groupname,$poll) {
function thread_load_newsserver(&$ns, $groupname, $poll)
{
global $spooldir, $logdir, $maxarticles, $maxfetch, $initialfetch, $maxarticles_extra, $config_name;
global $text_error, $text_thread, $compress_spoolfiles, $server;
global $www_charset, $iconv_enable, $thread_show, $thread_sort_order;
$logfile = $logdir . '/newsportal.log';
$idstring="0.36,".$server.",".$compress_spoolfiles.",".$maxarticles.",".
$maxarticles_extra.",".$maxfetch.",".$initialfetch.",".
$www_charset.','.$iconv_enable.','.$thread_show["replies"];
$maxfetch = 0;
$idstring = "0.36," . $server . "," . $compress_spoolfiles . "," . $maxarticles . "," . $maxarticles_extra . "," . $maxfetch . "," . $initialfetch . "," . $www_charset . ',' . $iconv_enable . ',' . $thread_show["replies"];
$overviewformat = thread_overview_read($ns);
$spoolfilename=$spooldir."/".$groupname."-data.dat";
$spoolfilename = $spooldir . '/' . $groupname . '-data.db3';
fputs($ns, "GROUP $groupname\r\n"); // select a group
$groupinfo = explode(" ", line_read($ns));
if (substr($groupinfo[0], 0, 1) != 2) {
@ -318,7 +314,7 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
$spoolopenmodus = "n";
// if the group-info file doesn't exist: create it
if (! ((file_exists($infofilename)) && (file_exists($spoolfilename)))) {
file_put_contents($logfile, "\n".format_log_date()." ".$config_name." ".$infofilename." or ".$spoolfilename." does not exist. Rebuilding ".$groupname, FILE_APPEND);
file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " Threads database does not exist. Rebuilding " . $groupname, FILE_APPEND);
$spoolopenmodus = "w";
} else {
$infofile = fopen($infofilename, "r");
@ -335,7 +331,8 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
$spoolopenmodus = "w";
}
if ($maxarticles == 0) {
if ($groupinfo[2] != $oldgroupinfo[0]) $spoolopenmodus="w";
if ($groupinfo[2] != $oldgroupinfo[0])
$spoolopenmodus = "w";
} else {
if ($groupinfo[2] > $oldgroupinfo[0]) {
file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " low watermark increased. Trimming " . $groupname, FILE_APPEND);
@ -422,7 +419,8 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
// decode the article itself, so it can be saved in the article
// cache
if ($poll) {
echo $article->number.", "; flush();
echo $article->number . ", ";
flush();
message_read($article->number, 0, $groupname);
}
// read the next line from the newsserver
@ -436,17 +434,9 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
fputs($infofile, serialize($lastarticleinfo));
fclose($infofile);
}
// remove the old spoolfile
// if (file_exists($spoolfilename)) unlink($spoolfilename);
if ((isset($headers)) && (count($headers) > 0)) {
//$infofile=fopen($infofilename,"w");
//if ($spoolopenmodus=="a") $firstarticle=$oldgroupinfo[0];
//fputs($infofile,$idstring."\n");
//fputs($infofile,$firstarticle." ".$lastarticle."\r\n");
//fclose($infofile);
foreach ($headers as $c) {
if (($c->isAnswer == false) &&
(isset($c->references))) { // is the article an answer to an
if (($c->isAnswer == false) && (isset($c->references))) { // is the article an answer to an
// other article?
// try to find a matching article to one of the references
$refmatch = false;
@ -468,9 +458,7 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
do {
$d->threadsize += $c->threadsize;
$d->date_thread = max($c->date, $d->date_thread);
} while(($headers[$d->bestreference]) &&
(isset($d->bestreference)) &&
($d =& $headers[$d->bestreference]));
} while (($headers[$d->bestreference]) && (isset($d->bestreference)) && ($d = &$headers[$d->bestreference]));
}
}
}
@ -479,11 +467,11 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
if (($thread_sort_order != 0) && (count($headers) > 0))
uasort($headers, 'thread_mycompare');
// Save the thread-informations
// if (file_exists($spoolfilename)) unlink($spoolfilename);
thread_cache_save($headers, $groupname);
// Save the info-file
$infofile = fopen($infofilename, "w");
if ($spoolopenmodus=="a") $firstarticle=$oldgroupinfo[0];
if ($spoolopenmodus == "a")
$firstarticle = $oldgroupinfo[0];
fputs($infofile, $idstring . "\n");
fputs($infofile, $firstarticle . " " . $lastarticle . " " . count($headers) . "\r\n");
fclose($infofile);
@ -498,19 +486,14 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
unlink($spooldir . '/' . $cachefile);
}
// remove the html cache files of this group
if((substr($cachefile,strlen($cachefile)-5)==".html") &&
(substr($cachefile,0,strlen($groupname)+1)==$groupname."-"))
if ((substr($cachefile, strlen($cachefile) - 5) == ".html") && (substr($cachefile, 0, strlen($groupname) + 1) == $groupname . "-"))
unlink($spooldir . '/' . $cachefile);
}
}
if(isset($headers))
return $headers;
return false;
//return((isset($headers)) ? $headers : false);
return ((isset($headers)) ? $headers : false);
}
}
/*
* Read the Overview.
* Format of the overview-file:
@ -526,8 +509,8 @@ function thread_load_newsserver(&$ns,$groupname,$poll) {
* newsserver, if there exists no cached data for this group
* $poll: polling mode, see description at thread_load_newsserver()
*/
function thread_load($groupname,$readmode = 1,$poll=false) {
function thread_load($groupname, $readmode = 1, $poll = false)
{
global $text_error, $maxarticles, $server, $port;
global $spooldir, $thread_sort_order, $cache_thread;
global $articles_per_page;
@ -562,7 +545,8 @@ function thread_load($groupname,$readmode = 1,$poll=false) {
if ($query_ns) {
// look if there is new data on the newsserver
$ns = nntp_open($server, $port);
if ($ns == false) return false;
if ($ns == false)
return false;
if (($ns != false) && ($readmode > 0))
$articles = thread_load_newsserver($ns, $groupname, $poll);
if ((isset($articles)) && ($articles)) {
@ -588,21 +572,24 @@ function thread_load($groupname,$readmode = 1,$poll=false) {
* The function removes the re:, aw: etc. from $subject end returns true
* if it removed anything, and false if not.
*/
function splitSubject(&$subject) {
function splitSubject(&$subject)
{
$s = preg_replace('/^(odp:|aw:|re:|re\[2\]:| )+/i', '', $subject);
$return = ($s != $subject);
$subject = $s;
return $return;
}
function str_change($str,$pos,$char) {
function str_change($str, $pos, $char)
{
return (substr($str, 0, $pos) . $char . substr($str, $pos + 1, strlen($str) - $pos));
}
/*
* calculate the graphic representation of the thread
*/
function thread_show_calculate($newtree,$depth,$num,$liste,$c) {
function thread_show_calculate($newtree, $depth, $num, $liste, $c)
{
global $thread_show;
// displays the replies to an article?
if (! $thread_show["replies"]) {
@ -629,7 +616,6 @@ function thread_show_calculate($newtree,$depth,$num,$liste,$c) {
return ($newtree);
}
/*
* Format the message-tree
* Zeichen im Baum:
@ -640,7 +626,8 @@ function thread_show_calculate($newtree,$depth,$num,$liste,$c) {
* + : T-Stueck T.gif
* ` : Winkel L.gif
*/
function thread_show_treegraphic($newtree) {
function thread_show_treegraphic($newtree)
{
global $imgdir;
$return = "";
for ($o = 0; $o < strlen($newtree); $o ++) {
@ -673,13 +660,15 @@ function thread_show_treegraphic($newtree) {
break;
}
$return .= '" alt="' . $alt . '" class="thread_image"';
if (strcmp($k,".") == 0) $return .=(' width="12" height="9"');
if (strcmp($k, ".") == 0)
$return .= (' width="12" height="9"');
$return .= '>';
}
return ($return);
}
function formatTreeText($tree) {
function formatTreeText($tree)
{
$tree = str_replace("i", "|", $tree);
$tree = str_replace(".", "&nbsp;", $tree);
return ($tree);
@ -688,7 +677,8 @@ function formatTreeText($tree) {
/*
* format the subject inside the thread
*/
function thread_format_subject($c,$group,$highlightids=false) {
function thread_format_subject($c, $group, $highlightids = false)
{
global $file_article, $thread_maxSubject, $frame_article, $frame, $thread_show, $spooldir, $CONFIG;
if (isset($_COOKIE['tzo'])) {
$offset = $_COOKIE['tzo'];
@ -715,9 +705,7 @@ function thread_format_subject($c,$group,$highlightids=false) {
else {
$return = '<a ';
$return .= 'target="' . $frame['content'] . '" ';
$return .= 'href="'.$file_article.
'?id='.urlencode($c->number).'&group='.urlencode($group).'#'.
urlencode($c->number).'">';
$return .= 'href="' . $file_article . '?id=' . urlencode($c->number) . '&group=' . urlencode($group) . '#' . urlencode($c->number) . '">';
}
$return .= $re . htmlspecialchars(mb_substr(trim($c->subject), 0, $thread_maxSubject));
if ($highlight)
@ -744,7 +732,8 @@ function thread_format_subject($c,$group,$highlightids=false) {
/*
* colorize the date inside the thread
*/
function thread_format_date_color($date) {
function thread_format_date_color($date)
{
global $age_count, $age_time, $age_color;
$return = "";
$currentTime = time();
@ -762,7 +751,8 @@ function thread_format_date_color($date) {
/*
* format the date inside the thread
*/
function thread_format_date($c) {
function thread_format_date($c)
{
global $age_count, $age_time, $age_color, $thread_show, $thread_show;
$return = "";
$currentTime = time();
@ -775,17 +765,21 @@ function thread_format_date($c) {
$date = $c->date;
if ($age_count > 0)
for ($t = $age_count; $t >= 1; $t --)
if ($currentTime - $date < $age_time[$t]) $color = $age_color[$t];
if ($color != "") $return .= '<font color="'.$color.'">';
if ($currentTime - $date < $age_time[$t])
$color = $age_color[$t];
if ($color != "")
$return .= '<font color="' . $color . '">';
$return .= date("d M ", $date); // format the date
if ($color != "") $return .= '</font>';
if ($color != "")
$return .= '</font>';
return ($return);
}
/*
* format the author inside the thread
*/
function thread_format_author($c,$group='',$lastmessage=1) {
function thread_format_author($c, $group = '', $lastmessage = 1)
{
global $thread_show, $anonym_address;
if ($lastmessage == 1) {
return thread_format_lastmessage($c, $group, $lastmessage);
@ -816,7 +810,8 @@ function thread_format_author($c,$group='',$lastmessage=1) {
/*
* format the last message info in the thread
*/
function thread_format_lastmessage($c,$group='') {
function thread_format_lastmessage($c, $group = '')
{
global $thread_show, $anonym_address, $spooldir, $CONFIG;
$ovfound = 0;
if ($CONFIG['article_database'] == '1') {
@ -829,7 +824,8 @@ function thread_format_lastmessage($c,$group='') {
$stmt->execute();
if ($found = $stmt->fetch()) {
$ovfound = 1;
};
}
;
$dbh = null;
}
} else {
@ -843,11 +839,13 @@ function thread_format_lastmessage($c,$group='') {
$stmt->execute();
if ($found = $stmt->fetch()) {
$ovfound = 1;
};
}
;
$dbh = null;
}
$fromline = address_decode(headerDecode($found['name']), "nowhere");
if (!isset($fromline[0]["host"])) $fromline[0]["host"]="";
if (! isset($fromline[0]["host"]))
$fromline[0]["host"] = "";
$name_from = $fromline[0]["mailbox"] . "@" . $fromline[0]["host"];
$name_username = $fromline[0]["mailbox"];
if (! isset($fromline[0]["personal"])) {
@ -877,14 +875,16 @@ function thread_format_lastmessage($c,$group='') {
* Displays a part of the thread. This function is recursively called
* It is used by thread_show
*/
function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_first=0,$article_last=0,&$article_count,$highlight=false,$lastmessage=1) {
function thread_show_recursive(&$headers, &$liste, $depth, $tree, $group, $article_first = 0, $article_last = 0, &$article_count, $highlight = false, $lastmessage = 1)
{
global $thread_treestyle;
global $thread_show, $imgdir;
global $file_article, $thread_maxSubject;
global $age_count, $age_time, $age_color, $spooldir;
global $frame_article;
$output = "";
if ($thread_treestyle==3) $output.= "\n<UL>\n";
if ($thread_treestyle == 3)
$output .= "\n<UL>\n";
for ($i = 0; $i < count($liste); $i ++) {
// CSS class for the actual line
$lineclass = "np_thread_line" . (($article_count % 2) + 1);
@ -904,15 +904,16 @@ function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_fi
case 7: // thread, table, graphic
$newtree = thread_show_calculate($tree, $depth, $i, $liste, $c);
}
if (($article_first == 0) ||
(($article_count >= $article_first) &&
($article_count <= $article_last))) {
if (($article_first == 0) || (($article_count >= $article_first) && ($article_count <= $article_last))) {
switch ($thread_treestyle) {
case 0: // simple list
$output .= '<span class="np_thread_line_text">';
if ($thread_show["date"]) $output.= thread_format_date($c)." ";
if ($thread_show["subject"]) $output.= thread_format_subject($c,$group,false)." ";
if ($thread_show["author"]) $output.= "(".thread_format_author($c,$group,$lastmessage).")";
if ($thread_show["date"])
$output .= thread_format_date($c) . " ";
if ($thread_show["subject"])
$output .= thread_format_subject($c, $group, false) . " ";
if ($thread_show["author"])
$output .= "(" . thread_format_author($c, $group, $lastmessage) . ")";
$output .= '</span>';
$output .= "<br>\n";
break;
@ -929,20 +930,13 @@ function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_fi
case 2: // table
$output .= '<tr>';
if ($thread_show["date"]) {
$output.= '<td><span class="np_thread_line_text">'.
thread_format_date($c).' </span></td>';
$output .= '<td><span class="np_thread_line_text">' . thread_format_date($c) . ' </span></td>';
}
if ($thread_show["subject"]) {
$output.= '<td nowrap="nowrap">'.
'<span class="np_thread_line_text">'.
thread_format_subject($c,$group,$highlight).
'</span></td>';
$output .= '<td nowrap="nowrap">' . '<span class="np_thread_line_text">' . thread_format_subject($c, $group, $highlight) . '</span></td>';
}
if ($thread_show["author"]) {
$output.= '<td></td>'.
'<td nowrap="nowrap">'.
'<span class="np_thread_line_text">'.thread_format_author($c,$group,$lastmessage).
'</span></td>';
$output .= '<td></td>' . '<td nowrap="nowrap">' . '<span class="np_thread_line_text">' . thread_format_author($c, $group, $lastmessage) . '</span></td>';
}
$output .= "</tr>\n";
break;
@ -970,15 +964,10 @@ function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_fi
case 5: // thread, graphic
$output .= '<table cellspacing="0"><tr>';
if ($thread_show["date"])
$output.= '<td nowrap="nowrap">'.
'<span class="np_thread_line_text">'.
thread_format_date($c).' </span></td>';
$output.= '<td><span class="np_thread_line_text">'.
thread_show_treegraphic($newtree).'</span></td>';
$output .= '<td nowrap="nowrap">' . '<span class="np_thread_line_text">' . thread_format_date($c) . ' </span></td>';
$output .= '<td><span class="np_thread_line_text">' . thread_show_treegraphic($newtree) . '</span></td>';
if ($thread_show["subject"])
$output.= '<td nowrap="nowrap">'.
'<span class="np_thread_line_text">&nbsp;'.
thread_format_subject($c,$group,$highlight)." ";
$output .= '<td nowrap="nowrap">' . '<span class="np_thread_line_text">&nbsp;' . thread_format_subject($c, $group, $highlight) . " ";
if ($thread_show["author"])
$output .= '(' . thread_format_author($c, $group, $lastmessage) . ')</span></td>';
$output .= "</tr></table>";
@ -986,35 +975,25 @@ function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_fi
case 6: // thread, table
$output .= "<tr>";
if ($thread_show["date"])
$output.= '<td nowrap="nowrap"><tt>'.
'<span class="np_thread_line_text">'.
thread_format_date($c).' </span></tt></td>';
$output.= '<td nowrap="nowrap"><tt>'.
'<span class="np_thread_line_text">'.
formatTreeText($newtree)." ";
$output .= '<td nowrap="nowrap"><tt>' . '<span class="np_thread_line_text">' . thread_format_date($c) . ' </span></tt></td>';
$output .= '<td nowrap="nowrap"><tt>' . '<span class="np_thread_line_text">' . formatTreeText($newtree) . " ";
if ($thread_show["subject"]) {
$output .= thread_format_subject($c, $group, $highlight) . "</span></tt></td>";
$output .= "<td></td>";
}
if ($thread_show["author"])
$output.= '<td nowrap="nowrap"><tt>'.
'<span class="np_thread_line_text">'.
thread_format_author($c,$group,$lastmessage).'</span></tt></td>';
$output .= '<td nowrap="nowrap"><tt>' . '<span class="np_thread_line_text">' . thread_format_author($c, $group, $lastmessage) . '</span></tt></td>';
$output .= "</tr>";
break;
case 7: // thread, table, graphic
$output .= '<tr class="' . $lineclass;
$output .= '">';
if ($thread_show["date"])
$output.= '<td class="'.$lineclass.'" nowrap="nowrap">'.
'<span class="np_thread_line_text">'.
thread_format_date($c)." ".
'</span></td>';
$output .= '<td class="' . $lineclass . '" nowrap="nowrap">' . '<span class="np_thread_line_text">' . thread_format_date($c) . " " . '</span></td>';
$output .= '<td class="' . $lineclass . '">';
$output .= thread_show_treegraphic($newtree);
if ($thread_show["subject"]) {
$output.= '<span class="np_thread_line_text">&nbsp;'.
thread_format_subject($c,$group,$highlight).'</span>';
$output .= '<span class="np_thread_line_text">&nbsp;' . thread_format_subject($c, $group, $highlight) . '</span>';
}
$output .= '</td>';
if ($thread_show["threadsize"]) {
@ -1022,52 +1001,47 @@ function thread_show_recursive(&$headers,&$liste,$depth,$tree,$group,$article_fi
$output .= '<td class="' . $lineclass . '" nowrap="nowrap">' . $replies_count . '</td>';
}
if ($thread_show["author"])
$output.= '<td class="'.$lineclass.'">'.
'<span class="np_thread_line_text">'.
thread_format_author($c,$group,$lastmessage).'</span></td>';
$output .= '<td class="' . $lineclass . '">' . '<span class="np_thread_line_text">' . thread_format_author($c, $group, $lastmessage) . '</span></td>';
$output .= "</tr>";
break;
}
}
if ((isset($c->answers[0])) && (count($c->answers)>0) &&
($article_count<=$article_last)) {
if ((isset($c->answers[0])) && (count($c->answers) > 0) && ($article_count <= $article_last)) {
if ($thread_treestyle >= 4) {
if (substr($newtree, $depth - 2, 1) == "+")
$newtree = str_change($newtree, $depth - 2, "i");
$newtree = str_change($newtree, $depth - 1, "+");
$newtree = strtr($newtree, "`", ".");
}
if (!isset($newtree)) $newtree="";
if (! isset($newtree))
$newtree = "";
if ($thread_show["replies"]) {
$output.=thread_show_recursive($headers,$c->answers,$depth+1,$newtree."",$group,
$article_first,$article_last,$article_count,$highlight,$lastmessage);
$output .= thread_show_recursive($headers, $c->answers, $depth + 1, $newtree . "", $group, $article_first, $article_last, $article_count, $highlight, $lastmessage);
}
}
flush();
}
if ($thread_treestyle==3) $output.= "</UL>";
if ($thread_treestyle == 3)
$output .= "</UL>";
return $output;
}
/*
* Displays the Head (table tags, headlines etc.) of a thread
*/
function thread_show_head($lastmessage=1) {
function thread_show_head($lastmessage = 1)
{
global $thread_show, $thread_showTable;
global $text_thread, $thread_treestyle;
if (($thread_treestyle==2) || ($thread_treestyle==6) ||
($thread_treestyle==7)) {
if (($thread_treestyle == 2) || ($thread_treestyle == 6) || ($thread_treestyle == 7)) {
echo '<table cellspacing="0" class="np_thread_table">';
echo '<tr class="np_thread_head">' . "\n";
if ($thread_show["date"])
echo '<td width="1%" class="np_thread_head">' . $text_thread["date"] . "&nbsp;</td>";
if ($thread_show["subject"])
echo '<td class="np_thread_head">'.
$text_thread["subject"]."</td>";
echo '<td class="np_thread_head">' . $text_thread["subject"] . "</td>";
if ($thread_show["threadsize"])
echo '<td width="70em" class="np_thread_head">'.
$text_thread["threadsize"]."</td>";
echo '<td width="70em" class="np_thread_head">' . $text_thread["threadsize"] . "</td>";
if ($thread_show["author"]) {
if ($lastmessage == 1) {
echo '<td width="15%" class="np_thread_head">' . $text_thread["lastmessage"] . "</td>\n";
@ -1077,21 +1051,23 @@ function thread_show_head($lastmessage=1) {
}
echo "</tr>\n";
} else {
if ($thread_treestyle==1) echo "<ul>\n";
if ($thread_treestyle == 1)
echo "<ul>\n";
}
}
/*
* Displays the tail (closing table tags, headlines etc.) of a thread
*/
function thread_show_tail() {
function thread_show_tail()
{
global $thread_show, $thread_showTable;
global $text_thread, $thread_treestyle;
if (($thread_treestyle==2) || ($thread_treestyle==6) ||
($thread_treestyle==7)) {
if (($thread_treestyle == 2) || ($thread_treestyle == 6) || ($thread_treestyle == 7)) {
echo "</table>\n";
} else {
if ($thread_treestyle==1) echo "</ul>\n";
if ($thread_treestyle == 1)
echo "</ul>\n";
}
}
@ -1103,15 +1079,15 @@ function thread_show_tail() {
* $article_first: Number of the first article to be displayed
* $article_last: last article
*/
function thread_show(&$headers,$group,$article_first=0,$article_last=0,$lastmessage=1) {
function thread_show(&$headers, $group, $article_first = 0, $article_last = 0, $lastmessage = 1)
{
global $spooldir, $text_thread;
$article_count = 0;
if ($headers == false) {
echo $text_thread["no_articles"];
} else {
// exists a cached html-output?
$filename=$spooldir."/".$group."-".$article_first."-".
$article_last.".html";
$filename = $spooldir . "/" . $group . "-" . $article_first . "-" . $article_last . ".html";
if (! file_exists($filename)) {
// no, we need to create a new html-output
$output = "";
@ -1125,8 +1101,7 @@ function thread_show(&$headers,$group,$article_first=0,$article_last=0,$lastmess
}
reset($liste);
if (count($liste) > 0) {
$output.=thread_show_recursive($headers,$liste,1,"",$group,$article_first,
$article_last,$article_count,$lastmessage);
$output .= thread_show_recursive($headers, $liste, 1, "", $group, $article_first, $article_last, $article_count, $lastmessage);
}
// cache the html-output
$file = fopen($filename, "w");
@ -1144,26 +1119,27 @@ function thread_show(&$headers,$group,$article_first=0,$article_last=0,$lastmess
}
}
/*
* returns the article-numbers of all articles in a given subthread
*
* $id: article number or message id of a article in a subthread
* $thread: thread data, as returned by thread_cache_load()
*/
function thread_getsubthreadids($id,$thread) {
function thread_getsubthreadids($id, $thread)
{
// recursive helper function to walk through the subtree
function thread_getsubthreadids_recursive($id) {
function thread_getsubthreadids_recursive($id)
{
global $thread;
$answers=array($thread[$id]->number);
$answers = array(
$thread[$id]->number
);
// has this article answers?
if (isset($thread[$id]->answers)) {
// walk through the answers
foreach ($thread[$id]->answers as $answer) {
$answers=array_merge($answers,
thread_getsubthreadids_recursive($answer));
$answers = array_merge($answers, thread_getsubthreadids_recursive($answer));
}
}
$answers = array_map('json_encode', $answers);

View File

@ -1499,6 +1499,23 @@ function mail_db_open($database, $table = 'messages')
return ($dbh);
}
function threads_db_open($database, $table="threads")
{
try {
$dbh = new PDO('sqlite:' . $database);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
exit();
}
$dbh->exec("CREATE TABLE IF NOT EXISTS $table(
id INTEGER PRIMARY KEY,
headers TEXT,
unique (headers))");
$stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_headers on ' . $table . '(headers)');
$stmt->execute();
return ($dbh);
}
function history_db_open($database, $table = 'history')
{
try {