HTTP Gateway * Download: https://news.novabbs.com/getrslight * * Based on Newsportal by Florian Amrhein * * 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 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 */ if (file_exists("lib/types.inc.php")) include "lib/types.inc.php"; if (file_exists("lib/thread.inc.php")) include "lib/thread.inc.php"; if (file_exists("lib/message.inc.php")) include "lib/message.inc.php"; if (file_exists("lib/post.inc.php")) include "lib/post.inc.php"; $CONFIG = include ($config_file); /* * opens the connection to the NNTP-Server * * $server: adress of the NNTP-Server * $port: port of the server */ function nntp_open($nserver = 0, $nport = 0) { global $text_error, $CONFIG; global $server, $port; // echo "
NNTP OPEN
"; if (! isset($CONFIG['enable_nntp']) || $CONFIG['enable_nntp'] != true) { $CONFIG['server_auth_user'] = $CONFIG['remote_auth_user']; $CONFIG['server_auth_pass'] = $CONFIG['remote_auth_pass']; } $authorize = ((isset($CONFIG['server_auth_user'])) && (isset($CONFIG['server_auth_pass'])) && ($CONFIG['server_auth_user'] != "")); if ($nserver == 0) $nserver = $server; if ($nport == 0) $nport = $port; $ns = @fsockopen($nserver, $nport); // if the connection to the news server fails, inform the user and stop processing. if ($ns == false) { echo '

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

'; echo '
'; echo '

Please wait a few moments and try again. If you see the same error, notify the owner that their Message Server is offline.

'; echo '
'; exit(0); } $weg = line_read($ns); // kill the first line if (substr($weg, 0, 2) != "20") { echo "

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

"; fclose($ns); $ns = false; } else { if ($ns != false) { fputs($ns, "MODE reader\r\n"); $weg = line_read($ns); // and once more if ((substr($weg, 0, 2) != "20") && ((! $authorize) || ((substr($weg, 0, 3) != "480") && ($authorize)))) { echo "

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

"; fclose($ns); $ns = false; } } if ((isset($CONFIG['server_auth_user'])) && (isset($CONFIG['server_auth_pass'])) && ($CONFIG['server_auth_user'] != "")) { fputs($ns, "AUTHINFO USER " . $CONFIG['server_auth_user'] . "\r\n"); $weg = line_read($ns); fputs($ns, "AUTHINFO PASS " . $CONFIG['server_auth_pass'] . "\r\n"); $weg = line_read($ns); /* Only check auth if reading and posting same server */ // NNTP Response NOT 281 (Authorization failed) if (substr($weg, 0, 3) != "281" && ! (isset($post_server)) && ($post_server != "")) { echo "

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

"; echo "

" . $text_error["auth_error"] . "

"; } } } if ($ns == false) echo "

" . $text_error["connection_failed"] . "

"; return $ns; } function nntp2_open($nserver = 0, $nport = 0) { global $text_error, $CONFIG; // echo "
NNTP OPEN
"; $authorize = ((isset($CONFIG['remote_auth_user'])) && (isset($CONFIG['remote_auth_pass'])) && ($CONFIG['remote_auth_user'] != "")); if ($nserver == 0) $nserver = $CONFIG['remote_server']; if ($nport == 0) $nport = $CONFIG['remote_port']; if ($CONFIG['remote_ssl']) { if ($nport == $CONFIG['remote_port']) { $nport = $CONFIG['remote_ssl']; } var_dump($ns = fsockopen("ssl://" . $nserver, $nport, $error, $errorString, 30)); var_dump($errorString); var_dump($error); // $ns=@fsockopen('ssl://'.$nserver.":".$nport); } else { if (isset($CONFIG['socks_host']) && $CONFIG['socks_host'] !== '') { $ns = fsocks4asockopen($CONFIG['socks_host'], $CONFIG['socks_port'], $nserver, $nport); } else { $ns = @fsockopen('tcp://' . $nserver . ":" . $nport); } } // $ns=@fsockopen($nserver,$nport); $weg = line_read($ns); // kill the first line if (substr($weg, 0, 2) != "20") { echo "

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

"; if ($ns) { fclose($ns); } $ns = false; } else { if ($ns != false) { fputs($ns, "MODE reader\r\n"); $weg = line_read($ns); // and once more if ((substr($weg, 0, 2) != "20") && ((! $authorize) || ((substr($weg, 0, 3) != "480") && ($authorize)))) { echo "

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

"; fclose($ns); $ns = false; } } if ((isset($CONFIG['remote_auth_user'])) && (isset($CONFIG['remote_auth_pass'])) && ($CONFIG['remote_auth_user'] != "")) { fputs($ns, "AUTHINFO USER " . $CONFIG['remote_auth_user'] . "\r\n"); $weg = line_read($ns); fputs($ns, "AUTHINFO PASS " . $CONFIG['remote_auth_pass'] . "\r\n"); $weg = line_read($ns); /* Only check auth if reading and posting same server */ if (substr($weg, 0, 3) != "281" && ! (isset($post_server)) && ($post_server != "")) { echo "

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

"; echo "

" . $text_error["auth_error"] . "

"; } } } if ($ns == false) echo "

" . $text_error["connection_failed"] . "

