diff --git a/Rocksolid_Light/rocksolid/lib/thread.inc.php b/Rocksolid_Light/rocksolid/lib/thread.inc.php index 8a4cbb2..0082ba9 100644 --- a/Rocksolid_Light/rocksolid/lib/thread.inc.php +++ b/Rocksolid_Light/rocksolid/lib/thread.inc.php @@ -1,60 +1,60 @@ HTTP Gateway - * Download: https://news.novabbs.com/getrslight + +/* + * rslight NNTP<->HTTP Gateway + * Download: https://news.novabbs.com/getrslight * - * Based on Newsportal by Florian Amrhein + * Based on Newsportal by Florian Amrhein * - * E-Mail: retroguy@novabbs.com - * Web: https://news.novabbs.com + * E-Mail: retroguy@novabbs.com + * Web: https://news.novabbs.com * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * 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) { - global $articles_per_page,$file_thread,$file_framethread,$name; - global $text_thread,$thread_show; - $pages=ceil($article_count / $articles_per_page); - if ($article_count > $articles_per_page) - echo $text_thread["pages"]; - for ($i = 0; $i < $pages; $i++) { - // echo '['; - if ($first != $i*$articles_per_page+1) { - echo ''; - } else { -// echo 'PAGE: '.$i.' OF: '.$pages; - } -// echo $i+1; - if ($i == $pages-1) { - // echo $article_count; - } else { - // echo ($i+1)*$articles_per_page; - } - if ($first != $i*$articles_per_page+1) { - echo $i+1; - echo ''; - } else { - echo ''.strval($i+1).''; - // echo '] '; - } +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); + if ($article_count > $articles_per_page) + echo $text_thread["pages"]; + for ($i = 0; $i < $pages; $i ++) { + // echo '['; + if ($first != $i * $articles_per_page + 1) { + echo ''; + } else { + // echo 'PAGE: '.$i.' OF: '.$pages; + } + // echo $i+1; + if ($i == $pages - 1) { + // echo $article_count; + } else { + // echo ($i+1)*$articles_per_page; + } + if ($first != $i * $articles_per_page + 1) { + echo $i + 1; + echo ''; + } else { + echo '' . strval($i + 1) . ''; + // echo '] '; + } } } @@ -62,70 +62,51 @@ function thread_pageselect($group,$article_count,$first) { * Load a thread from disk * * $group: name of the newsgroup, is needed to create the filename - * + * * returns: an array of headerType containing the thread. */ -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; +function thread_cache_load($group) +{ + global $spooldir, $compress_spoolfiles; + $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; + } + $dbh = null; } - } - 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); - } - return($headers); + 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) { - 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.'); +function thread_cache_save($headers, $group) +{ + global $spooldir, $compress_spoolfiles, $logdir, $config_name; + $logfile = $logdir . '/newsportal.log'; + $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; } - $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); - } } /* @@ -135,48 +116,51 @@ 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) { - global $logdir, $config_name; - $logfile=$logdir.'/newsportal.log'; - $thread=thread_cache_load($group); - if(!$thread) return false; - $changed=false; - foreach ($thread as $value) { - if(($value->number==$id) || ($value->id==$id)) { - // found to be deleted article - // now lets rebuild the tree... - if(isset($value->answers)) - foreach ($value->answers as $key => $answer) { - if(isset($thread[$answer])) { - $thread[$answer]->isAnswer=false; - } +function thread_cache_removearticle($group, $id) +{ + global $logdir, $config_name; + $logfile = $logdir . '/newsportal.log'; + $thread = thread_cache_load($group); + if (! $thread) + return false; + $changed = false; + foreach ($thread as $value) { + if (($value->number == $id) || ($value->id == $id)) { + // found to be deleted article + // now lets rebuild the tree... + if (isset($value->answers)) + foreach ($value->answers as $key => $answer) { + if (isset($thread[$answer])) { + $thread[$answer]->isAnswer = false; + } + } + if (isset($value->references)) + foreach ($value->references as $reference) { + if (isset($thread[$reference]->answers)) { + $search = array_search($value->id, $thread[$reference]->answers); + if (! ($search === false)) + unset($thread[$reference]->answers[$search]); + } + } + file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " Trimming: " . $id . " from " . $group, FILE_APPEND); + unset($thread[$value->id]); + $changed = true; + break; } - if(isset($value->references)) - foreach ($value->references as $reference) { - if(isset($thread[$reference]->answers)) { - $search=array_search($value->id,$thread[$reference]->answers); - if(!($search===false)) - unset($thread[$reference]->answers[$search]); - } - } - file_put_contents($logfile, "\n".format_log_date()." ".$config_name." Trimming: ".$id." from ".$group, FILE_APPEND); - unset($thread[$value->id]); - $changed=true; - 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; + * } + */ /* * interpret and decode one line of overview-data from the newsserver and @@ -184,97 +168,109 @@ function readArticles(&$ns,$groupname,$articleList) { * * $line: the data to be interpreted * $overviewformat: the format of an overview-line, given by - * thread_overview_read() + * thread_overview_read() * $groupname: the name of the newsgroup * * returns: headerType containing the data */ -function thread_overview_interpret($line,$overviewformat,$groupname) { - $return=""; - $overviewfmt=explode("\t",$overviewformat); - echo " "; // keep the connection to the webbrowser alive - flush(); // while generating the message-tree -// $over=explode("\t",$line,count($overviewfmt)-1); - $over=explode("\t",$line); - //$article=new headerType; - $article = (object)[]; - for ($i=0; $iisReply=splitSubject($subject); - $article->subject=$subject; - } - if ($overviewfmt[$i]=="Date:") { - $article->date=getTimestamp($over[$i+1]); - } - if ($overviewfmt[$i]=="From:") { - $fromline=address_decode(headerDecode($over[$i+1]),"nowhere"); - $article->from=$fromline[0]["mailbox"]."@".$fromline[0]["host"]; - $article->username=$fromline[0]["mailbox"]; - if (!isset($fromline[0]["personal"])) { - $article->name=$fromline[0]["mailbox"]; - if (strpos($article->name,'%')) { - $article->name=substr($article->name,0,strpos($article->name,'%')); +function thread_overview_interpret($line, $overviewformat, $groupname) +{ + $return = ""; + $overviewfmt = explode("\t", $overviewformat); + echo " "; // keep the connection to the webbrowser alive + flush(); // while generating the message-tree + // $over=explode("\t",$line,count($overviewfmt)-1); + $over = explode("\t", $line); + // $article=new headerType; + $article = (object) []; + for ($i = 0; $i < count($overviewfmt) - 1; $i ++) { + if ($overviewfmt[$i] == "Subject:") { + $subject = preg_replace('/\[doctalk\]/i', '', headerDecode($over[$i + 1])); + $article->isReply = splitSubject($subject); + $article->subject = $subject; + } + if ($overviewfmt[$i] == "Date:") { + $article->date = getTimestamp($over[$i + 1]); + } + if ($overviewfmt[$i] == "From:") { + $fromline = address_decode(headerDecode($over[$i + 1]), "nowhere"); + $article->from = $fromline[0]["mailbox"] . "@" . $fromline[0]["host"]; + $article->username = $fromline[0]["mailbox"]; + if (! isset($fromline[0]["personal"])) { + $article->name = $fromline[0]["mailbox"]; + if (strpos($article->name, '%')) { + $article->name = substr($article->name, 0, strpos($article->name, '%')); + } + $article->name = strtr($article->name, '_', ' '); + } else { + $article->name = $fromline[0]["personal"]; + } + } + if ($overviewfmt[$i] == "Message-ID:") + $article->id = $over[$i + 1]; + if (($overviewfmt[$i] == "References:") && ($over[$i + 1] != "")) { + $article->references = explode(" ", $over[$i + 1]); } - $article->name=strtr($article->name,'_',' '); - } else { - $article->name=$fromline[0]["personal"]; - } } - if ($overviewfmt[$i]=="Message-ID:") $article->id=$over[$i+1]; - if (($overviewfmt[$i]=="References:") && ($over[$i+1] != "")) { - $article->references=explode(" ",$over[$i+1]); + foreach ($article->references as &$refs) { + if (! strcmp($article->id, $refs)) { + $refs = ""; + } } - } - foreach($article->references as &$refs) { - if (!strcmp($article->id, $refs)) { - $refs=""; - } - } - $article->number=$over[0]; - $article->isAnswer=false; - return($article); + $article->number = $over[0]; + $article->isAnswer = false; + return ($article); } /* * read the overview-format from the newsserver. This data is used * by thread_overview_interpret */ -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 - if(substr($tmp,0,3)=="215") { - $line=line_read($ns); - while (strcmp($line,".") != 0) { - // workaround for braindead CLNews newsserver - if($line=="Author:") - $overviewfmt[]="From:"; - else - $overviewfmt[]=$line; - $line=line_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 + if (substr($tmp, 0, 3) == "215") { + $line = line_read($ns); + while (strcmp($line, ".") != 0) { + // workaround for braindead CLNews newsserver + if ($line == "Author:") + $overviewfmt[] = "From:"; + else + $overviewfmt[] = $line; + $line = line_read($ns); + } + } else { + // 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:" + ); } - } else { - // 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:"); - } - $overviewformat=implode("\t",$overviewfmt); - return $overviewformat; + $overviewformat = implode("\t", $overviewfmt); + return $overviewformat; } -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; +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; } else { - $r=($a->date_thread<$b->date_thread) ? -1 : 1; - if ($a->date_thread==$b->date_thread) $r=0; + $r = ($a->date_thread < $b->date_thread) ? - 1 : 1; + if ($a->date_thread == $b->date_thread) + $r = 0; } - return $r*$thread_sort_order; + return $r * $thread_sort_order; } /* @@ -289,295 +285,283 @@ function thread_mycompare($a,$b) { * $ns: handle of the connection to the newsserver * $groupname: name of the newsgroup * $poll: if set to 1, this function works in polling-mode, which - * means, that it also read every article from the newsserver. - * This makes only sense if the article cache is activated + * 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) { - 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"]; - $overviewformat=thread_overview_read($ns); - $spoolfilename=$spooldir."/".$groupname."-data.dat"; - fputs($ns,"GROUP $groupname\r\n"); // select a group - $groupinfo=explode(" ",line_read($ns)); - if (substr($groupinfo[0],0,1) != 2) { - echo "

