old header were to complicated for nothin. drop class Header, and treat it from Post
[banana.git] / include / NetNNTP.inc.php
index 8eafc5a..9b55740 100644 (file)
  *  implements some basic functions for NNTP protocol
  */
 class nntp {
-  /** socket filehandle */
-  var $ns;
-  /** debug mode */
-  var $debug;
-  /** posting allowed */
-  var $posting;
-  /** last NNTP error code */
-  var $lasterrorcode;
-  /** last NNTP error text */
-  var $lasterrortext;
+    /** socket filehandle */
+    var $ns;
+    /** debug mode */
+    var $debug;
+    /** posting allowed */
+    var $posting;
+    /** last NNTP error code */
+    var $lasterrorcode;
+    /** last NNTP error text */
+    var $lasterrortext;
 
 # Socket functions
 
-  /** get a line from server
-   * @return STRING 
-   */
+    /** get a line from server
+     * @return STRING 
+     */
 
-  function gline() {
-    $line = preg_replace("/(\r|\n)/","",fgets($this->ns,1200));
-    if ($this->debug) {
-      print "NNTP >>>> $line \n";
+    function gline() {
+        if ($this->debug) {
+            $line = trim(fgets($this->ns, 1200));
+            print "NNTP >>>> $line \n";
+            return $line;
+        }
+        return trim(fgets($this->ns, 1200));
     }
-    return $line;
-  }
-
-  /** puts a line on server
-   * @param STRING $_line line to put
-   */
-   
-  function pline($_line) {
-    if ($this->debug) {
-      $dline = preg_replace("/\r\n$/","",$_line);
-      $dline = preg_replace("/(\r|\n|\r\n)/","\nNNTP <<<< ",$dline);
-      print "NNTP <<<< $dline \n";
-    }
-    return fputs($this->ns,$_line,strlen($_line));
-  }
-  
-  /** constructor
-   * @param $_host STRING NNTP host
-   * @param $_timeout INTEGER socket timeout
-   * @param $_debug BOOLEAN debug flag (generates verbose output if on)
-   * @param $_reader BOOLEAN sends a "MODE READER" at connection if true
-   */
-
-  function nntp($_host,$_timeout=120,$_debug=0,$_reader=true) {
-    if (preg_match("/([^:]+):([^:]+)/",$_host,$regs)) {
-      $host = $regs[1];
-      $port = $regs[2];
-    } else {
-      $host = $_host;
-      $port = 119;
-    }
-    $this->ns = fsockopen($host, $port, $errno, $errstr, $_timeout);
-    $this->debug = $_debug;
-    if (!$this->ns) {
-      if ($this->debug) {
-        echo "ERREUR: $errno - $errstr <br />\n";
-      }
-      $this = false;
-      return false;
+
+    /** puts a line on server
+     * @param STRING $_line line to put
+     */
+
+    function pline($_line) {
+        if ($this->debug) {
+            $dline = preg_replace("/\r\n$/", "", $_line);
+            $dline = preg_replace("/(\r|\n|\r\n)/", "\nNNTP <<<< ", $dline);
+            print "NNTP <<<< $dline \n";
+        }
+        return fputs($this->ns, $_line, strlen($_line));
     }
-    $result = $this->gline(); 
-    $this->posting = (substr($result,0,3)=="200");
-    if ($_reader && (substr($result,0,1)=="2")) {
-      $this->pline("MODE READER\r\n");
-      $result = $this->gline();
-      $this->posting = (substr($result,0,3)=="200");
+
+    /** constructor
+     * @param $_host STRING NNTP host
+     * @param $_timeout INTEGER socket timeout
+     * @param $_debug BOOLEAN debug flag (generates verbose output if on)
+     * @param $_reader BOOLEAN sends a "MODE READER" at connection if true
+     */
+
+    function nntp($_host, $_timeout=120, $_debug=0, $_reader=true) {
+        if (preg_match("/([^:]+):([^:]+)/", $_host, $regs)) {
+            $host = $regs[1];
+            $port = $regs[2];
+        } else {
+            $host = $_host;
+            $port = 119;
+        }
+        $this->ns    = fsockopen($host, $port, $errno, $errstr, $_timeout);
+        $this->debug = $_debug;
+        if (!$this->ns) {
+            if ($this->debug) {
+                echo "ERREUR: $errno - $errstr <br />\n";
+            }
+            $this = false;
+            return false;
+        }
+        $result        = $this->gline(); 
+        $this->posting = (substr($result, 0, 3)=="200");
+        if ($_reader && ($result{0}=="2")) {
+            $this->pline("MODE READER\r\n");
+            $result        = $this->gline();
+            $this->posting = ($result{0}=="200");
+        }
+        return ($result{0}=="2");
     }
-    return (substr($result,0,1)=="2");
-  }
 
 # strict NNTP Functions [RFC 977]
 # see http://www.faqs.org/rfcs/rfc977.html
 
-  /** authentification
-   * @param $_user STRING login
-   * @param $_pass INTEGER password
-   * @return BOOLEAN true if authentication was successful
-   */
-
-  function authinfo($_user,$_pass) {
-    $user = preg_replace("/(\r|\n)/","",$_user);
-    $pass = preg_replace("/(\r|\n)/","",$_pass);
-    $this->pline("AUTHINFO USER $user\r\n");
-    $this->gline();
-    $this->pline("AUTHINFO PASS $pass\r\n");
-    $result=$this->gline();
-    if (substr($result,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
-    }
-    return true;
-  }
-
-  /** retrieves an article
-   * MSGID is a numeric ID a shown in article's headers. MSGNUM is a
-   * server-dependent ID (see X-Ref on many servers) and retriving 
-   * an article by this way will change the current article pointer.
-   * If an error occur, false is returned. 
-   * @param $_msgid STRING MSGID or MSGNUM of article
-   * @return ARRAY lines of the article
-   * @see body
-   * @see head
-   */
-
-  function article($_msgid="") {
-    $msgid = preg_replace("/(\r|\n)/","",$_msgid);
-    $this->pline("ARTICLE $msgid\r\n");
-    $result = $this->gline();
-    if (substr($result,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
-    }
-    $result = $this->gline();
-    while ($result != ".") {
-      $array[] = $result;
-      $result = $this->gline();
-    }
-    return $array;
-  }
-
-  /** post a message
-   * if an error occur, false is returned
-   * @param $_message STRING message to post
-   * @return STRING MSGID of article 
-   */
-
-  function post($_message) {
-    if (is_array($_message)) {
-      $message=join("\n",$_message);
-    } else {
-      $message=$_message;
-    }
-    $this->pline("POST \r\n");
-    $result=$this->gline();
-    if (substr($result,0,1)!="3") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
-    }
-    $this->pline($message."\r\n.\r\n");
-    $result = $this->gline();
-    if (substr($result,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
-    }
-    if (substr($result,0,1)=="2") {
-      if (preg_match("/(<[^@>]+@[^@>]+>)/",$result,$regs)) {
-        return $regs[0];
-      } else {
+    /** authentification
+     * @param $_user STRING login
+     * @param $_pass INTEGER password
+     * @return BOOLEAN true if authentication was successful
+     */
+
+    function authinfo($_user, $_pass) {
+        $user = preg_replace("/(\r|\n)/", "", $_user);
+        $pass = preg_replace("/(\r|\n)/", "", $_pass);
+        $this->pline("AUTHINFO USER $user\r\n");
+        $this->gline();
+        $this->pline("AUTHINFO PASS $pass\r\n");
+        $result=$this->gline();
+        if ($result{0}!="2") {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
         return true;
-      }
     }
-    return false;
-  }
-
-  /** fetches the body of an article
-   * params are the same as article
-   * @param $_msgid STRING MSGID or MSGNUM of article
-   * @return ARRAY lines of the article
-   * @see article
-   * @see head
-   */
-  
-  function body($_msgid="") {
-    $msgid = preg_replace("/(\r|\n)/","",$_msgid);
-    $this->pline("BODY $msgid\r\n");
-    $result = $this->gline();
-    if (substr($result,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
-    }
-    $result = $this->gline();
-    while ($result != ".") {
-      $array[] = $result;
-      $result = $this->gline();
+
+    /** retrieves an article
+     * MSGID is a numeric ID a shown in article's headers. MSGNUM is a
+     * server-dependent ID (see X-Ref on many servers) and retriving 
+     * an article by this way will change the current article pointer.
+     * If an error occur, false is returned. 
+     * @param $_msgid STRING MSGID or MSGNUM of article
+     * @return ARRAY lines of the article
+     * @see body
+     * @see head
+     */
+
+    function article($_msgid="") {
+        $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
+        $this->pline("ARTICLE $msgid\r\n");
+        $result = $this->gline();
+        if ($result{0} != '2') {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        $result = $this->gline();
+        while ($result != ".") {
+            $array[] = $result;
+            $result  = $this->gline();
+        }
+        return $array;
     }
-    return $array;
-  }
-
-  /** fetches the headers of an article
-   * params are the same as article
-   * @param $_msgid STRING MSGID or MSGNUM of article
-   * @return ARRAY lines of the article
-   * @see article
-   * @see body
-   */
-  
-  function head($_msgid="") {
-    $msgid = preg_replace("/(\r|\n)/","",$_msgid);
-    $this->pline("HEAD $msgid\r\n");
-    $result = $this->gline();
-    if (substr($result,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
+
+    /** post a message
+     * if an error occur, false is returned
+     * @param $_message STRING message to post
+     * @return STRING MSGID of article 
+     */
+
+    function post($_message) {
+        if (is_array($_message)) {
+            $message=join("\n", $_message);
+        } else {
+            $message=$_message;
+        }
+        $this->pline("POST \r\n");
+        $result=$this->gline();
+        if ($result{0} != '3') {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        $this->pline($message."\r\n.\r\n");
+        $result = $this->gline();
+        if ($result{0} != '2') {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        if ($result{0} == '2') {
+            if (preg_match("/(<[^@>]+@[^@>]+>)/", $result, $regs)) {
+                return $regs[0];
+            } else {
+                return true;
+            }
+        }
+        return false;
     }
-    $result = $this->gline();
-    while ($result != ".") {
-      $array[] = $result;
-      $result = $this->gline();
+
+    /** fetches the body of an article
+     * params are the same as article
+     * @param $_msgid STRING MSGID or MSGNUM of article
+     * @return ARRAY lines of the article
+     * @see article
+     * @see head
+     */
+
+    function body($_msgid="") {
+        $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
+        $this->pline("BODY $msgid\r\n");
+        $result = $this->gline();
+        if ($result{0} != '2') {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        $result = $this->gline();
+        while ($result != ".") {
+            $array[] = $result;
+            $result  = $this->gline();
+        }
+        return $array;
     }
-    return $array;
-  }
-  
-  /** set current group
-   * @param $_group STRING 
-   * @return ARRAY array : nb of articles in group, MSGNUM of first article, MSGNUM of last article, and group name
-   */
-  
-  function group($_group) {
-    $group = preg_replace("/(\r|\n)/","",$_group);
-    $this->pline("GROUP $group\r\n");
-    $line = $this->gline();
-    if (substr($line,0,1)!="2") {
-      $this->lasterrorcode = substr($line,0,3);
-      $this->lasterrortext = substr($line,4);
-      return false;
+
+    /** fetches the headers of an article
+     * params are the same as article
+     * @param $_msgid STRING MSGID or MSGNUM of article
+     * @return ARRAY lines of the article
+     * @see article
+     * @see body
+     */
+
+    function head($_msgid="") {
+        $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
+        $this->pline("HEAD $msgid\r\n");
+        $result = $this->gline();
+        if ($result{0}!="2") {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        $result = $this->gline();
+        while ($result != ".") {
+            $array[] = $result;
+            $result  = $this->gline();
+        }
+        return $array;
     }
-    if (preg_match("/^2\d{2} (\d+) (\d+) (\d+) ([^ ]+)/",
-    $line,$regs)) {
-      return array($regs[1],$regs[2],$regs[3],$regs[4]);
+
+    /** set current group
+     * @param $_group STRING 
+     * @return ARRAY array : nb of articles in group, MSGNUM of first article, MSGNUM of last article, and group name
+     */
+
+    function group($_group) {
+        $group = preg_replace("/(\r|\n)/", "", $_group);
+        $this->pline("GROUP $group\r\n");
+        $line = $this->gline();
+        if ($line{0}!="2") {
+            $this->lasterrorcode = substr($line, 0, 3);
+            $this->lasterrortext = substr($line, 4);
+            return false;
+        }
+        if (preg_match("/^2\d{2} (\d+) (\d+) (\d+) ([^ ]+)/", $line, $regs)) {
+            return array($regs[1], $regs[2], $regs[3], $regs[4]);
+        }
+        return false;
     }
-    return $false;
-  }
-
-  /** set the article pointer to the previous article in current group
-   * @return STRING MSGID of article
-   * @see next
-   */
-  
-  function last() {
-    $this->pline("LAST \r\n");
-    $line = $this->gline();
-    if (substr($line,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
+
+    /** set the article pointer to the previous article in current group
+     * @return STRING MSGID of article
+     * @see next
+     */
+
+    function last() {
+        $this->pline("LAST \r\n");
+        $line = $this->gline();
+        if ($line{0}!="2") {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
+            return "<{$regs[1]}>";
+        }
+        return false;
     }
-    if (preg_match("/^2\d{2} \d+ <([^>]+)>/",$line,$regs)) {
-      return "<{$regs[1]}>";
+
+    /** set the article pointer to the next article in current group
+     * @return STRING MSGID of article
+     * @see last
+     */
+
+    function next() {
+        $this->pline("NEXT \r\n");
+        $line = $this->gline();
+        if ($line{0}!="2") {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
+            return "<{$regs[1]}>";
+        }
+        return false;
     }
-    return $false;
-  }
-  
-  /** set the article pointer to the next article in current group
-   * @return STRING MSGID of article
-   * @see last
-   */
-  
-  function next() {
-    $this->pline("NEXT \r\n");
-    $line = $this->gline();
-    if (substr($line,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
+
+    /** set the current article pointer
+     * @param $_msgid STRING MSGID or MSGNUM of article
+     * @return BOOLEAN true if authentication was successful, error code otherwise
+     * @see article
+     * @see body
+     */
+
+    function nntpstat($_msgid) {
+        $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
+        $this->pline("STAT $msgid\r\n");
+        $line  = $this->gline();
+        if ($line{0}!="2") {
+            $this->lasterrorcode = substr($result, 0, 3);
+            $this->lasterrortext = substr($result, 4);
+            return false;
+        }
+        if (preg_match("/^2\d{2} \d+ <([^>]+)>/", $line, $regs)) {
+            return "<{$regs[1]}>";
+        }
+        return false;
     }
-    if (preg_match("/^2\d{2} \d+ <([^>]+)>/",$line,$regs)) {
-      return "<{$regs[1]}>";
+
+    /** returns true if posting is allowed
+     * @return BOOLEAN true if posting is allowed lines 
+     */
+
+    function postok() {
+        return ($this->posting);
     }
-    return $false;
-  }
-
-  /** set the current article pointer
-   * @param $_msgid STRING MSGID or MSGNUM of article
-   * @return BOOLEAN true if authentication was successful, error code otherwise
-   * @see article
-   * @see body
-   */
-  
-  function nntpstat($_msgid) {
-    $msgid = preg_replace("/(\r|\n)/","",$_msgid);
-    $this->pline("STAT $msgid\r\n");
-    $line = $this->gline();
-    if (substr($line,0,1)!="2") {
-      $this->lasterrorcode = substr($result,0,3);
-      $this->lasterrortext = substr($result,4);
-      return false;
+
+    /** gets information about all active newsgroups
+     * @return ARRAY group name => (MSGNUM of first article, MSGNUM of last article, NNTP flags)
+     * @see newgroups
+     */
+
+    function liste() {
+        $this->pline("LIST\r\n");
+        if (substr($this->gline(), 0, 1)!="2") return false;
+        $result = $this->gline();
+        while ($result != ".") {
+            preg_match("/([^ ]+) (\d+) (\d+) (.)/", $result, $regs);
+            $array[$regs[1]] = array(intval($regs[2]), intval($regs[3]), intval($regs[4]));
+            $result          = $this->gline();
+        }
+        return $array;
     }
-    if (preg_match("/^2\d{2} \d+ <([^>]+)>/",$line,$regs)) {
-      return "<{$regs[1]}>";
+
+    /** get information about recent newsgroups 
+     * same as list, but information are limited to newgroups created after $_since
+     * @param $_since INTEGER unix timestamp
+     * @param $_distributions STRING distributions 
+     * @return ARRAY same format as liste
+     * @see liste
+     */
+
+    function newgroups($_since, $_distributions="") {
+#assume $_since is a unix timestamp
+        $distributions = preg_replace("/(\r|\n)/", "", $_distributions);
+        $this->pline("NEWGROUPS ".gmdate("ymd His", $_since)
+                ." GMT $distributions\r\n");
+        if (substr($this->gline(), 0, 1)!="2") {
+            return false;
+        }
+        $result = $this->gline();
+        $array  = array();
+        while ($result != ".") {
+            preg_match("/([^ ]+) (\d+) (\d+) (.)/", $result, $regs);
+            $array[$regs[1]] = array(intval($regs[2]), intval($regs[3]), intval($regs[4]));
+            $result          = $this->gline();
+        }
+        return $array;
     }
-    return false;
-  }
-  
-  /** returns true if posting is allowed
-   * @return BOOLEAN true if posting is allowed lines 
-   */
-  
-  function postok() {
-    return ($this->posting);
-  }
-
-  /** gets information about all active newsgroups
-   * @return ARRAY group name => (MSGNUM of first article, MSGNUM of last article, NNTP flags)
-   * @see newgroups
-   */
-  
-  function liste() {
-    $this->pline("LIST\r\n");
-    if (substr($this->gline(),0,1)!="2") return false;
-    $result = $this->gline();
-    while ($result != ".") {
-      preg_match("/([^ ]+) (\d+) (\d+) (.)/",$result,$regs);
-      $array[$regs[1]]=array(intval($regs[2]),intval($regs[3]),
-        intval($regs[4]));
-      $result = $this->gline();
+
+    /** gets a list of new articles
+     * @param $_since INTEGER unix timestamp
+     * @parma $_groups STRING pattern of intersting groups 
+     * @return ARRAY MSGID of new articles
+     */
+
+    function newnews($_since, $_groups="*", $_distributions="") {
+        $distributions = preg_replace("/(\r|\n)/", "", $_distributions);
+        $groups = preg_replace("/(\r|\n)/", "", $_groups);
+        $array  = array();
+#assume $since is a unix timestamp
+        $this->pline("NEWNEWS $_groups ".gmdate("ymd His", $_since)." GMT $distributions\r\n");
+        if (substr($this->gline(), 0, 1)!="2") {
+            return false;
+        }
+        $result = $this->gline();
+        while ($result != ".") {
+            $array[] =  $result;
+            $result  = $this->gline();
+        }
+        return $array;
     }
-    return $array;
-  }
-
-  /** get information about recent newsgroups 
-   * same as list, but information are limited to newgroups created after $_since
-   * @param $_since INTEGER unix timestamp
-   * @param $_distributions STRING distributions 
-   * @return ARRAY same format as liste
-   * @see liste
-   */
-  
-  function newgroups($_since,$_distributions="") {
-    #assume $_since is a unix timestamp
-    $distributions = preg_replace("/(\r|\n)/","",$_distributions);
-    $this->pline("NEWGROUPS ".gmdate("ymd His",$_since)
-    ." GMT $distributions\r\n");
-    if (substr($this->gline(),0,1)!="2") return false;
-    $result = $this->gline();
-    $array=array();
-    while ($result != ".") {
-      preg_match("/([^ ]+) (\d+) (\d+) (.)/",$result,$regs);
-      $array[$regs[1]]=array(intval($regs[2]),intval($regs[3]),
-        intval($regs[4]));
-      $result = $this->gline();
+
+    /** Tell the remote server that I am not a user client, but probably another news server
+     * @return BOOLEAN true if sucessful
+     */
+
+    function slave() {
+        $this->pline("SLAVE \r\n");
+        return (substr($this->gline(), 0, 1)=="2");
     }
-    return $array;
-  }
-
-  /** gets a list of new articles
-   * @param $_since INTEGER unix timestamp
-   * @parma $_groups STRING pattern of intersting groups 
-   * @return ARRAY MSGID of new articles
-   */
-  
-  function newnews($_since,$_groups="*",$_distributions="") {
-    $distributions = preg_replace("/(\r|\n)/","",$_distributions);
-    $groups = preg_replace("/(\r|\n)/","",$_groups);
-    $array=array();
-    #assume $since is a unix timestamp
-    $this->pline("NEWNEWS $_groups ".gmdate("ymd His",$_since)
-    ." GMT $distributions\r\n");
-    if (substr($this->gline(),0,1)!="2") return false;
-    $result = $this->gline();
-    while ($result != ".") {
-      $array[] =  $result;
-      $result = $this->gline();
+
+    /** implements IHAVE method
+     * @param $_msgid STRING MSGID of article
+     * @param $_message STRING article
+     * @return BOOLEAN 
+     */
+
+    function ihave($_msgid, $_message=false) {
+        $msgid = preg_replace("/(\r|\n)/", "", $_msgid);
+        if (is_array($message)) {
+            $message = join("\n", $_message);
+        } else {
+            $message = $_message;
+        }
+        $this->pline("IHAVE $msgid \r\n");
+        $result = $this->gline();
+        if ($message && ($result{0}=="3")) {
+            $this->pline("$message\r\n.\r\n");
+            $result = $this->gline();
+        }
+        return ($result{0}=="2");
     }
-    return $array;
-  }
-
-  /** Tell the remote server that I am not a user client, but probably another news server
-   * @return BOOLEAN true if sucessful
-   */
-  
-  function slave() {
-    $this->pline("SLAVE \r\n");
-    return (substr($this->gline(),0,1)=="2");
-  }
-
-  /** implements IHAVE method
-   * @param $_msgid STRING MSGID of article
-   * @param $_message STRING article
-   * @return BOOLEAN 
-   */
-  
-  function ihave($_msgid,$_message=false) {
-    $msgid = preg_replace("/(\r|\n)/","",$_msgid);
-    if (is_array($message)) 
-         $message=join("\n",$_message);
-       else 
-         $message=$_message;
-    $this->pline("IHAVE $msgid \r\n");
-    $result=$this->gline();
-    if ($message && (substr($result,0,1)=="3")) {
-      $this->pline("$message\r\n.\r\n");
-      $result=$this->gline();
+
+    /** closes connection to server
+     */
+
+    function quit() {
+        $this->pline("QUIT\r\n");
+        $this->gline();
+        fclose($this->ns);
     }
-    return (substr($result,0,1)=="2");
-  }
-
-  /** closes connection to server
-   */
-  
-  function quit() {
-    $this->pline("QUIT\r\n");
-    $this->gline();
-    fclose($this->ns);
-  }
 
 # NNTP Extensions [RFC 2980]
 
-  /** Returns the date on the remote server
-   * @return INTEGER timestamp 
-   */
-  
-  function date() {
-    $this->pline("DATE \r\n");
-    $result = $this->gline();
-    if (preg_match("/^111 (\d{4})(\d{2})(\d{2})"
-    ."(\d{2})(\d{2})(\d{2})$/",$result,$r)) {
-      return gmmktime($r[4],$r[5],$r[6],$r[2],$r[3],$r[1]);
+    /** Returns the date on the remote server
+     * @return INTEGER timestamp 
+     */
+
+    function date() {
+        $this->pline("DATE \r\n");
+        $result = $this->gline();
+        if (preg_match("/^111 (\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/", $result, $r)) {
+            return gmmktime($r[4], $r[5], $r[6], $r[2], $r[3], $r[1]);
+        }
+        return false;
     }
-    return false;
-  }
-
-  /** returns group descriptions
-   * @param $_pattern STRING pattern of intersting groups
-   * @return ARRAY group name => description
-   */
-  
-  function xgtitle($_pattern="*") {
-    $pattern = preg_replace("/(\r|\n)/","",$_pattern);
-    $this->pline("XGTITLE $pattern \r\n");
-    if (substr($this->gline(),0,1)!="2") return false;
-    $result = $this->gline();
-    while ($result != ".") {
-      preg_match("/([^ \t]+)( |\t)+(.+)$/",$result,$regs);
-      $array[$regs[1]]=$regs[3];
-      $result = $this->gline();
+
+    /** returns group descriptions
+     * @param $_pattern STRING pattern of intersting groups
+     * @return ARRAY group name => description
+     */
+
+    function xgtitle($_pattern="*") {
+        $pattern = preg_replace("/(\r|\n)/", "", $_pattern);
+        $this->pline("XGTITLE $pattern \r\n");
+        if (substr($this->gline(), 0, 1)!="2") return false;
+        $result = $this->gline();
+        while ($result != ".") {
+            preg_match("/([^ \t]+)( |\t)+(.+)$/", $result, $regs);
+            $array[$regs[1]] = $regs[3];
+            $result          = $this->gline();
+        }
+        return $array;
     }
-    return $array;
-  }
-
-  /** obtain the header field $hdr for all the messages specified
-   * @param $_hdr STRING name of the header (eg: 'From')
-   * @param $_range STRING range of articles 
-   * @return ARRAY MSGNUM => header value
-   */
-  
-  function xhdr($_hdr,$_range="") {
-    $hdr = preg_replace("/(\r|\n)/","",$_hdr);
-    $range = preg_replace("/(\r|\n)/","",$_range);
-    $this->pline("XHDR $hdr $range \r\n");
-    if (substr($this->gline(),0,1)!="2") return false;
-    $result = $this->gline();
-    while ($result != ".") {
-      preg_match("/([^ \t]+) (.*)$/",$result,$regs);
-      $array[$regs[1]]=$regs[2];
-      $result = $this->gline();
+
+    /** obtain the header field $hdr for all the messages specified
+     * @param $_hdr STRING name of the header (eg: 'From')
+     * @param $_range STRING range of articles 
+     * @return ARRAY MSGNUM => header value
+     */
+
+    function xhdr($_hdr, $_range="") {
+        $hdr    = preg_replace("/(\r|\n)/", "", $_hdr);
+        $range  = preg_replace("/(\r|\n)/", "", $_range);
+        $this->pline("XHDR $hdr $range \r\n");
+        if (substr($this->gline(), 0, 1)!="2") {
+            return false;
+        }
+            
+        $array  = array();
+        while (($result = $this->gline()) != '.') {
+            preg_match("/([^ \t]+) (.*)$/", $result, $regs);
+            $array[$regs[1]] = $regs[2];
+        }
+        return $array;
     }
-    return $array;
-  }
 
+    /** obtain the header field $_hdr matching $_pat for all the messages specified
+     * @param $_hdr STRING name of the header (eg: 'From')
+     * @param $_range STRING range of articles 
+     * @param $_pat STRING pattern
+     * @return ARRAY MSGNUM => header value
+     */
+
+    function xpat($_hdr, $_range, $_pat) {
+        $hdr   = preg_replace("/(\r|\n)/", "", $_hdr);
+        $range = preg_replace("/(\r|\n)/", "", $_range);
+        $pat   = preg_replace("/(\r|\n)/", "", $_pat);
+        $this->pline("XPAT $hdr $range $pat\r\n");
+        if (substr($this->gline(), 0, 1)!="2") {
+            return false;
+        }
+        $result = $this->gline();
+        while ($result != ".") {
+            preg_match("/([^ \t]+) (.*)$/", $result, $regs);
+            $array[$regs[1]] = $regs[2];
+            $result          = $this->gline();
+        }
+        return $array;
+    }
 }
 
 ?>