"; return $ns; } function fsocks4asockopen($proxyHostname, $proxyPort, $targetHostname, $targetPort) { $sock = fsockopen($proxyHostname, $proxyPort); if ($sock === false) return false; fwrite($sock, pack("CCnCCCCC", 0x04, 0x01, $targetPort, 0x00, 0x00, 0x00, 0x01, 0x00) . $targetHostname . pack("C", 0x00)); $response = fread($sock, 16); $values = unpack("xnull/Cret/nport/Nip", $response); if ($values["ret"] == 0x5a) return $sock; else { fclose($sock); return false; } } /* * Close a NNTP connection * * $ns: the handle of the connection */ function nntp_close(&$ns) { if ($ns != false) { fputs($ns, "QUIT\r\n"); fclose($ns); } } /* * Validates an email adress * * $address: a string containing the email-address to be validated * * returns true if the address passes the tests, false otherwise. */ function validate_email($address) { global $validate_email; $return = true; if (($validate_email >= 1) && ($return == true)) /* Need to clean up this regex to work properly with preg_match $return = (preg_match('^[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+'.'@'. '[-!#$%&\'*+\\/0-9=?A-Z^_A-z{|}~]+\.'. '[-!#$%&\'*+\\./0-9=?A-Z^_A-z{|}~]+$',$address)); */ $return = 1; if (($validate_email >= 2) && ($return == true)) { $addressarray = address_decode($address, "garantiertungueltig"); $return = checkdnsrr($addressarray[0]["host"], "MX"); if (! $return) $return = checkdnsrr($addressarray[0]["host"], "A"); } return ($return); } /* * decodes a block of 7bit-data in uuencoded format to it's original * 8bit format. * The headerline containing filename and permissions doesn't have to * be included. * * $data: The uuencoded data as a string * * returns the 8bit data as a string * * Note: this function is very slow and doesn't recognize incorrect code. */ function uudecode_line($line) { $data = substr($line, 1); $length = ord($line[0]) - 32; $decoded = ""; for ($i = 0; $i < (strlen($data) >> 2); $i ++) { $pack = substr($data, $i << 2, 4); $upack = ""; $bitmaske = 0; for ($o = 0; $o < 4; $o ++) { $g = ((ord($pack[3 - $o]) - 32)); if ($g == 64) $g = 0; $bitmaske = $bitmaske | ($g << (6 * $o)); } $schablone = 255; for ($o = 0; $o < 3; $o ++) { $c = ($bitmaske & $schablone) >> ($o << 3); $schablone = ($schablone << 8); $upack = chr($c) . $upack; } $decoded .= $upack; } $decoded = substr($decoded, 0, $length); return $decoded; } /* * decodes uuencoded Attachments. * * $data: the encoded data * * returns the decoded data */ function uudecode($data) { $d = explode("\n", $data); $u = ""; for ($i = 0; $i < count($d) - 1; $i ++) $u .= uudecode_line($d[$i]); return $u; } /* * returns the mimetype of an filename * * $name: the complete filename of a file * * returns a string containing the mimetype */ function get_mimetype_by_filename($name) { $ending = strtolower(strrchr($name, ".")); switch ($ending) { case ".jpg": case ".jpeg": $type = "image/jpeg"; break; case ".gif": $type = "image/gif"; break; case ".png": $type = "image/png"; break; case ".bmp": $type = "image/bmp"; break; default: $type = "text/plain"; } return $type; } function get_mimetype_by_string($filedata) { if (function_exists('finfo_open')) { $f = finfo_open(); return finfo_buffer($f, $filedata, FILEINFO_MIME_TYPE); } else { return false; } } /* * Test, if the access to a group is allowed. This is true, if $testgroup is * false or the groupname is in groups.txt * * $groupname: name of the group to be checked * * returns true, if access is allowed */ function testGroup($groupname) { global $CONFIG, $testgroup, $file_groups, $config_dir; $groupname = strtolower($groupname); if ($testgroup) { $gf = fopen($file_groups, "r"); while (! feof($gf)) { $read = trim(line_read($gf)); $read = preg_replace('/\t/', ' ', $read); $read = strtolower($read); $pos = strpos($read, " "); if ($pos != false) { if (substr($read, 0, $pos) == trim($groupname)) return true; } else { if ($read == trim($groupname)) return true; } } fclose($gf); if ($groupname == $CONFIG['spamgroup']) { return true; } else { /* Find section */ $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[1] == '0') { continue; } $glfp = fopen($config_dir . $menuitem[0] . "/groups.txt", 'r'); $section = ""; while ($gl = fgets($glfp)) { $group_name = preg_split("/( |\t)/", $gl, 2); if (stripos(trim($groupname), trim($group_name[0])) !== false) { fclose($glfp); return true; } } } fclose($glfp); return false; } } else { return true; } } function get_section_by_group($groupname) { global $CONFIG, $config_dir; $menulist = file($config_dir . "menu.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // Get first group in Newsgroups $groupname = preg_split("/( |\,)/", $groupname, 2); $groupname = $groupname[0]; foreach ($menulist as $menu) { if ($menu[0] == '#') { continue; } $menuitem = explode(':', $menu); if ($menuitem[1] == '0') { continue; } $section = ""; $gldata = file($config_dir . $menuitem[0] . "/groups.txt"); foreach ($gldata as $gl) { $group_name = preg_split("/( |\t)/", $gl, 2); if (strtolower(trim($groupname)) == strtolower(trim($group_name[0]))) { $section = $menuitem[0]; return $section; } } } return false; } function testGroups($newsgroups) { $groups = explode(",", $newsgroups); $count = count($groups); $return = ""; $o = 0; for ($i = 0; $i < $count; $i ++) { if (testgroup($groups[$i]) && (! function_exists("npreg_group_has_write_access") || npreg_group_has_write_access($groups[$i]))) { if ($o > 0) $return .= ","; $o ++; $return .= $groups[$i]; } } return ($return); } /* * read one line from the NNTP-server */ function line_read(&$ns) { if ($ns != false) { $t = str_replace("\n", "", str_replace("\r", "", fgets($ns, 1200))); return $t; } } /* * Split an internet-address string into its parts. An address string could * be for example: * - user@host.domain (Realname) * - "Realname" * - user@host.domain * * The address will be split into user, host (incl. domain) and realname * * $adrstring: The string containing the address in internet format * $defaulthost: The name of the host which should be returned if the * address-string doesn't contain a hostname. * * returns an hash containing the fields "mailbox", "host" and "personal" */ function address_decode($adrstring, $defaulthost) { $parsestring = trim($adrstring); $len = strlen($parsestring); $at_pos = strpos($parsestring, '@'); // find @ $ka_pos = strpos($parsestring, "("); // find ( $kz_pos = strpos($parsestring, ')'); // find ) $ha_pos = strpos($parsestring, '<'); // find < $hz_pos = strpos($parsestring, '>'); // find > $space_pos = strpos($parsestring, ')'); // find ' ' $email = ""; $mailbox = ""; $host = ""; $personal = ""; if ($space_pos != false) { if (($ka_pos != false) && ($kz_pos != false)) { $personal = substr($parsestring, $ka_pos + 1, $kz_pos - $ka_pos - 1); $email = trim(substr($parsestring, 0, $ka_pos - 1)); } } else { $email = $adrstring; } if (($ha_pos != false) && ($hz_pos != false)) { $email = trim(substr($parsestring, $ha_pos + 1, $hz_pos - $ha_pos - 1)); $personal = substr($parsestring, 0, $ha_pos - 1); } if ($at_pos != false) { $mailbox = substr($email, 0, strpos($email, '@')); $host = substr($email, strpos($email, '@') + 1); } else { $mailbox = $email; $host = $defaulthost; } $personal = trim($personal); if (substr($personal, 0, 1) == '"') $personal = substr($personal, 1); if (substr($personal, strlen($personal) - 1, 1) == '"') $personal = substr($personal, 0, strlen($personal) - 1); $result["mailbox"] = trim($mailbox); $result["host"] = trim($host); if ($personal != "") $result["personal"] = $personal; $complete[] = $result; return ($complete); } /* * Read the groupnames from groups.txt, and get additional informations * of the groups from the newsserver * * when load=0, returns cached group list * when load=1, checks if the cache should be used, and returns nothing * when force_reload=true, rebuilds group list cache */ function groups_read($server, $port, $load = 0, $force_reload = false) { global $gl_age, $file_groups, $spooldir, $config_name, $cache_index; // is there a cached version, and is it actual enough? $cachefile = $spooldir . '/' . $config_name . '-groups.dat'; // if cache is new enough, don't recreate it clearstatcache(TRUE, $cachefile); if (! $force_reload && $load == 1 && file_exists($cachefile) && (filemtime($cachefile) + $cache_index > time())) { return; } if (! $force_reload && file_exists($cachefile) && $load == 0) { // cached file exists and is new enough, so lets read it out. $file = fopen($cachefile, "r"); $data = ""; while (! feof($file)) { $data .= fgets($file, 1000); } fclose($file); $newsgroups = unserialize($data); } else { // force a refresh of the group list $ns = nntp_open($server, $port); if ($ns == false) return false; // $gf=fopen($file_groups,"r"); $gfdata = file($file_groups); // if we want to mark groups with new articles with colors, we will later // need the format of the overview $overviewformat = thread_overview_read($ns); foreach ($gfdata as $gf) { $gruppe = new newsgroupType(); $tmp = preg_replace('/\t/', ' ', trim($gf)); if (substr($tmp, 0, 1) == ":") { $gruppe->text = substr($tmp, 1); $newsgroups[] = $gruppe; } elseif (strlen($tmp) > 0) { // is there a description in groups.txt? $gr = explode(" ", $tmp, 2); if (isset($gr[1])) { // Yes $gruppe->name = $gr[0]; $desc = $gr[1]; } else { // No // no, get it from the newsserver. $gruppe->name = $tmp; if (is_file($spooldir . '/' . $tmp . '-title')) { $response = file_get_contents($spooldir . '/' . $tmp . '-title'); $desc = strrchr($response, "\t"); } else { $desc = "-"; } } if (strcmp($desc, "") == 0) $desc = "-"; $gruppe->description = $desc; fputs($ns, "GROUP " . $gruppe->name . "\r\n"); $t = explode(" ", line_read($ns)); if ($t[0] == "211") $gruppe->count = $t[1]; else { nntp_close($ns); $ns = nntp_open($server, $port); if ($ns == false) return false; fputs($ns, "GROUP " . $gruppe->name . "\r\n"); $t = explode(" ", line_read($ns)); if ($t[0] == "211") $gruppe->count = $t[1]; else continue; } // mark group with new articles with colors if ($gl_age) { fputs($ns, 'XOVER ' . $t[3] . "\r\n"); $tmp = explode(" ", line_read($ns)); if ($tmp[0] == "224") { $tmp = line_read($ns); if ($tmp != ".") { $head = thread_overview_interpret($tmp, $overviewformat, $gruppe->name); $tmp = line_read($ns); $gruppe->age = $head->date; } } } if ((strcmp(trim($gruppe->name), "") != 0) && (substr($gruppe->name, 0, 1) != "#")) $newsgroups[] = $gruppe; } } nntp_close($ns); // write the data to the cachefile file_put_contents($cachefile, serialize($newsgroups)); } if ($load == 0) { return $newsgroups; } else { return; } } function groups_show($gruppen) { global $gl_age, $frame, $spooldir, $logdir, $CONFIG, $spoolnews; if ($gruppen == false) return; global $file_thread, $text_groups; $logfile = $logdir . '/debug.log'; write_access_log(); $c = count($gruppen); $acttype = "keins"; echo ''; $subs = array(); $nonsubs = array(); $user = null; if (isset($_COOKIE['mail_name'])) { if ($userdata = get_user_mail_auth_data($_COOKIE['mail_name'])) { $userfile = $spooldir . '/' . strtolower($_COOKIE['mail_name']) . '-articleviews.dat'; } } for ($i = 0; $i < $c; $i ++) { unset($groupdisplay); $g = $gruppen[$i]; if (isset($g->text)) { if ($acttype != "text") { $acttype = "text"; } } else { if ($acttype != "group") { $acttype = "group"; } /* Display group name and description */ if (isset($userdata[$g->name])) { $lineclass = "np_thread_line2"; } else { $lineclass = "np_thread_line1"; } $groupdisplay = ''; $groupdisplay .= '
'; echo 'LatestNewsgroupMessagesLast Message
'; $groupdisplay .= ''; if (file_exists('../common/themes/' . $_SESSION['theme'] . '/images/latest.png')) { $latest_image = '../common/themes/' . $_SESSION['theme'] . '/images/latest.png'; } else { $latest_image = '../common/images/latest.png'; } $groupdisplay .= ''; $groupdisplay .= ''; $groupdisplay .= ''; $groupdisplay .= ''; $groupdisplay .= '' . group_display_name($g->name) . "\n"; if ($g->description != "-") $groupdisplay .= '