".$text_error["error:"]."

"; - echo "

".$text_thread["no_such_group"]."

"; - flush(); - } else { - $infofilename=$spooldir."/".$groupname."-info.txt"; - // lets find out, in which mode wie want to read articles: - // w: complete rebuild of the group-info file - // a: add new articles to the group-info file - // n: there are no new articles, no rebuild or actualisation - // t: low watermark increased, remove expired articles - $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); - $spoolopenmodus="w"; +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'; + $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.db3'; + fputs($ns, "GROUP $groupname\r\n"); // select a group + $groupinfo = explode(" ", line_read($ns)); + if (substr($groupinfo[0], 0, 1) != 2) { + echo "

" . $text_error["error:"] . "

"; + echo "

" . $text_thread["no_such_group"] . "

"; + flush(); } else { - $infofile=fopen($infofilename,"r"); - $oldid=fgets($infofile,100); - if (trim($oldid) != $idstring) { - echo "\n"; - file_put_contents($logfile, "\n".format_log_date()." ".$config_name." config changed, Rebuilding ".$groupname, FILE_APPEND); - $spoolopenmodus="w"; - } - $oldgroupinfo=explode(" ",trim(fgets($infofile,200))); - fclose($infofile); - if ($groupinfo[3] < $oldgroupinfo[1]) { - file_put_contents($logfile, "\n".format_log_date()." ".$config_name." high watermark reduced. Rebuilding ".$groupname, FILE_APPEND); - $spoolopenmodus="w"; - } - if ($maxarticles == 0) { - 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); - $spoolopenmodus="t"; - } - } - // if the high watermark increased, add articles to the existing spool - if (($spoolopenmodus == "n") && ($groupinfo[3] > $oldgroupinfo[1])) { - file_put_contents($logfile, "\n".format_log_date()." ".$config_name." Adding articles to ".$groupname, FILE_APPEND); - $spoolopenmodus="a"; - } - } - if ($spoolopenmodus=="a") { - $firstarticle=$oldgroupinfo[1]+1; - $lastarticle=$groupinfo[3]; - } - if ($spoolopenmodus=="w") { - $firstarticle=$groupinfo[2]; - $lastarticle=$groupinfo[3]; - } - if ($spoolopenmodus != "n") { - if ($maxarticles != 0) { + $infofilename = $spooldir . "/" . $groupname . "-info.txt"; + // lets find out, in which mode wie want to read articles: + // w: complete rebuild of the group-info file + // a: add new articles to the group-info file + // n: there are no new articles, no rebuild or actualisation + // t: low watermark increased, remove expired articles + $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 . " Threads database does not exist. Rebuilding " . $groupname, FILE_APPEND); + $spoolopenmodus = "w"; + } else { + $infofile = fopen($infofilename, "r"); + $oldid = fgets($infofile, 100); + if (trim($oldid) != $idstring) { + echo "\n"; + file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " config changed, Rebuilding " . $groupname, FILE_APPEND); + $spoolopenmodus = "w"; + } + $oldgroupinfo = explode(" ", trim(fgets($infofile, 200))); + fclose($infofile); + if ($groupinfo[3] < $oldgroupinfo[1]) { + file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " high watermark reduced. Rebuilding " . $groupname, FILE_APPEND); + $spoolopenmodus = "w"; + } + if ($maxarticles == 0) { + 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); + $spoolopenmodus = "t"; + } + } + // if the high watermark increased, add articles to the existing spool + if (($spoolopenmodus == "n") && ($groupinfo[3] > $oldgroupinfo[1])) { + file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " Adding articles to " . $groupname, FILE_APPEND); + $spoolopenmodus = "a"; + } + } + if ($spoolopenmodus == "a") { + $firstarticle = $oldgroupinfo[1] + 1; + $lastarticle = $groupinfo[3]; + } if ($spoolopenmodus == "w") { - $firstarticle=$lastarticle-$maxarticles+1; - if ($firstarticle < $groupinfo[2]) - $firstarticle=$groupinfo[2]; - } else { - if ($lastarticle-$oldgroupinfo[0]+1 > $maxarticles + $maxarticles_extra) { - $firstarticle=$lastarticle-$maxarticles+1; - $spoolopenmodus="w"; - } + $firstarticle = $groupinfo[2]; + $lastarticle = $groupinfo[3]; } - } - if (($maxfetch!=0) && (($lastarticle-$firstarticle+1) > $maxfetch)) { - if ($spoolopenmodus=="w") { - $tofetch=($initialfetch != 0) ? $initialfetch : $maxfetch; - $lastarticle=$firstarticle+$tofetch-1; - } else { - $lastarticle=$firstarticle+$maxfetch-1; - } - } - } - echo "\n"; - // load the old spool-file, if we do not have a complete rebuild - if (($spoolopenmodus != "w") && ($spoolopenmodus != "t")) { - $headers=thread_cache_load($groupname); - } - if ($spoolopenmodus == 't') { - $count = 0; - for($i=$oldgroupinfo[0]; $i<$groupinfo[2]; $i++) { - thread_cache_removearticle($groupname,$i); - $count++; - } - // Save the info-file - $oldinfo=file($infofilename); - $oldstring=explode(" ", $oldinfo[1]); - $infofile=fopen($infofilename,"w"); - fputs($infofile,$idstring."\n"); - fputs($infofile,$groupinfo[2]." ".$oldstring[1]." ".($oldgroupinfo[2] - $count)."\r\n"); - fclose($infofile); - $spoolopenmodus = "n"; - } - // read articles from the newsserver - if ($spoolopenmodus != "n") { - // order the article overviews from the newsserver - if($firstarticle == 0 && $lastarticle == 0) { - fclose($ns); - return false; - } - fputs($ns,"XOVER ".$firstarticle."-".$lastarticle."\r\n"); - $tmp=line_read($ns); - // have the server accepted our order? - if (substr($tmp,0,3) == "224") { - $line=line_read($ns); - // read overview by overview until the data ends - while ($line != ".") { - // parse the output of the server... - $article=thread_overview_interpret($line,$overviewformat,$groupname); - // ... and save it in our data structure - $article->threadsize++; - $article->date_thread=$article->date; - $headers[$article->id]=$article; - // if we are in poll-mode: print status information and - // decode the article itself, so it can be saved in the article - // cache - if($poll) { - echo $article->number.", "; flush(); - message_read($article->number,0,$groupname); - } - // read the next line from the newsserver - $line=line_read($ns); - } - // write information about the last article to the spool-directory - $infofile=fopen($spooldir."/".$groupname."-lastarticleinfo.dat","w"); - $lastarticleinfo['from']=$article->from; - $lastarticleinfo['date']=$article->date; - $lastarticleinfo['name']=$article->name; - 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 - // other article? - // try to find a matching article to one of the references - $refmatch=false; - foreach ($c->references as $reference) { - if(isset($headers[$reference])) { - $refmatch=$reference; - } + if ($spoolopenmodus != "n") { + if ($maxarticles != 0) { + if ($spoolopenmodus == "w") { + $firstarticle = $lastarticle - $maxarticles + 1; + if ($firstarticle < $groupinfo[2]) + $firstarticle = $groupinfo[2]; + } else { + if ($lastarticle - $oldgroupinfo[0] + 1 > $maxarticles + $maxarticles_extra) { + $firstarticle = $lastarticle - $maxarticles + 1; + $spoolopenmodus = "w"; + } + } } - // have we found an article, to which this article is an answer? - if($refmatch!=false) { - $c->isAnswer=true; - $c->bestreference=$refmatch; - $headers[$c->id]=$c; - // the referenced article get the ID af this article as in - // its answers-array - $headers[$refmatch]->answers[]=$c->id; - // propagate down the number of articles in this thread - $d =& $headers[$c->bestreference]; - 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])); + if (($maxfetch != 0) && (($lastarticle - $firstarticle + 1) > $maxfetch)) { + if ($spoolopenmodus == "w") { + $tofetch = ($initialfetch != 0) ? $initialfetch : $maxfetch; + $lastarticle = $firstarticle + $tofetch - 1; + } else { + $lastarticle = $firstarticle + $maxfetch - 1; + } } - } } - reset($headers); - // sort the articles - 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]; - fputs($infofile,$idstring."\n"); - fputs($infofile,$firstarticle." ".$lastarticle." ".count($headers)."\r\n"); - fclose($infofile); - } - // remove cached articles that are not in this group - // (expired on the server or canceled) - $dirhandle=opendir($spooldir); - while ($cachefile = readdir($dirhandle)) { - if(substr($cachefile,0,strlen($groupname)+1)==$groupname."_") { - $num=preg_replace('/^(.*)_(.*)\.(.*)$/i','\2',$cachefile); - if(($num<$firstarticle) || ($num>$lastarticle)) - unlink($spooldir.'/'.$cachefile); + echo "\n"; + // load the old spool-file, if we do not have a complete rebuild + if (($spoolopenmodus != "w") && ($spoolopenmodus != "t")) { + $headers = thread_cache_load($groupname); } - // remove the html cache files of this group - if((substr($cachefile,strlen($cachefile)-5)==".html") && - (substr($cachefile,0,strlen($groupname)+1)==$groupname."-")) - unlink($spooldir.'/'.$cachefile); - } + if ($spoolopenmodus == 't') { + $count = 0; + for ($i = $oldgroupinfo[0]; $i < $groupinfo[2]; $i ++) { + thread_cache_removearticle($groupname, $i); + $count ++; + } + // Save the info-file + $oldinfo = file($infofilename); + $oldstring = explode(" ", $oldinfo[1]); + $infofile = fopen($infofilename, "w"); + fputs($infofile, $idstring . "\n"); + fputs($infofile, $groupinfo[2] . " " . $oldstring[1] . " " . ($oldgroupinfo[2] - $count) . "\r\n"); + fclose($infofile); + $spoolopenmodus = "n"; + } + // read articles from the newsserver + if ($spoolopenmodus != "n") { + // order the article overviews from the newsserver + if ($firstarticle == 0 && $lastarticle == 0) { + fclose($ns); + return false; + } + fputs($ns, "XOVER " . $firstarticle . "-" . $lastarticle . "\r\n"); + $tmp = line_read($ns); + // have the server accepted our order? + if (substr($tmp, 0, 3) == "224") { + $line = line_read($ns); + // read overview by overview until the data ends + while ($line != ".") { + // parse the output of the server... + $article = thread_overview_interpret($line, $overviewformat, $groupname); + // ... and save it in our data structure + $article->threadsize ++; + $article->date_thread = $article->date; + $headers[$article->id] = $article; + // if we are in poll-mode: print status information and + // decode the article itself, so it can be saved in the article + // cache + if ($poll) { + echo $article->number . ", "; + flush(); + message_read($article->number, 0, $groupname); + } + // read the next line from the newsserver + $line = line_read($ns); + } + // write information about the last article to the spool-directory + $infofile = fopen($spooldir . "/" . $groupname . "-lastarticleinfo.dat", "w"); + $lastarticleinfo['from'] = $article->from; + $lastarticleinfo['date'] = $article->date; + $lastarticleinfo['name'] = $article->name; + fputs($infofile, serialize($lastarticleinfo)); + fclose($infofile); + } + if ((isset($headers)) && (count($headers) > 0)) { + foreach ($headers as $c) { + 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; + foreach ($c->references as $reference) { + if (isset($headers[$reference])) { + $refmatch = $reference; + } + } + // have we found an article, to which this article is an answer? + if ($refmatch != false) { + $c->isAnswer = true; + $c->bestreference = $refmatch; + $headers[$c->id] = $c; + // the referenced article get the ID af this article as in + // its answers-array + $headers[$refmatch]->answers[] = $c->id; + // propagate down the number of articles in this thread + $d = &$headers[$c->bestreference]; + 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])); + } + } + } + reset($headers); + // sort the articles + if (($thread_sort_order != 0) && (count($headers) > 0)) + uasort($headers, 'thread_mycompare'); + // Save the thread-informations + thread_cache_save($headers, $groupname); + // Save the info-file + $infofile = fopen($infofilename, "w"); + if ($spoolopenmodus == "a") + $firstarticle = $oldgroupinfo[0]; + fputs($infofile, $idstring . "\n"); + fputs($infofile, $firstarticle . " " . $lastarticle . " " . count($headers) . "\r\n"); + fclose($infofile); + } + // remove cached articles that are not in this group + // (expired on the server or canceled) + $dirhandle = opendir($spooldir); + while ($cachefile = readdir($dirhandle)) { + if (substr($cachefile, 0, strlen($groupname) + 1) == $groupname . "_") { + $num = preg_replace('/^(.*)_(.*)\.(.*)$/i', '\2', $cachefile); + if (($num < $firstarticle) || ($num > $lastarticle)) + 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 . "-")) + unlink($spooldir . '/' . $cachefile); + } + } + return ((isset($headers)) ? $headers : false); } - if(isset($headers)) - return $headers; - return false; - //return((isset($headers)) ? $headers : false); - } -} - +} /* * Read the Overview. * Format of the overview-file: - * message-id - * date - * subject - * author - * email - * references + * message-id + * date + * subject + * author + * email + * references * * $groupname: name of the newsgroup - * $readmode: if set to 0, this function only reads data from the - * newsserver, if there exists no cached data for this group + * $readmode: if set to 0, this function only reads data from the + * 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) +{ + global $text_error, $maxarticles, $server, $port; + global $spooldir, $thread_sort_order, $cache_thread; + global $articles_per_page; + if (! testGroup($groupname)) { + echo $text_error["read_access_denied"]; + return; + } + // first assume that we have to query the newsserver + $query_ns = true; + // name of the file that indicates by it's timestamp when the + // last query of the newsserver was + $cachefile = $spooldir . '/' . $groupname . '-cache.txt'; + // should we load the data only from cache if it's recent enough, or + // do we have to query the newsserver every time? + if (is_file($cachefile)) { + if (filemtime($cachefile) + $cache_thread < time()) { + if (is_file($spooldir . '/' . $groupname . '-1-' . $articles_per_page . '.html')) { + unlink($spooldir . '/' . $groupname . '-1-' . $articles_per_page . '.html'); + } + unlink($cachefile); + } + } + if ($cache_thread > 0) { + if (file_exists($cachefile)) { + // cached file exists and is new enough. so lets read it out. + $articles = thread_cache_load($groupname); + return $articles; + $query_ns = false; + } + } + // do we have to query the newsserver? + 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) && ($readmode > 0)) + $articles = thread_load_newsserver($ns, $groupname, $poll); + if ((isset($articles)) && ($articles)) { -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; - if (!testGroup($groupname)) { - echo $text_error["read_access_denied"]; - return; - } - // first assume that we have to query the newsserver - $query_ns=true; - // name of the file that indicates by it's timestamp when the - // last query of the newsserver was - $cachefile=$spooldir.'/'.$groupname.'-cache.txt'; - // should we load the data only from cache if it's recent enough, or - // do we have to query the newsserver every time? - if(is_file($cachefile)) { - if(filemtime($cachefile)+$cache_thread < time()) { - if(is_file($spooldir.'/'.$groupname.'-1-'.$articles_per_page.'.html')) { - unlink($spooldir.'/'.$groupname.'-1-'.$articles_per_page.'.html'); - } - unlink($cachefile); + // write the file which indicates the time of the last newsserver query + touch($cachefile); + return $articles; + } else { + // uh, we didn't get articles from the newsservers... + // for now, return false. but it would also make sense to get + // the articles from the cache then... + return false; + } + nntp_close($ns); } - } - if($cache_thread>0) { - if(file_exists($cachefile)) { - // cached file exists and is new enough. so lets read it out. - $articles=thread_cache_load($groupname); - return $articles; - $query_ns=false; - } - } - // do we have to query the newsserver? - 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) && ($readmode > 0)) - $articles=thread_load_newsserver($ns,$groupname,$poll); - if ((isset($articles)) && ($articles)) { - - // write the file which indicates the time of the last newsserver query - touch($cachefile); - return $articles; - } else { - // uh, we didn't get articles from the newsservers... - // for now, return false. but it would also make sense to get - // the articles from the cache then... - return false; - } - nntp_close($ns); - } } /* @@ -588,611 +572,603 @@ 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) { - $s=preg_replace('/^(odp:|aw:|re:|re\[2\]:| )+/i','',$subject); - $return=($s != $subject); - $subject=$s; - return $return; +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) { - return(substr($str,0,$pos).$char.substr($str,$pos+1,strlen($str)-$pos)); +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) { - global $thread_show; - // displays the replies to an article? - if(!$thread_show["replies"]) { - // no - if ((isset($c->answers[0])) && (count($c->answers)>0)) - $newtree.="o"; - else - $newtree.="o"; - } else { - // yes, display the replies - if ((isset($c->answers[0])) && (count($c->answers)>0)) { - $newtree.="*"; +function thread_show_calculate($newtree, $depth, $num, $liste, $c) +{ + global $thread_show; + // displays the replies to an article? + if (! $thread_show["replies"]) { + // no + if ((isset($c->answers[0])) && (count($c->answers) > 0)) + $newtree .= "o"; + else + $newtree .= "o"; } else { - if ($depth == 1) { - $newtree.="o"; - } else { - $newtree.="-"; - } + // yes, display the replies + if ((isset($c->answers[0])) && (count($c->answers) > 0)) { + $newtree .= "*"; + } else { + if ($depth == 1) { + $newtree .= "o"; + } else { + $newtree .= "-"; + } + } + if (($num == count($liste) - 1) && ($depth > 1)) { + $newtree = str_change($newtree, $depth - 2, "`"); + } } - if (($num == count($liste)-1) && ($depth>1)) { - $newtree=str_change($newtree,$depth-2,"`"); - } - } - return($newtree); + return ($newtree); } - /* * Format the message-tree * Zeichen im Baum: - * o : leerer Kasten k1.gif - * * : Kasten mit Zeichen drin k2.gif - * i : vertikale Linie I.gif - * - : horizontale Linie s.gif - * + : T-Stueck T.gif - * ` : Winkel L.gif + * o : leerer Kasten k1.gif + * * : Kasten mit Zeichen drin k2.gif + * i : vertikale Linie I.gif + * - : horizontale Linie s.gif + * + : T-Stueck T.gif + * ` : Winkel L.gif */ -function thread_show_treegraphic($newtree) { - global $imgdir; - $return=""; - for ($o=0 ; $oisReply) { - $re="Re: "; - } else { - $re=""; - } - // is the current article to be highlighted? - if((is_array($highlightids))) { - if((in_array($c->id,$highlightids)) || (in_array($c->number,$highlightids))) { - $highlight=true; - } else { - $highlight=false; - } - } else { - $highlight=false; - } - if($highlight) - $return=''; - else { - $return='number).'">'; - } - $return.=$re.htmlspecialchars(mb_substr(trim($c->subject),0,$thread_maxSubject)); - if($highlight) - $return .=''; - else - $return.=''; - if($thread_show["latest"] == true) { - $newdate = $c->date + ($offset * 60); - - unset($ts); - $fromoutput = explode("<", html_entity_decode($c->name)); - if(strlen($fromoutput[0]) < 1) { - $started = $fromoutput[1]; +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']; } else { - $started = $fromoutput[0]; + $offset = $CONFIG['timezone'] * 60; } - $return.='
'; - $return.='

