_setCurrentGroup($group)) !== NULL) { $timestring = date("ymd His", $timestamp); $command = "NEWNEWS $group $timestring"; if (($newids = $this->_command($command, '230')) != NULL) { return $newids; } else { $this->_logError("command \"$command\" failed, status: " . $this->last_command_status[0] . ", " . $this->last_command_status[1]); } } else { $this->_logError("cannot set group $group"); } return NULL; } /** * creates an array of NNTP Message-IDs of new messages in the given group * since $lastmsg * * @param $group name of the newsgroup * @param $lastmsg message number of last message read previously * @param $maxmsg max number of Message-IDs to be returned * * @return * array of NNTP Message-IDs, indexed by the message number in * the group */ function getNewNewsXover($group,$lastmsg,$maxmsg) { if (($curGroup = $this->_setCurrentGroup($group)) !== NULL) { $command = "XOVER $lastmsg-".($lastmsg+$maxmsg); $xover = $this->_command($command, '224'); if ($xover !== FALSE && $xover !== NULL) { $newids = array(); foreach ($xover as $line) { $fields = explode("\t", $line); $newids[$fields[0]] = $fields[4]; } return $newids; } else { // don't log an error for 420 - No article(s) selected // as it just means there are no new articles if ($this->last_command_status[0] == '420') { $this->_logInfo("command \"$command\" on $group failed, status: " . $this->last_command_status[0] . ", " . $this->last_command_status[1] . " (meaning: there are no messages in that range)"); } else { $this->_logError("command \"$command\" on $group failed, status: " . $this->last_command_status[0] . ", " . $this->last_command_status[1]); } } } else { $this->_logError("cannot set group $group"); } return NULL; } /** * creates an array of NNTP headers * * @param $ids array of NNTP message-IDs * * @return * array of NNTP headers */ function getHeaders($ids) { return $this->getArticles($ids, TRUE, FALSE); } /** * creates an array of article bodies * * @param $ids array of NNTP message-IDs * * @return * array of article bodies */ function getBodies($ids) { if (($bodies = $this->getArticles(ids, FALSE, TRUE)) !== NULL) { $articles = array(); foreach ($ids as $idx => $id) { $articles['id'] = $bodies[$idx]; } return $articles; } return NULL; } /** * creates an array of NNTP headers, articles, or both * * @param $ids array of NNTP message-IDs * @param $headers indicates whether headers should be returned (default TRUE) * @param $bodies indicates whether bodies should be returned (default TRUE) * * @return * array of headers, bodies, or arrays containing the header and * body of an article */ function getArticles($ids, $headers=TRUE, $bodies=TRUE) { $throw = NULL; _netnews_trace("called getArticles "); do { $items = array(); foreach ($ids as $msgnum => $ident) { if ($headers && $bodies) { $item = $this->getArticle($ident, $msgnum); } else if ($headers) { $item = $this->getHeader($ident, $msgnum); } else { $item = $this->getBody($ident); } if ($item === NULL && $this->last_command_status[0] != '430') { $throw = "Cannot get header and/or body for $ident"; break 2; } if ($item !== NULL) { $items[] = $item; } } return $items; } while (FALSE); if ($throw !== NULL) { $this->_logError($throw); } return NULL; } /** * posts a message to the news server, returns TRUE on succes * * @param $header header as an array indexed with NNTP header labels, * associated with their values * @param $body message body (string of text) * @param $return_id flag indicating whether the message-ID that the server * may return, should be returned in $msgid (default FALSE) * @param &$msgid ref for returning message-ID * * @return * TRUE on success, FALSE on failure */ function post($header, $body, $return_id=FALSE, $msgid=NULL) { $canPost = TRUE; /* * check for the required header fields */ foreach ($this->_requiredHeaderFields as $field => $flag) { if ($flag && !array_key_exists($field, $header)) { $this->_logError("$field does not exist in message header"); $canPost = FALSE; } } if (!$canPost) { return FALSE; } /* * start posting */ if ($this->_send("POST")) { list($code, $msg) = $this->_status(); if ($code == '340') { /* * if requested, see if the newsserver returned a message id */ if ($return_id) { $msgid = ''; if (preg_match('/(<[^>]*>)/', $msg, $matches)) { $msg_id = $matches[1]; } } $sendfailed = FALSE; /* * first handle the required headers */ foreach ($this->_requiredHeaderFields as $field => $flag) { if (!$this->_send("$field: " . $header[$field])) { list($code, $msg) = $this->_status(); $this->_logError("posting failed. $code: $msg"); $sendfailed = TRUE; break; } } /* * then any other headers */ if (!$sendfailed) { foreach($header as $field => $value) { if (!array_key_exists($field, $this->_requiredHeaderFields)) { if(!$this->_send("$field: $value")) { list($code, $msg) = $this->_status(); $this->_logError("posting failed. $code: $msg"); $sendfailed = TRUE; break; } } } } if (!$sendfailed) { $this->_send("\r\n$body\r\n."); list($code, $msg) = $this->_status(); if ($code == '240') { return TRUE; } else { $this->_logError("posting failed. $code: $msg"); return FALSE; } } } else { $this->_logError("posting failed. $code: $msg"); return FALSE; } } else { $this->_logError("posting failed. Unknown reason."); } return FALSE; } /** * retieves the body of a message from the news server * * @param $ident message-ID or message number * @param $type indicates what part of the body should be returned: * 'text' (default): only the plaintext part * 'raw' the entirey bosy as read through NNTP * * @return * article body as an array of lines */ function getBody($ident, $type='text') { _netnews_trace("called getBody"); switch ($type) { case 'raw' : return $this->_command("BODY $ident", '222'); break; case 'text' : if (($header = $this->getHeader($ident)) && ($msginfo = $this->_get_format_info($header))) { return $this->_command("BODY $ident", '222', TRUE, $msginfo); } else { return $this->_command("BODY $ident", '222'); } } return NULL; } /** * retrieves the NNTP header of a message. * * @param $ident message-ID or message number * * @return * article header as an array of NNTP header values, indexed by * the NNTP header labels, or NULL on failure */ function getHeader($ident, $msgnum=0) { if (($head = $this->_command("HEAD $ident", '221')) !== NULL) { $header = array(); foreach ($head as $line) { /* * parse the header lines into label => value pairs * * \TODO integrate these two regexps, shame on you! */ if (preg_match('/^([^:]+): (.*)$/', $line, $matches)) { $header[$this->_normalize($matches[1])] = $matches[2]; if ($matches[1] == 'Content-Type' ) { if (preg_match('/;\s*(boundary)="([^"]+)"/i', $matches[2], $boundmatch)) { $this->_add_boundary($header, $boundmatch[2]); } } } else if (preg_match('/([^:]+):/', $line, $matches)) { $header[$matches[1]] = ''; } else if (preg_match('/^\s*(boundary)="([^"]+)"/i', $line, $matches)) { $this->_add_boundary($header, $matches[2]); } else { $this->_logError("Invalid header line '$line' in header:", $head); return NULL; } } if ($this->headerValidates($header)) { // insert the message number into the header if ($msgnum != 0) { $header[LOCAL_MSGNUM] = $msgnum; $this->_logInfo("message $ident has msgnum $msgnum"); } return $header; } } return NULL; } /** * retrieves an article from the news server * * @param $ident message-ID or message number * * @return * array with header as the first member, body as the second, NULL * on failure */ function getArticle($ident, $msgnum) { $header = $this->getHeader($ident, $msgnum); _netnews_trace("called getArticle $ident $msgnum"); $body = $this->getBody($ident); if ($header !== NULL && $body !== NULL) { return array($header, $body); } $this->_logInfo("null header or body result on getArticle() '$body'"); return NULL; } /** * gets the highest existing message number in a group * * @param $group group name * * @return * message number, 0 if group invalid */ function getLastMsgNum($group) { if ($curGroup = $this->_setCurrentGroup($group)) { return $curGroup['last']; } return 0; } /** * sets the logging level * * @param $errors boolean if error messages should be logged * @param $infos boolean if info messages should be logged * @param $protocol boolean if the actual NNTP messages and responses should * be logged */ function setLogging($errors=TRUE, $infos=FALSE, $protocol=FALSE) { $this->_logErrors = $errors; $this->_logInfos = $infos; $this->_logProtocol = $protocol; } /** * gets the messages logged so far * * @return * array with logging messages */ function getLog($html=False, $filter=NULL) { if (isset($filter)) { array_walk($this->log, array($this, '_logFilter'), $filter); } if ($html) { return implode('
', $this->log); } return $this->log; } /*private*/ function _logFilter($array, $idx, $regex) { if (!preg_match($regex, $array[$idx])) { array_splice($array, $idx, 1); } } /** * checks if the header contains all the required NNTP values * * @param $header the NNTP header * @param $post flag indicating that only fields required for * posting should be checked (default TRUE) * * @return * TRUE of FALSE */ function headerValidates($header, $post=TRUE) { foreach ($this->_requiredHeaderFields as $label => $flag) { if (!$post || ($post && $flag)) { if (!array_key_exists($label, $header)) { return FALSE; } } } return TRUE; } /** * finds NNTP header of a message in a group where a given field in the * header has the requested value. searching starts at a specified message * message * * @param $group name of the newsgroup * @param $key label of the field to match on * @param $value value to match on * @param $from number of first (earliest) message to search * * @return * header found, or NULL if no header found */ function findHeaderWith($group, $key, $value, $from=1) { if ($curGroup = $this->_setCurrentGroup($group)) { $this->_logInfo("scan $group for $key => $value from message " . $curGroup['last'] . " to " . $curGroup['first']); for ($cur = $from; $cur <= $curGroup['last']; ++$cur) { if ($hdr = $this->getHeader($cur)) { if ($hdr[$key] == $value) { return $hdr; } } } } else { $this->_logError("Cannot set group to $group"); } return NULL; } /** * sets the current newsgroup on the news server * * @param $group name of the newsgroup * * @return * NNTP info for current newsgroup, or FALSE if setting the group failed */ function setGroup($group) { if ($curGroup = $this->_setCurrentGroup($group)) { return $curGroup; } return False; } /** * checks access to news server * * @return * TRUE if login succeeded, otherwise FALSE */ function checkAccess() { if ($this->_connect()) { $this->_disconnect(); return TRUE; } return FALSE; } /* * the constructor for the nntpserver class */ function /*__construct*/nntpserver($config) { $this->_config = $config; $this->_handle = NULL; $this->_server = $config['nntp_server']; $this->_port = $config['nntp_port']; $this->_authuser = $config['nntp_user']; $this->_authpasswd = $config['nntp_passwd']; $this->_authed = FALSE; $this->_log = array(); $this->_logErrors = TRUE; $this->_logInfos = FALSE; $this->_logProtocol = FALSE; /* * fields that are required in a header. Those marked TRUE are * required for posting */ $this->_requiredHeaderFields = array("From" => TRUE, "Subject" => TRUE, "Newsgroups" => TRUE); } /* * destructor. disfunctional in PHP4? * * \TODO: check and document */ function __destruct() { $this->_disconnect(); } /** * disconnects from the news server */ function done() { $this->_disconnect(); } /** * sets the name for a callback function to be used by the _log() function * * @param $function name of callback function */ function setTracer($function) { $this->tracer = $function; } /* * sets the current group */ /*private*/ function _setCurrentGroup($group) { $command = "GROUP $group"; if ($this->_send($command)) { list($code, $msg) = $this->_status(); if ($code[0] = '2') { if (preg_match('/^(\d+) (\d+) (\d+)/', $msg, $matches)) { list($match, $count, $first, $last) = $matches; return array('count' => $count, 'first' => $first, 'last' => $last); } else { $this->_logError("Could not parse GROUP reply: $msg"); } } } $this->_logError("Command \"$command\" failed"); return NULL; } /* * connects to the newsserver, with authentication if set */ /*private*/ function _connect() { if ($this->_handle) { return TRUE; } $this->_logInfo('trying to connect to ' . "$this->_server:$this->_port"); $this->_handle = fsockopen($this->_server, $this->_port, $errno, $errstr, 2); if (!$this->_handle) { $this->_logError("_connect(): $errstr ($errno)"); $this->_handle = NULL; return FALSE; } list($code, $msg) = $this->_status(); if ($code[0] != '2') { $this->_logInfo("_connect(): connected, but: $msg ($code)"); } else { $this->maypost = ($code[2] == '0') ? TRUE : FALSE; } /* * take care of authentication, if required */ $this->_logInfo("user is '".$this->_authuser."' - this is ".((!is_null($this->_authuser))?"not":"")." NULL" ); if (!is_null($this->_authuser)) { $this->_send("AUTHINFO USER $this->_authuser"); list($code, $msg) = $this->_status(); if ($code[0] == '3') { $this->_send("AUTHINFO PASS $this->_authpasswd"); list($code, $msg) = $this->_status(); if ($code[0] == '2') { $this->_authed = TRUE; } } if (!$this->_authed) { $this->_disconnect(); return FALSE; } } $this->_send('MODE READER'); list($code, $msg) = $this->_status(); $this->_logInfo('_connect(): connected (to ' . "$this->_server:$this->_port)"); return TRUE; } /* * disconnects from the news server */ /*private*/ function _disconnect() { if ($this->_handle) { /* * send quit, get the status for logging purposes. no attempt * is made to check the status */ $this->_send('QUIT'); list($code, $msg) = $this->_status(); fclose($this->_handle); $this->_handle = NULL; $this->_logInfo('_disconnect(): disconnected from ' . "$this->_server:$this->_port"); } } /* * sends command $msg to the newsserver, checks the status info * returned by the news server against $expStatus, and * returns the output as an array if $output is TRUE. * Returns TRUE or FALSE if no output is requested. */ /*private*/ function _command($msg, $expStatus='xxx', $output=TRUE, $msginfo=NULL) { _netnews_trace("called _command($msg)"); $this->_send($msg); list($code, $msg) = $this->_status(); $this->last_command_status = array($code, $msg); if ($expStatus == 'xxx' || strncmp($code, $expStatus, strlen($expStatus)) == 0) { if ($output) { return $this->_receive($msginfo); } else { return TRUE; } } else { return NULL; } } /* * sends a message to the news server */ /*private*/ function _send($msg) { if ($this->_connect()) { @fwrite($this->_handle, "$msg\r\n"); if (preg_match('/^(AUTHINFO) (USER|PASS)/', $msg, $matches)) { $msg = "$matches[0] xxxxxx"; } $this->_logNNTP("[C] $msg"); return TRUE; } else { $this->_logError("Cannot send($msg), connect failed"); } return FALSE; } /* * receives output from the news server, and returns it as an array of lines */ /*private*/ function _receive($msginfo=NULL) { if ($msginfo) { switch ($msginfo['type']) { case 'uuencode': case 'yEnc': $message = $this->_receive_body_Xencode($msginfo); break; case 'mime_multi': case 'mime_mixed': $message = $this->_receive_body_mime_multi($msginfo); break; } //$message = $this->_receive_body($msginfo); } else { /* * no format info given, keep your eyes open for embedded attachments * anyway */ $message = array(); $lineno = 0; while (($line = chop(@fgets($this->_handle))) != '.') { $this->_logNNTP("[S] $line"); $message[] = $line; /* NOTE: A newsreader like Xnews (and no doubt others) can embed attachments in the body without any info in the header. This code does embedded attachment scanning. Note that since users could enter these kind of lines by hand, there is a small chance that this code will rip a range of lines out of the message body without a good reason to to so :-) Though the risk is rather small, it could be made smaller if the newsreaders that can do this are known, so the bodies actually scanned could be reduced to only those originating from such newsreaders. */ if (preg_match(YENC_BEGIN_REGEXP, $line) && !isset($uucbegin)) { $yencbegin = $lineno; } if (preg_match(YENC_END_REGEXP, $line) && isset($yencbegin)) { $count = $lineno - $yencbegin + 1; $attachment_enc = implode("\r\n",$message); $this->_logInfo('Found a yenc block. decoding now'); require_once('yenc.php'); $yenc = new yenc(); $yenc_attachment = $yenc->decode($attachment_enc); // yEnc seems to fail more often than not. // Can't be bothered with it. if(!$yenc_attachment){ $this->_logError("yEncoding error found when retrieving '".$yenc->filename."': ".$yenc->error); $message[] = "---\nEncoding error - attached yEnc file '".$yenc->filename."' was unable to be extracted.\n".$yenc->error."\n---"; // save corrupt attachment anyway for analysis. But set fileperm to '000'; $this->attachments[$yenc->filename] = array('filename'=>$yenc->filename, 'filedata'=>$yenc->attachment, 'fileraw'=>$attachment_enc, 'fileperm'=>'000' ); } else { $this->attachments[$yenc->filename] = array('filename'=>$yenc->filename, 'filedata'=>$yenc_attachment); } array_splice($message, $yencbegin, $count); $lineno -= $count; $yencbegin = NULL; } if (preg_match(UUC_BEGIN_REGEXP, $line) && !isset($yencbegin)) { $uucbegin = $lineno; $this->_logNNTP("UUCBEGIN, Line:$uucbegin"); } if (preg_match(UUC_END_REGEXP, $line) && isset($uucbegin)) { $count = $lineno - $uucbegin + 1; $this->_logNNTP("UUCEND, Line:$lineno"); $attachment_enc = implode("\r\n",array_slice($message, $uucbegin, $count)); $this->_logInfo('extracting uuencoded block from message from $uucbegin for $count '); require_once('Mail/MimeDecode.php'); $this->attachments =& Mail_mimeDecode::uudecode($attachment_enc); $this->_logNNTP("Extracted binary attachment: \n".print_r($this->attachments,1) ); // if($this->discard_attachments){ array_splice($message, $uucbegin, $count); // } $lineno -= $count; $uucbegin = NULL; } ++$lineno; } $this->_logNNTP("[S] $line"); } $this->_logInfo('Finished _receive . Message length is '.count($message).' lines, '.strlen(join("",$message)).' chars'); return $message; } /* * recieves the plain text from a message body that contains an * uuencoded attachment */ /*private*/ function _receive_body_Xencode($msginfo) { _netnews_trace('Recieving Xencode '); $message = array(); $skip = False; while (($line = chop(@fgets($this->_handle))) != '.') { if (preg_match($msginfo['skipfrom'], $line)) { $this->_logInfo("matching $line against " . $msginfo['skipfrom']); $skip = True; $this->_logInfo("Skipping encoded part of body"); } if (!$skip) { $this->_logNNTP("[S] $line"); $message[] = $line; } if (preg_match($msginfo['skipto'], $line)) { $skip = FALSE; $this->_logInfo("Stopped skipping encoded part of body"); } } $this->_logNNTP("[S] $line"); return $message; } /* * receives the plain text from a message body that is in MIME format */ /*private*/ function _receive_body_mime_multi($msginfo) { $mime_body = $this->_receive(); $this->_logInfo("mime_multi body: " . print_r($body, TRUE)); $message = array(); $part = array(); $header = FALSE; $body = FALSE; $plain = array(); $html = array(); foreach ($mime_body as $line) { if (preg_match($msginfo['sectionlabel'], $line)) { $this->_logInfo("saw a sectionlabel"); if ($part) { if (array_key_exists('Content-Type', $part)) { switch ($part['Content-Type']) { case 'text/plain' : if (!preg_match('/^inline$/i', $part['Content-Disposition'])) { $plain = array_merge($plain, $part['body']); } break; case 'text/html': $html = $part['body']; break; } } else { /* * just read a part without a Content-Type. if the last line of the * body is not empty, treat it as text/plain */ if ($part['body'][count($part['body'])-1] != '') { $plain = array_merge($plain, $part['body']); } } $message[] = $part; } if (preg_match($msginfo['end'], $line)) { $this->_logInfo("saw sectionlabel-end"); break; } if (is_array($part)) { $this->_logInfo("part:" . print_r($part, TRUE)); } $part = array(); $header = TRUE; $body = FALSE; } elseif ($header) { if ($line == '') { $header = FALSE; $body = TRUE; $part['body'] = array(); } elseif (preg_match('/^([^:]+): (.*)$/', $line, $matches)) { $value = $matches[2]; if (preg_match('/;/', $value)) { $this->_match_mime_values($value, $part); } $part[$matches[1]] = preg_replace('/;.*$/', '', $matches[2]); } elseif (preg_match('/^\s*.*$/', $line)) { $this->_match_mime_values($line, $part); } else { $this->_logError("unrecognized part of header: \"$line\""); } } elseif ($body) { $part['body'][] = $line; } } /* * return, in order of preference: plain text, html or the first part */ if (isset($plain)) { return $plain; } elseif (isset($html)) { return $html; } elseif (isset($message[0]['body'])) { return $message[0]['body']; } /* * couldn't parse it at all, return the whole body */ return $mime_body; } /*private*/ function _match_mime_values($str, &$header) { if (preg_match_all(MIME_VALUES_REGEXP, $str, $all_matches, PREG_SET_ORDER)) { //$this->_logInfo("mime values seen in \"$str\"(".$all_matches[0].")"); foreach ($all_matches as $valmatch) { if (!array_key_exists('mime', $header)) { $header['mime']=array(); } //$this->_logInfo('mime: '.$valmatch[1].'='.$valmatch[2]); $header['mime'][$valmatch[1]] = $valmatch[2]; } } } /* * tries to determine the format of a message based on the * information available in the header */ /*private*/ function _get_format_info($hdr) { $msginfo = NULL; if (array_key_exists('Mime-Version', $hdr)) { $this->_logInfo("

mime recognized: ".$hdr['Content-Type']."
"); if (preg_match('/^multipart\/alternative;$/i', $hdr['Content-Type'])) { $this->_logInfo("

mime_multi recognized
"); $msginfo = array( 'type' => 'mime_multi', 'Content-Type' => $hdr['Content-Type'], 'sectionlabel' => '/^--' . preg_quote($hdr[BOUNDARIES][0]) . '/i', 'end' => '/^' . preg_quote($hdr[BOUNDARIES][0]) . '--$/i', ); } if (preg_match('/multipart\/mixed/i', $hdr['Content-Type'])) { $msginfo = array( 'type' => 'mime_mixed', 'Content-Type' => $hdr['Content-Type'], 'sectionlabel' => '/^--' . preg_quote($hdr[BOUNDARIES][0]) . '/i', 'end' => '/^' . preg_quote($hdr[BOUNDARIES][0]) . '--$/i', ); } } elseif (preg_match('/ -\s*(\d+)\s+attachment(\s?)$/i', $hdr['Subject'], $matches) || preg_match( '/ -\s+File\s+\d+\s+of\s+\d+\s+-\s+yEnc\s+\"[^\"]+\"\s+\d+\s+bytes\s+\(\d+\/\d+\)$/i', $hdr['Subject']) ) { /* * could be an yEnc attachment? */ $this->_logInfo("Looks like a yEnc msginfo found"); $msginfo = array( 'type' => 'yEnc', 'skipfrom' => '/^\=ybegin .* line\=\d+ size\=\d+ name\=.*$/i', 'skipto' => '/^\=yend size=\d+ crc32=[\da-f]+$/i' ); // =ybegin part=2 total=2 line=128 size=488254 name=H72_eng_gb_colTanBert_02.jpg } elseif (preg_match('/ -\s*([\w \._]+)$/i', $hdr['Subject'], $matches)) { /* * looks like a filename at the end of the subject: Subject: Ter afwisseling - iets moois? - mooi_zon.jpg begin 644 mooi_zon.jpg ... end * * Matches the filename from the header against the filename in * the "begin" line, but case insensitive */ $this->_logInfo("uuencode msginfo found"); $msginfo = array( 'type' => 'uuencode', 'name' => $matches[1], 'skipfrom' => '/^begin [\d]+ ' . preg_quote($matches[1]) . '$/i', 'skipto' => '/^end$/i' ); } return $msginfo; } /* * gets status from the news server */ /*private*/ function _status() { if ($this->_handle) { $status = chop(@fgets($this->_handle, 1024)); $this->_logNNTP("[S] $status"); if(preg_match('/^(\d+)\s*(.+)$/', $status, $statinfo)) { return(array($statinfo[1], $statinfo[2])); } else if ($status == ".") { // not really an expected response, or is it? // anyway, it's not bad news $this->_logInfo( "Received unexpected response '.'. Returned status 2XX"); return (array('2XX', '')); } else { return(array('400','')); } } else { $this->_logError("Cannot read status, invalid handle"); } return FALSE; } /* * set of internal logging functions */ /*private*/ function _logError($msg) { if ($this->_logErrors) { $this->_log('(E) '.$msg); } } /*private*/ function _logInfo($msg) { if ($this->_logInfos) { $this->_log('(I) '.$msg); } } /*private*/ function _logNNTP($msg) { if ($this->_logProtocol) { $this->_log('(P) '.$msg); } } /*private*/ function _log($msg) { /* * send the message through the tracer callback, if set */ if (isset($this->tracer) && function_exists($this->tracer)) { $tracer = $this->tracer; $tracer('(nntpserver) ' . $msg); } $this->log[] = $msg; // always log for yourself } /* * return a fixed spelling for some header labels so that this module does * not need to be bothered about spelling (case) of those labels */ /*private*/ function _normalize($label) { static $normtab = array( '/^content-type$/i' => 'Content-Type', '/^mime-version$/i' => 'Mime-Version', ); foreach ($normtab as $regexp => $normform) { if (preg_match($regexp, $label)) { $label = $normform; break; } } return $label; } /* * adds boundary information to a header */ /*private*/ function _add_boundary(&$header, $value) { if (!array_key_exists(BOUNDARIES, $header)) { $header[BOUNDARIES] = array(); } $header[BOUNDARIES][] = $value; } } function checkNNTPAccess($srvconfig) { $server = new nntpserver($srvconfig); $server->setLogging(TRUE, TRUE, TRUE); if ($server->checkAccess()) { return TRUE; } return FALSE; } ?>