' . $g->description . '

'; // Subscribed features $filename = $spooldir . "/" . $g->name . "-lastarticleinfo.dat"; if (is_file($filename)) { $lastarticleinfo = unserialize(file_get_contents($filename)); } else { $lastarticleinfo['date'] = 0; } // Look up last article info for group (np does not write this file sometimes for some reason) $database = $spooldir . '/articles-overview.db3'; $table = 'overview'; $articles_dbh = overview_db_open($database); $articles_query = $articles_dbh->prepare('SELECT * FROM overview WHERE newsgroup=:group ORDER BY date DESC LIMIT 2'); $articles_query->execute([ 'group' => $g->name ]); $found = 0; while ($row = $articles_query->fetch()) { $found = 1; break; } $articles_dbh = null; if ($found == 1) { $lastarticleinfo['date'] = $row['date']; } if (isset($userdata[$g->name])) { $groupdisplay .= '

'; $groupdisplay .= '(unsubscribe)'; // TESTING HERE /* * file_put_contents($logfile, "\n".format_log_date()." ".$config_name." ".$g->name." is subscribed for ".$_COOKIE['mail_name'], FILE_APPEND); * file_put_contents($logfile, "\n".format_log_date()." ".$config_name." userdata=".$userdata[$g->name]." name." ".($userdata[$g->name] - $lastarticleinfo['date']), FILE_APPEND); */ if ($userdata[$g->name] < $lastarticleinfo['date']) { $groupdisplay .= '(new) '; } $groupdisplay .= ''; if ($gl_age) $datecolor = thread_format_date_color($g->age); $groupdisplay .= ''; if ($datecolor != "") $groupdisplay .= '' . $g->count . ''; else $groupdisplay .= $g->count; $groupdisplay .= ''; /* Display latest article info */ $groupdisplay .= '