By: '.create_name_link($started, $c->from).' on '.date("D, j M Y",$newdate).'

'; - $return.='
'; - } - return($return); + if ($c->isReply) { + $re = "Re: "; + } else { + $re = ""; + } + // is the current article to be highlighted? + if ((is_array($highlightids))) { + if ((in_array($c->id, $highlightids)) || (in_array($c->number, $highlightids))) { + $highlight = true; + } else { + $highlight = false; + } + } else { + $highlight = false; + } + if ($highlight) + $return = ''; + else { + $return = 'number) . '">'; + } + $return .= $re . htmlspecialchars(mb_substr(trim($c->subject), 0, $thread_maxSubject)); + if ($highlight) + $return .= ''; + else + $return .= ''; + if ($thread_show["latest"] == true) { + $newdate = $c->date + ($offset * 60); + + unset($ts); + $fromoutput = explode("<", html_entity_decode($c->name)); + if (strlen($fromoutput[0]) < 1) { + $started = $fromoutput[1]; + } else { + $started = $fromoutput[0]; + } + $return .= '
'; + $return .= '

By: ' . create_name_link($started, $c->from) . ' on ' . date("D, j M Y", $newdate) . '

'; + $return .= '
'; + } + return ($return); } /* * colorize the date inside the thread */ -function thread_format_date_color($date) { - global $age_count,$age_time,$age_color; - $return=""; - $currentTime=time(); - if ($age_count > 0) - for($t = $age_count; $t >= 1; $t--) { - if ($currentTime - $date < $age_time[$t]) - $color = $age_color[$t]; - } - if (isset($color)) - return $color; - else - return ""; +function thread_format_date_color($date) +{ + global $age_count, $age_time, $age_color; + $return = ""; + $currentTime = time(); + if ($age_count > 0) + for ($t = $age_count; $t >= 1; $t --) { + if ($currentTime - $date < $age_time[$t]) + $color = $age_color[$t]; + } + if (isset($color)) + return $color; + else + return ""; } /* * format the date inside the thread */ -function thread_format_date($c) { - global $age_count,$age_time,$age_color,$thread_show,$thread_show; - $return=""; - $currentTime=time(); - $color=""; - // show the date of the individual article or of the latest article - // in the thread? - if($thread_show["lastdate"]) - $date=$c->date_thread; - else - $date=$c->date; +function thread_format_date($c) +{ + global $age_count, $age_time, $age_color, $thread_show, $thread_show; + $return = ""; + $currentTime = time(); + $color = ""; + // show the date of the individual article or of the latest article + // in the thread? + if ($thread_show["lastdate"]) + $date = $c->date_thread; + else + $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 .= ''; - $return .= date("d M ",$date); // format the date - if ($color != "") $return .= ''; - return($return); + for ($t = $age_count; $t >= 1; $t --) + if ($currentTime - $date < $age_time[$t]) + $color = $age_color[$t]; + if ($color != "") + $return .= ''; + $return .= date("d M ", $date); // format the date + if ($color != "") + $return .= ''; + return ($return); } /* * format the author inside the thread */ -function thread_format_author($c,$group='',$lastmessage=1) { - global $thread_show,$anonym_address; - if($lastmessage == 1) { - return thread_format_lastmessage($c,$group,$lastmessage); - } - // if the address the anonymous address, only return the name - if($c->from==$anonym_address) - return $c->name; - $return=""; - if($thread_show["authorlink"]) - $return .= ''; - if (trim($c->name)!="") { - $return .= htmlspecialchars(trim($c->name)); - } else { - if (isset($c->username)) { - $s = strpos($c->username,"%"); - if ($s != false) { - $return .= htmlspecialchars(substr($c->username,0,$s)); - } else { - $return .= htmlspecialchars($c->username); - } +function thread_format_author($c, $group = '', $lastmessage = 1) +{ + global $thread_show, $anonym_address; + if ($lastmessage == 1) { + return thread_format_lastmessage($c, $group, $lastmessage); } - } - if($thread_show["authorlink"]) - $return .= ""; - return($return); + // if the address the anonymous address, only return the name + if ($c->from == $anonym_address) + return $c->name; + $return = ""; + if ($thread_show["authorlink"]) + $return .= ''; + if (trim($c->name) != "") { + $return .= htmlspecialchars(trim($c->name)); + } else { + if (isset($c->username)) { + $s = strpos($c->username, "%"); + if ($s != false) { + $return .= htmlspecialchars(substr($c->username, 0, $s)); + } else { + $return .= htmlspecialchars($c->username); + } + } + } + if ($thread_show["authorlink"]) + $return .= ""; + return ($return); } /* * format the last message info in the thread */ -function thread_format_lastmessage($c,$group='') { - global $thread_show,$anonym_address,$spooldir,$CONFIG; - $ovfound = 0; - if($CONFIG['article_database'] == '1') { - $database = $spooldir.'/'.$group.'-articles.db3'; - $table = 'articles'; - if(is_file($database)) { - $dbh = article_db_open($database, $table); - $stmt = $dbh->prepare("SELECT * FROM $table WHERE date=:date ORDER BY date DESC"); - $stmt->bindParam(':date', $c->date_thread); - $stmt->execute(); - if($found = $stmt->fetch()) { - $ovfound = 1; - }; - $dbh = null; - } - } else { -// Tradspool - $database = $spooldir.'/articles-overview.db3'; +function thread_format_lastmessage($c, $group = '') +{ + global $thread_show, $anonym_address, $spooldir, $CONFIG; + $ovfound = 0; + if ($CONFIG['article_database'] == '1') { + $database = $spooldir . '/' . $group . '-articles.db3'; + $table = 'articles'; + if (is_file($database)) { + $dbh = article_db_open($database, $table); + $stmt = $dbh->prepare("SELECT * FROM $table WHERE date=:date ORDER BY date DESC"); + $stmt->bindParam(':date', $c->date_thread); + $stmt->execute(); + if ($found = $stmt->fetch()) { + $ovfound = 1; + } + ; + $dbh = null; + } + } else { + // Tradspool + $database = $spooldir . '/articles-overview.db3'; $table = 'overview'; $dbh = overview_db_open($database, $table); $stmt = $dbh->prepare("SELECT * FROM $table WHERE newsgroup=:newsgroup AND date=:date ORDER BY date DESC"); $stmt->bindParam(':newsgroup', $group); $stmt->bindParam(':date', $c->date_thread); $stmt->execute(); - if($found = $stmt->fetch()) { + if ($found = $stmt->fetch()) { $ovfound = 1; - }; + } + ; $dbh = null; } - $fromline = address_decode(headerDecode($found['name']),"nowhere"); - 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"])) { - $poster_name=$fromline[0]["mailbox"]; - } else { - $poster_name=$fromline[0]["personal"]; - } - if(trim($poster_name) == '') { - $fromoutput = explode("<", html_entity_decode($c->name)); - if(strlen($fromoutput[0]) < 1) { - $poster_name = $fromoutput[1]; - } else { - $poster_name = $fromoutput[0]; - } - } - if($ovfound == 1) { - $url = 'article-flat.php?id='.$found['number'].'&group='.urlencode($group).'#'.$found['number']; - $return='

'.get_date_interval(date("D, j M Y H:i T",$c->date_thread)).''; + $fromline = address_decode(headerDecode($found['name']), "nowhere"); + 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"])) { + $poster_name = $fromline[0]["mailbox"]; } else { - $return='

'.get_date_interval(date("D, j M Y H:i T",$c->date_thread)).'

'; + $poster_name = $fromline[0]["personal"]; } - $return.='

By: '.create_name_link($poster_name, $name_from).'

'; - return($return); + if (trim($poster_name) == '') { + $fromoutput = explode("<", html_entity_decode($c->name)); + if (strlen($fromoutput[0]) < 1) { + $poster_name = $fromoutput[1]; + } else { + $poster_name = $fromoutput[0]; + } + } + if ($ovfound == 1) { + $url = 'article-flat.php?id=' . $found['number'] . '&group=' . urlencode($group) . '#' . $found['number']; + $return = '

' . get_date_interval(date("D, j M Y H:i T", $c->date_thread)) . ''; + } else { + $return = '

' . get_date_interval(date("D, j M Y H:i T", $c->date_thread)) . '

'; + } + $return .= '

By: ' . create_name_link($poster_name, $name_from) . '

'; + return ($return); } /* * 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) { - 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"; + return $output; } - /* * Displays the Head (table tags, headlines etc.) of a thread */ -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)) { - echo ''; - echo ''."\n"; - if ($thread_show["date"]) - echo '"; - if ($thread_show["subject"]) - echo '"; - if ($thread_show["threadsize"]) - echo '"; - if ($thread_show["author"]) { - if($lastmessage == 1) { - echo '\n"; - } else { - echo '\n"; - } +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)) { + echo '
'.$text_thread["date"]." '. - $text_thread["subject"]."'. - $text_thread["threadsize"]."'.$text_thread["lastmessage"]."'.$text_thread["author"]."
'; + echo '' . "\n"; + if ($thread_show["date"]) + echo '"; + if ($thread_show["subject"]) + echo '"; + if ($thread_show["threadsize"]) + echo '"; + if ($thread_show["author"]) { + if ($lastmessage == 1) { + echo '\n"; + } else { + echo '\n"; + } + } + echo "\n"; + } else { + if ($thread_treestyle == 1) + echo "
' . $text_thread["date"] . " ' . $text_thread["subject"] . "' . $text_thread["threadsize"] . "' . $text_thread["lastmessage"] . "' . $text_thread["author"] . "
\n"; - } else { - if ($thread_treestyle==1) echo "\n"; - } +function thread_show_tail() +{ + global $thread_show, $thread_showTable; + global $text_thread, $thread_treestyle; + if (($thread_treestyle == 2) || ($thread_treestyle == 6) || ($thread_treestyle == 7)) { + echo "\n"; + } else { + if ($thread_treestyle == 1) + echo "\n"; + } } /* * Shows a complete thread * * $headers: The thread to be displayed - * $group: name of the newsgroup + * $group: name of the newsgroup * $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) { - 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"; - if (!file_exists($filename)) { - // no, we need to create a new html-output - $output=""; - reset($headers); - $c=current($headers); - for ($i=0; $i<=count($headers)-1; $i++) { // create the array $liste - if ($c->isAnswer == false) { // where are all the articles - $liste[]=$c->id; // in that don't have - } // references - $c=next($headers); - } - reset($liste); - if (count($liste)>0) { - $output.=thread_show_recursive($headers,$liste,1,"",$group,$article_first, - $article_last,$article_count,$lastmessage); - } - // cache the html-output - $file=fopen($filename,"w"); - fputs($file,$output); - fclose($file); +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 { - // yes, a cached output exists, load it! - $file=fopen($filename,"r"); - $output=fread($file,filesize($filename)); - fclose($file); + // exists a cached html-output? + $filename = $spooldir . "/" . $group . "-" . $article_first . "-" . $article_last . ".html"; + if (! file_exists($filename)) { + // no, we need to create a new html-output + $output = ""; + reset($headers); + $c = current($headers); + for ($i = 0; $i <= count($headers) - 1; $i ++) { // create the array $liste + if ($c->isAnswer == false) { // where are all the articles + $liste[] = $c->id; // in that don't have + } // references + $c = next($headers); + } + reset($liste); + if (count($liste) > 0) { + $output .= thread_show_recursive($headers, $liste, 1, "", $group, $article_first, $article_last, $article_count, $lastmessage); + } + // cache the html-output + $file = fopen($filename, "w"); + fputs($file, $output); + fclose($file); + } else { + // yes, a cached output exists, load it! + $file = fopen($filename, "r"); + $output = fread($file, filesize($filename)); + fclose($file); + } + thread_show_head($lastmessage); + echo $output; + thread_show_tail(); } - thread_show_head($lastmessage); - echo $output; - thread_show_tail(); - } } - - - /* * 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) { - // recursive helper function to walk through the subtree - function thread_getsubthreadids_recursive($id) { - global $thread; - $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_map('json_encode', $answers); - $answers = array_unique($answers); - $answers = array_map('json_decode', $answers); - return $answers; - } +function thread_getsubthreadids($id, $thread) +{ -//echo htmlspecialchars(print_r($thread,true)); - // exists the article $id? - if(!isset($thread[$id])) - return false; - // "rewind" the subthread to the first article in the subthread - $current=$id; - flush(); - while(isset($thread[$id]->references)) { - foreach($thread[$id]->references as $reference) { - if((trim($reference)!='') && (isset($thread[$reference]))) { - $id=$reference; - continue 2; - } + // recursive helper function to walk through the subtree + function thread_getsubthreadids_recursive($id) + { + global $thread; + $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_map('json_encode', $answers); + $answers = array_unique($answers); + $answers = array_map('json_decode', $answers); + return $answers; } - break; - } - // walk through the thread and fill up $subthread - // use the recursive helper-function thread_getsubthreadids_recursive - $subthread=thread_getsubthreadids_recursive($id); - return $subthread; + // echo htmlspecialchars(print_r($thread,true)); + // exists the article $id? + if (! isset($thread[$id])) + return false; + // "rewind" the subthread to the first article in the subthread + $current = $id; + flush(); + while (isset($thread[$id]->references)) { + foreach ($thread[$id]->references as $reference) { + if ((trim($reference) != '') && (isset($thread[$reference]))) { + $id = $reference; + continue 2; + } + } + break; + } + + // walk through the thread and fill up $subthread + // use the recursive helper-function thread_getsubthreadids_recursive + $subthread = thread_getsubthreadids_recursive($id); + return $subthread; } ?> diff --git a/Rocksolid_Light/rocksolid/newsportal.php b/Rocksolid_Light/rocksolid/newsportal.php index d46e377..88c6519 100644 --- a/Rocksolid_Light/rocksolid/newsportal.php +++ b/Rocksolid_Light/rocksolid/newsportal.php @@ -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 {