'; if ($found == 1) { // $lastarticleinfo['date'] = $row['date']; // Put this in a function already! $fromoutput = explode("<", html_entity_decode($row['name'])); // Just an email address? if (strlen($fromoutput[0]) < 2) { preg_match("/\<([^\)]*)\@/", html_entity_decode($row['name']), $fromaddress); $fromoutput[0] = $fromaddress[1]; } if (strpos($fromoutput[0], "(")) { preg_match("/\(([^\)]*)\)/", html_entity_decode($row['name']), $fromaddress); $fromoutput[0] = $fromaddress[1]; } if ((isset($CONFIG['hide_email']) && $CONFIG['hide_email'] == true) && (strpos($fromoutput[0], '@') !== false)) { $lastarticleinfo['name'] = truncate_email($fromoutput[0]); } else { $lastarticleinfo['name'] = $fromoutput[0]; } } $groupdisplay .= get_date_interval(date("D, j M Y H:i T", $lastarticleinfo['date'])); $groupdisplay .= '
'; $groupdisplay .= 'by: '; $groupdisplay .= create_name_link(mb_decode_mimeheader(html_entity_decode($lastarticleinfo['name'])), $lastarticleinfo['from']); $groupdisplay .= '
'; } if (isset($groupdisplay)) { $groupdisplay .= "\n"; flush(); if (isset($userdata[$g->name])) { $subs[] = $groupdisplay; } else { $nonsubs[] = $groupdisplay; } } } // END foreach ($subs as $sub) { echo $sub; } foreach ($nonsubs as $nonsub) { echo $nonsub; } echo "
\n"; } /* * print the group names from an array to the webpage */ function groups_show_frames($gruppen) { global $gl_age, $frame, $spooldir; if ($gruppen == false) return; global $file_thread, $text_groups; $c = count($gruppen); echo '
'; $acttype = "keins"; for ($i = 0; $i < $c; $i ++) { $g = $gruppen[$i]; if (isset($g->text)) { if ($acttype != "text") { $acttype = "text"; if ($i > 0) echo '
'; echo '
'; } echo $g->text; } else { if ($acttype != "group") { $acttype = "group"; if ($i > 0) echo '
'; echo '
'; } echo '
'; echo '' . group_display_name($g->name) . "\n"; if ($gl_age) $datecolor = thread_format_date_color($g->age); echo '('; if ($datecolor != "") echo '' . $g->count . ''; else echo $g->count; echo ')'; if ($g->description != "-") echo '
' . $g->description . ''; echo '
'; } echo "\n"; flush(); } echo "
\n"; } /* * gets a list of available articles in the group $groupname */ /* * function getArticleList(&$ns,$groupname) { * fputs($ns,"LISTGROUP $groupname \r\n"); * $line=line_read($ns); * $line=line_read($ns); * while(strcmp($line,".") != 0) { * $articleList[] = trim($line); * $line=line_read($ns); * } * if (!isset($articleList)) $articleList="-"; * return $articleList; * } */ /* * Decode quoted-printable or base64 encoded headerlines * * $value: The to be decoded line * * returns the decoded line */ function headerDecode($value) { return mb_decode_mimeheader($value); } /* * calculates an Unix timestamp out of a Date-Header in an article * * $value: Value of the Date: header * * returns an Unix timestamp */ function getTimestamp($value) { global $CONFIG; return strtotime($value); } function parse_header($hdr, $number = "") { for ($i = count($hdr) - 1; $i > 0; $i --) if (preg_match("/^(\x09|\x20)/", $hdr[$i])) $hdr[$i - 1] = $hdr[$i - 1] . " " . ltrim($hdr[$i]); $header = new headerType(); $header->isAnswer = false; for ($count = 0; $count < count($hdr); $count ++) { $variable = substr($hdr[$count], 0, strpos($hdr[$count], " ")); $value = trim(substr($hdr[$count], strpos($hdr[$count], " ") + 1)); switch (strtolower($variable)) { case "from:": $fromline = address_decode(headerDecode($value), "nowhere"); if (! isset($fromline[0]["host"])) $fromline[0]["host"] = ""; $header->from = $fromline[0]["mailbox"] . "@" . $fromline[0]["host"]; $header->username = $fromline[0]["mailbox"]; if (! isset($fromline[0]["personal"])) { $header->name = ""; } else { $header->name = $fromline[0]["personal"]; } break; case "message-id:": $header->id = $value; break; case "subject:": $header->subject = headerDecode($value); break; case "newsgroups:": $header->newsgroups = $value; break; case "organization:": $header->organization = headerDecode($value); break; case "content-transfer-encoding:": $header->content_transfer_encoding = trim(strtolower($value)); break; case "content-type:": $header->content_type = array(); $subheader = explode(";", $value); $header->content_type[0] = strtolower(trim($subheader[0])); for ($i = 1; $i < count($subheader); $i ++) { $gleichpos = strpos($subheader[$i], "="); if ($gleichpos) { $subvariable = trim(substr($subheader[$i], 0, $gleichpos)); $subvalue = trim(substr($subheader[$i], $gleichpos + 1)); if (($subvalue[0] == '"') && ($subvalue[strlen($subvalue) - 1] == '"')) $subvalue = substr($subvalue, 1, strlen($subvalue) - 2); switch ($subvariable) { case "charset": $header->content_type_charset = array( strtolower($subvalue) ); break; case "name": $header->content_type_name = array( $subvalue ); break; case "boundary": $header->content_type_boundary = $subvalue; break; case "format": $header->content_type_format = array( $subvalue ); } } } break; case "references:": $ref = trim($value); while (strpos($ref, "> <") != false) { $header->references[] = substr($ref, 0, strpos($ref, " ")); $ref = substr($ref, strpos($ref, "> <") + 2); } $header->references[] = trim($ref); break; case "date:": $header->date = getTimestamp(trim($value)); break; case "followup-to:": $header->followup = trim($value); break; case "x-newsreader:": case "x-mailer:": case "x-rslight-to:": $header->rslight_to = trim($value); break; case "x-rslight-site:": $header->rslight_site = trim($value); break; case "user-agent:": $header->user_agent = trim($value); break; case "x-face:": // not ready // echo "

-".base64_decode($value)."-

"; break; case "x-no-archive:": $header->xnoarchive = strtolower(trim($value)); } } if (! isset($header->content_type[0])) $header->content_type[0] = "text/plain"; if (! isset($header->content_transfer_encoding)) $header->content_transfer_encoding = "8bit"; if ($number != "") $header->number = $number; return $header; } /* * convert the charset of a text */ function recode_charset($text, $source = false, $dest = false) { global $iconv_enable, $www_charset; if ($dest == false) $dest = $www_charset; if (($iconv_enable) && ($source != false)) { $return = iconv($source, $dest . "//TRANSLIT", $text); if ($return != "") return $return; else return $text; } else { return $text; } } function decode_body($body, $encoding) { $bodyzeile = ""; switch ($encoding) { case "base64": $body = base64_decode($body); break; case "quoted-printable": $body = Quoted_printable_decode($body); $body = str_replace("=\n", "", $body); // default: // $body=str_replace("\n..\n","\n.\n",$body); } return $body; } /* * makes URLs clickable * * $text: A text-line probably containing links. * * the function returns the text-line with HTML-Links to the links or * email-adresses. */ function html_parse($text) { global $frame_externallink; if ((isset($frame_externallink)) && ($frame_externallink != "")) { $target = ' TARGET="' . $frame_externallink . '" '; } else { $target = ' '; } $ntext = ""; // split every line into it's words $words = explode(" ", $text); $n = count($words); $is_link = 0; for ($i = 0; $i < $n; $i ++) { $word = $words[$i]; if (preg_match('/(https?|ftp|news|gopher|telnet)\:\/\/[^\",]+/i', $word)) { $is_link = 1; $nlink = trim($word, '().,'); $nlink = preg_replace('/(\<|\>|\ );/', '', $nlink); $nlink = preg_replace('/\[url=/', '', $nlink); $bbnlink = explode(']', $nlink); $nlink = $bbnlink[0]; $nword = '' . $nlink . ''; if (isset($bbnlink[1])) { $nword .= ' ' . $bbnlink[1]; } if ($nword != $word && substr($nlink, strlen($nlink) - 3) != "://") { $word = $nword; } } // add the spaces between the words if ($i > 0) $ntext .= " "; if ($is_link) { $word = preg_replace('/\[\/url\]/', '', $word); } $ntext .= $word; } return ($ntext); } /* * read the header of an article in plaintext into an array * $articleNumber can be the number of an article or its message-id. */ function readPlainHeader(&$ns, $group, $articleNumber) { fputs($ns, "GROUP $group\r\n"); $line = line_read($ns); fputs($ns, "HEAD $articleNumber\r\n"); $line = line_read($ns); if (substr($line, 0, 3) != "221") { echo $text_error["article_not_found"]; $header = false; } else { $line = line_read($ns); $body = ""; while (strcmp(trim($line), ".") != 0) { $body .= $line . "\n"; $line = line_read($ns); } return explode("\n", str_replace("\r\n", "\n", $body)); } } /* * cancel an article on the newsserver * * DO NOT USE THIS FUNCTION, IF YOU DON'T KNOW WHAT YOU ARE DOING! * * $ns: The handler of the NNTP-Connection * $group: The group of the article * $id: the Number of the article inside the group or the message-id */ function message_cancel($subject, $from, $newsgroups, $ref, $body, $id) { global $server, $port, $send_poster_host, $CONFIG, $text_error; global $www_charset; flush(); $ns = nntp_open($server, $port); if ($ns != false) { fputs($ns, "POST\r\n"); $weg = line_read($ns); fputs($ns, 'Subject: ' . quoted_printable_encode($subject) . "\r\n"); fputs($ns, 'From: ' . $from . "\r\n"); fputs($ns, 'Newsgroups: ' . $newsgroups . "\r\n"); fputs($ns, "Mime-Version: 1.0\r\n"); fputs($ns, "Content-Type: text/plain; charset=" . $www_charset . "\r\n"); fputs($ns, "Content-Transfer-Encoding: 8bit\r\n"); if ($send_poster_host) fputs($ns, 'X-HTTP-Posting-Host: ' . gethostbyaddr(getenv("REMOTE_ADDR")) . "\r\n"); if ($ref != false) fputs($ns, 'References: ' . $ref . "\r\n"); if (isset($CONFIG['organization'])) fputs($ns, 'Organization: ' . quoted_printable_encode($CONFIG['organization']) . "\r\n"); fputs($ns, "Control: cancel " . $id . "\r\n"); $body = str_replace("\n.\r", "\n..\r", $body); $body = str_replace("\r", '', $body); $b = explode("\n", $body); $body = ""; for ($i = 0; $i < count($b); $i ++) { if ((strpos(substr($b[$i], 0, strpos($b[$i], " ")), ">") != false) | (strcmp(substr($b[$i], 0, 1), ">") == 0)) { $body .= textwrap(stripSlashes($b[$i]), 78, "\r\n") . "\r\n"; } else { $body .= textwrap(stripSlashes($b[$i]), 74, "\r\n") . "\r\n"; } } fputs($ns, "\r\n" . $body . "\r\n.\r\n"); $message = line_read($ns); nntp_close($ns); } else { $message = $text_error["post_failed"]; } return $message; } function rslight_encrypt($data, $key) { $encryption_key = base64_decode($key); $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc')); $encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv); return base64_encode($encrypted . '::' . $iv); } function _rawurlencode($string) { $string = rawurlencode(str_replace('+', '%2B', $string)); return $string; } function _rawurldecode($string) { $string = rawurldecode(str_replace('%2B', '+', $string)); return $string; } function rslight_decrypt($data, $key) { $encryption_key = base64_decode($key); list ($encrypted_data, $iv) = explode('::', base64_decode($data), 2); return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv); } function group_display_name($gname) { global $config_dir; $namelist = file($config_dir . "rename.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); foreach ($namelist as $name) { if ($name[0] == '#') { continue; } $nameitem = explode(':', $name); if (! strcmp(trim($nameitem[0]), trim($gname))) { return $nameitem[1]; } } return $gname; } function check_bbs_auth($username, $password) { global $config_dir, $CONFIG; if ($username == '' && $password == '') { return false; } $workpath = $config_dir . "users/"; $username = trim(strtolower($username)); $userFilename = $workpath . $username; $keyFilename = $config_dir . "/userconfig/" . $username; // Create accounts for $anonymous and $CONFIG['server_auth_user'] if not exist if ($username == strtolower($CONFIG['anonusername'])) { if (filemtime($config_dir . "rslight.inc.php") > filemtime($userFilename)) { if ($userFileHandle = fopen($userFilename, 'w+')) { fwrite($userFileHandle, password_hash($CONFIG['anonuserpass'], PASSWORD_DEFAULT)); fclose($userFileHandle); } } } if ($username == strtolower($CONFIG['server_auth_user'])) { if (filemtime($config_dir . "rslight.inc.php") > filemtime($userFilename)) { if ($userFileHandle = fopen($userFilename, 'w+')) { fwrite($userFileHandle, password_hash($CONFIG['server_auth_pass'], PASSWORD_DEFAULT)); fclose($userFileHandle); } } } if (trim($username) == strtolower($CONFIG['anonusername']) && $CONFIG['anonuser'] != true) { return FALSE; } if ($userFileHandle = fopen($userFilename, 'r')) { $userFileInfo = fread($userFileHandle, filesize($userFilename)); fclose($userFileHandle); if (password_verify($password, $userFileInfo)) { touch($userFilename); $ok = TRUE; } else { return FALSE; } } else { $ok = FALSE; } if ($ok) { return TRUE; } else { if (isset($CONFIG['auto_create']) && $CONFIG['auto_create'] == true) { if ($userFileHandle = @fopen($userFilename, 'w+')) { fwrite($userFileHandle, password_hash($password, PASSWORD_DEFAULT)); fclose($userFileHandle); chmod($userFilename, 0666); } $newkey = base64_encode(openssl_random_pseudo_bytes(44)); if ($userFileHandle = @fopen($keyFilename, 'w+')) { fwrite($userFileHandle, 'encryptionkey:' . $newkey); fclose($userFileHandle); chmod($userFilename, 0666); } return TRUE; } else { return FALSE; } } } function check_encryption_groups($request) { global $config_path; $groupsFilename = $config_path . "encryption_ok.txt"; if ($groupsFileHandle = @fopen($groupsFilename, 'r')) { while (! feof($groupsFileHandle)) { $buffer = fgets($groupsFileHandle); $buffer = str_replace(array( "\r", "\n" ), '', $buffer); if (! strcmp($buffer, $request)) { fclose($groupsFileHandle); return TRUE; } } fclose($groupsFileHandle); } else { return FALSE; } } function set_user_config($username, $request, $newval) { global $config_dir; $userconfigpath = $config_dir . "userconfig/"; $username = strtolower($username); $userFilename = $userconfigpath . $username; $userData = file($userFilename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); $userFileHandle = fopen($userFilename, 'w'); $found = 0; foreach ($userData as $data) { if (strpos($data, $request . ':') !== FALSE) { fputs($userFileHandle, $request . ':' . $newval . "\r\n"); $found = 1; } else { fputs($userFileHandle, $data . "\r\n"); } } if ($found == 0) { fputs($userFileHandle, $request . ':' . $newval . "\r\n"); } fclose($userFileHandle); return; } function get_user_config($username, $request) { global $config_dir; $userconfigpath = $config_dir . "userconfig/"; $username = strtolower($username); $userFilename = $userconfigpath . $username; if ($userFileHandle = @fopen($userFilename, 'r')) { while (! feof($userFileHandle)) { $buffer = fgets($userFileHandle); if (strpos($buffer, $request . ':') !== FALSE) { $userdataline = $buffer; fclose($userFileHandle); $userdatafound = explode(':', $userdataline); return trim($userdatafound[1]); } } fclose($userFileHandle); return FALSE; } else { return FALSE; } } function is_multibyte($s) { return mb_strlen($s, 'utf-8') < strlen($s); } function check_spam($subject, $from, $newsgroups, $ref, $body, $msgid) { global $msgid_generate, $msgid_fqdn, $spooldir; global $CONFIG; $spamfile = tempnam($spooldir, 'spam-'); $tmpheader = 'From: ' . $from . "\r\n"; if (strpos($from, $CONFIG['anonusername'])) { $tmpheader .= "Anonymous: TRUE\r\n"; } $tmpheader .= 'Message-ID: ' . $msgid . "\r\n"; $tmpheader .= 'Subject: ' . encode_subject($subject) . "\r\n\r\n"; if ($spamFileHandle = fopen($spamfile, 'w')) { fwrite($spamFileHandle, $tmpheader); fwrite($spamFileHandle, $body); $spamcommand = $CONFIG['spamc'] . ' -E < ' . $spamfile; ob_start(); $spamresult = passthru($spamcommand, $res); $spamresult = ob_get_contents(); ob_end_clean(); $spam_fail = 1; foreach (explode(PHP_EOL, $spamresult) as $line) { $line = str_replace(array( "\n\r", "\n", "\r" ), '', $line); if (strpos($line, 'X-Spam-Checker-Version:') !== FALSE) { $spamcheckerversion = $line; $spam_fail = 0; } if (strpos($line, 'X-Spam-Level:') !== FALSE) { $spamlevel = $line; } } } fclose($spamFileHandle); unlink($spamfile); return array( 'res' => $res, 'spamresult' => $spamresult, 'spamcheckerversion' => $spamcheckerversion, 'spamlevel' => $spamlevel, 'spam_fail' => $spam_fail ); } function format_log_date() { return date('M d H:i:s'); } function create_name_link($name, $data = null) { global $CONFIG; $name = preg_replace('/\"/', '', $name); if ($data) { $data = urlencode(base64_encode($data)); } if ((strpos($name, '...@') !== false && (isset($CONFIG['hide_email']) && $CONFIG['hide_email'] == true)) && ! $data) { $return = '' . substr(htmlspecialchars($name), 0, 20) . ''; } else { $return = '' . substr(htmlspecialchars($name), 0, 20) . ''; } return ($return); } function truncate_email($address) { $before_at = explode('@', $address); $namelen = strlen($before_at[0]); if ($namelen > 3) { $endname = $namelen - 3; if ($endname > 8) $endname = 8; if ($endname < 3) $endname ++; if ($endname < 3) $endname ++; } else { $endname = $namelen; } return substr($before_at[0], 0, $endname) . '...' . substr($address, $namelen, strlen($address)); } function get_date_interval($value) { $current = time(); $datetime1 = date_create($value); $datetime2 = date_create("@$current"); $interval = date_diff($datetime1, $datetime2); if (! $interval) { return '(date error)'; } $years = $interval->format('%y') . " Years "; $months = $interval->format('%m') . " Months "; $days = $interval->format('%d') . " Days "; $hours = $interval->format('%h') . " Hours "; $minutes = $interval->format('%i') . " Minutes "; if ($interval->format('%y') == 1) { $years = $interval->format('%y') . " Year "; } if ($interval->format('%m') == 1) { $months = $interval->format('%m') . " Month "; } if ($interval->format('%d') == 1) { $days = $interval->format('%d') . " Day "; } if ($interval->format('%h') == 1) { $hours = $interval->format('%h') . " Hour "; } if ($interval->format('%i') == 1) { $minutes = $interval->format('%i') . " Minute "; } if ($interval->format('%y') == 0) { $years = ''; } if ($interval->format('%m') == 0) { $months = ''; } if ($interval->format('%d') == 0) { $days = ''; } if ($interval->format('%h') == 0) { $hours = ''; } if ($interval->format('%i') == 0) { $minutes = ''; } if ($years > 0) { $days = ''; $hours = ''; $minutes = ''; } if ($months > 0) { $hours = ''; $minutes = ''; } if ($days > 0) { $minutes = ''; } $variance = $interval->format($years . $months . $days . $hours . $minutes . ' ago'); if (strlen($variance) < 5) { $variance = " now"; } return $variance; } function get_search_snippet($body, $content_type = '') { $body = quoted_printable_decode($body); if ($content_type !== '') { $mysnippet = recode_charset($body, $content_type, "utf8"); } else { $mysnippet = $body; } if ($bodyend = strrpos($mysnippet, "\n---\n")) { $mysnippet = substr($mysnippet, 0, $bodyend); } else { if ($bodyend = strrpos($mysnippet, "\n-- ")) { $mysnippet = substr($mysnippet, 0, $bodyend); } else { if ($bodyend = strrpos($mysnippet, "\n.")) { $mysnippet = substr($mysnippet, 0, $bodyend); } } } $mysnippet = preg_replace('/\n.{0,5}>(.*)/', '', $mysnippet); $snipstart = strpos($mysnippet, ":\n"); if (substr_count(trim(substr($mysnippet, 0, $snipstart)), "\n") < 2) { $mysnippet = substr($mysnippet, $snipstart + 1); } else { $mysnippet = substr($mysnippet, 0); } return $mysnippet; } function mail_db_open($database, $table = 'messages') { try { $dbh = new PDO('sqlite:' . $database); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); exit(); } $dbh->exec("CREATE TABLE IF NOT EXISTS messages( id INTEGER PRIMARY KEY, msgid TEXT UNIQUE, mail_from TEXT, mail_viewed TEXT, rcpt_to TEXT, rcpt_viewed TEXT, rcpt_target TEXT, date TEXT, subject TEXT, message TEXT, from_hide TEXT, to_hide TEXT)"); 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 { $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, newsgroup TEXT, number TEXT, msgid TEXT, status TEXT, statusdate TEXT, statusreason TEXT, statusnotes TEXT, unique (newsgroup, msgid), unique (newsgroup, number))"); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_status on ' . $table . '(status)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_newsgroup on ' . $table . '(newsgroup)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_msgid on ' . $table . '(msgid)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_newsgroup_number on ' . $table . '(newsgroup,number)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_statusdate on ' . $table . '(statusdate)'); $stmt->execute(); return ($dbh); } function overview_db_open($database, $table = 'overview') { 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, newsgroup TEXT, number TEXT, msgid TEXT, date TEXT, datestring TEXT, name TEXT, subject TEXT, refs TEXT, bytes TEXT, lines TEXT, xref TEXT, unique (newsgroup, msgid))"); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_date on ' . $table . '(date)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_newsgroup on ' . $table . '(newsgroup)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_msgid on ' . $table . '(msgid)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_newsgroup_number on ' . $table . '(newsgroup,number)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS id_name on ' . $table . '(name)'); $stmt->execute(); return ($dbh); } function article_db_open($database, $table = 'articles') { 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, newsgroup TEXT, number TEXT UNIQUE, msgid TEXT UNIQUE, date TEXT, name TEXT, subject TEXT, search_snippet TEXT, article TEXT)"); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS db_number on ' . $table . '(number)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS db_date on ' . $table . '(date)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS db_msgid on ' . $table . '(msgid)'); $stmt->execute(); $stmt = $dbh->query('CREATE INDEX IF NOT EXISTS db_name on ' . $table . '(name)'); $stmt->execute(); $dbh->exec("CREATE VIRTUAL TABLE IF NOT EXISTS search_fts USING fts5( newsgroup, number, msgid, date, name, subject, search_snippet)"); $dbh->exec("CREATE TRIGGER IF NOT EXISTS after_articles_insert AFTER INSERT ON $table BEGIN INSERT INTO search_fts(newsgroup, number, msgid, date, name, subject, search_snippet) VALUES(new.newsgroup, new.number, new.msgid, new.date, new.name, new.subject, new.search_snippet); END;"); $dbh->exec("CREATE TRIGGER IF NOT EXISTS after_articles_delete AFTER DELETE ON $table BEGIN DELETE FROM search_fts WHERE msgid = old.msgid; END;"); return ($dbh); } function np_get_db_article($article, $group, $makearray = 1, $dbh = null) { global $config_dir, $path, $groupconfig, $config_name, $logdir, $spooldir; $logfile = $logdir . '/newsportal.log'; $msg2 = ""; $closeme = 0; $database = $spooldir . '/' . $group . '-articles.db3'; if (! $dbh) { if (! is_file($database)) { return FALSE; } $dbh = article_db_open($database); $closeme = 1; } $ok_article = 0; // By Message-ID if (! is_numeric($article)) { $stmt = $dbh->prepare("SELECT * FROM articles WHERE msgid like :terms"); $stmt->bindParam(':terms', $article); $stmt->execute(); while ($found = $stmt->fetch()) { $msg2 = $found['article']; $ok_article = 1; break; } } else { $stmt = $dbh->prepare("SELECT * FROM articles WHERE number = :terms"); $stmt->bindParam(':terms', $article); $stmt->execute(); while ($found = $stmt->fetch()) { $msg2 = $found['article']; $ok_article = 1; break; } } if ($closeme == 1) { $dbh = null; } if ($ok_article !== 1) { // file_put_contents($logfile, "\n".format_log_date()." ".$config_name." DEBUG: ".$article." from ".$group." not found in database", FILE_APPEND); return FALSE; } // file_put_contents($logfile, "\n".format_log_date()." ".$config_name." DEBUG: fetched: ".$article." from ".$group, FILE_APPEND); if ($makearray == 1) { $thisarticle = preg_split("/\r\n|\n|\r/", trim($msg2)); array_pop($thisarticle); return $thisarticle; } else { return trim($msg2); } } function get_poster_name($name) { $fromline = address_decode($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($name)); if (strlen($fromoutput[0]) < 1) { $poster_name = $fromoutput[1]; } else { $poster_name = $fromoutput[0]; } } $thisposter['name'] = $poster_name; $thisposter['from'] = $name_from; return ($thisposter); } function get_config_value($configfile, $request) { global $config_dir; if ($configFileHandle = @fopen($config_dir . '/' . $configfile, 'r')) { while (! feof($configFileHandle)) { $buffer = fgets($configFileHandle); if (strpos($buffer, $request . ':') !== FALSE) { $dataline = $buffer; fclose($configFileHandle); $datafound = explode(':', $dataline); return $datafound[1]; } } fclose($configFileHandle); return FALSE; } else { return FALSE; } } function throttle_hits() { global $CONFIG, $logdir; $logfile = $logdir . '/newsportal.log'; if (! isset($_SESSION['starttime'])) { $_SESSION['starttime'] = time(); $_SESSION['views'] = 0; } $_SESSION['views'] ++; // $loadrate = allowed article request per second $loadrate = .15; $rate = fdiv($_SESSION['views'], (time() - $_SESSION['starttime'])); if (($rate > $loadrate) && ($_SESSION['views'] > 50)) { header("HTTP/1.0 429 Too Many Requests"); if (! isset($_SESSION['throttled'])) { file_put_contents($logfile, "\n" . format_log_date() . " " . $config_name . " Too many requests from " . $_SERVER['REMOTE_ADDR'] . " throttling", FILE_APPEND); $_SESSION['throttled'] = true; if (isset($_SESSION['rsactive'])) { unset($_SESSION['rsactive']); } } exit(0); } } function get_user_mail_auth_data($user) { global $spooldir; $userdata = array(); $user = strtolower($user); $pkey_config = get_user_config($user, "pkey"); if (! isset($_COOKIE['pkey'])) { $_COOKIE['pkey'] = null; } $pkey_cookie = $_COOKIE['pkey']; if ((! isset($_COOKIE['pkey'])) || $pkey_config == false || $pkey_cookie == false) { return false; } if ($pkey_config == $pkey_cookie) { $userfile = $spooldir . '/' . $user . '-articleviews.dat'; if (is_file($userfile)) { $userdata = unserialize(file_get_contents($userfile)); } return $userdata; } return false; } function write_access_log() { global $logdir; $accessfile = $logdir . '/access.log'; $currentPageUrl = $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; file_put_contents($accessfile, "\n" . format_log_date() . " " . $currentPageUrl, FILE_APPEND); } function verify_gpg_signature($res, $signed_text) { $result = gnupg_verify($res, $signed_text, false); if ($result == false) { return false; } if ((($result[0]['summary'] > 3)) || $result[0]['validity'] == 2) { return false; // Bad signature } else { return true; // Good signature } } function is_deleted_post($group, $number) { global $spooldir; $database = $spooldir . '/history.db3'; $table = 'history'; $dbh = history_db_open($database, $table); $stmt = $dbh->prepare("SELECT * FROM $table WHERE newsgroup=:newsgroup AND number=:nicole"); $stmt->bindParam(':newsgroup', $group); $stmt->bindParam(':nicole', $number); $stmt->execute(); $status = false; while ($row = $stmt->fetch()) { if ($row['status'] == "deleted") { $status = "430 Article Deleted"; break; } } $dbh = null; return $status; } function add_to_history($group, $number, $msgid, $status, $statusdate, $statusreason = null, $statusnotes = null) { global $spooldir; $history = $spooldir . '/history.db3'; $history_dbh = history_db_open($history); $history_sql = 'INSERT OR IGNORE INTO history(newsgroup, number, msgid, status, statusdate, statusreason, statusnotes) VALUES(?,?,?,?,?,?,?)'; $history_stmt = $history_dbh->prepare($history_sql); $history_stmt->execute([ $group, $number, $msgid, $status, $statusdate, $statusreason, $statusnotes ]); $history_dbh = null; } function get_db_data_from_msgid($msgid, $group) { global $spooldir; $database = $spooldir . '/' . $group . '-articles.db3'; if (! is_file($database)) { return false; } $articles_dbh = article_db_open($database); $articles_query = $articles_dbh->prepare('SELECT * FROM articles WHERE msgid=:messageid'); $articles_query->execute([ 'messageid' => $msgid ]); $found = 0; while ($row = $articles_query->fetch()) { $found = 1; break; } $dbh = null; if ($found) { return $row; } else { return false; } } function get_data_from_msgid($msgid) { global $spooldir; $database = $spooldir . '/articles-overview.db3'; $articles_dbh = overview_db_open($database); $articles_query = $articles_dbh->prepare('SELECT * FROM overview WHERE msgid=:messageid'); $articles_query->execute([ 'messageid' => $msgid ]); $found = 0; while ($row = $articles_query->fetch()) { $found = 1; break; } $dbh = null; if ($found) { return $row; } else { return false; } } function prune_dir_by_days($path, $days) { if ($filenames = array_diff(scandir($path), array( '..', '.' ))) { foreach ($filenames as $file) { $filelastmodified = filemtime($path . $file); if ((time() - $filelastmodified) > $days * 86400) { if (is_file($path . $file)) { unlink($path . $file); } } } } else { return false; } return true; } function send_admin_message($admin, $from, $subject, $message) { global $config_dir, $spooldir; if (($to = get_config_value('aliases.conf', strtolower($admin))) == false) { $to = strtolower($admin); } $to = trim($to); $from = $to; $database = $spooldir . '/mail.db3'; $dbh = mail_db_open($database); if (! $dbh) { echo "Database error\n"; return false; } $date = time(); $msgid = '<' . md5(strtolower($to) . strtolower($from) . strtolower($subject) . strtolower($message)) . '>'; $sql = 'INSERT OR IGNORE INTO messages(msgid, mail_from, rcpt_to, rcpt_target, date, subject, message, from_hide, to_hide, mail_viewed, rcpt_viewed) VALUES(?,?,?,?,?,?,?,?,?,?,?)'; $stmt = $dbh->prepare($sql); $target = "local"; $mail_viewed = "true"; $rcpt_viewed = null; $q = $stmt->execute([ $msgid, $from, $to, $target, $date, $subject, $message, null, null, false, false ]); $dbh = null; return true; }