[grisbi-cvs] grisbi-web/newsportal/lib check.php, NONE, 1.1 message.inc.php, NONE, 1.1 post.inc.php, NONE, 1.1 thread.inc.php, NONE, 1.1 types.inc.php, NONE, 1.1 validator.inc, NONE, 1.1

NIEL Gérald gegeweb at users.sourceforge.net
Mon May 24 17:03:52 CEST 2010


Update of /cvsroot/grisbi/grisbi-web/newsportal/lib
In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv18681/lib

Added Files:
	check.php message.inc.php post.inc.php thread.inc.php 
	types.inc.php validator.inc 
Log Message:

news version off newsportal

--- NEW FILE: thread.inc.php ---
<?
/*
 *  NewsPortal: Functions for handling threads
 *
 *  Copyright (C) 2002-2004 Florian Amrhein
 *  E-Mail: newsportal at florian-amrhein.de
 *  Web: http://florian-amrhein.de
 *
 *  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
[...991 lines suppressed...]
  // "rewind" the subthread to the first article in the subthread
  $current=$id;
  flush();
  while(isset($thread[$id]->references)) {
    foreach($thread[$id]->references as $reference) {
      if((trim($reference)!='') && (isset($thread[$reference]))) {
        $id=$reference;
        continue 2;
      }
    }
    break;
  }

  // walk through the thread and fill up $subthread
  // use the recursive helper-function thread_getsubthreadids_recursive
  $subthread=thread_getsubthreadids_recursive($id);
  return $subthread;
}

?>
--- NEW FILE: validator.inc ---
<?
/*
 * Validator
 *
 * Validierung von Formulareingaben
 *
 * Autor: Florian Amrhein
 */

class formvalidate {
  var $fields=array();
  /*
   * Überprüft ein komplettes Formular auf korrekte Eingaben, und liefert
   * false, falls irgendwo ein Fehler vorhanden ist.
   * Setzt intern die entsprechenden Daten, die show_error und
   * is_error zum Abfragen der Daten benötigen.
   */
  function validate() {
    $errors=false;
    foreach($this->fields as $field) {
      switch($field->typ) {
        case "text":
        case "textarea":
        case "checkbox":
        case "radiobutton":
          // Basteln wegen scheiss PHP
          $valtmp=$field->validator;
          // feld_leer*feld_darf_leer + 
          // nicht_feld_leer*(testfkt.ex.*testfkt +
          //   nicht_testfkt.ex)
          if(
             (
              (
               (!isset($_REQUEST[$field->name])) ||
               (trim($_REQUEST[$field->name])=="")
              ) &&
              (isset($field->empty)) &&
              ($field->empty==true)
             ) || (
              (isset($_REQUEST[$field->name])) &&
              (trim($_REQUEST[$field->name])!="") &&
              (
               ($field->validator==false) ||
               ($field->validator!=false) &&
               (($errmsg=$valtmp($_REQUEST[$field->name]))===true)
              )
             )
            ) {
            // Feld leer und darf leer sein, oder
            // feld voll und (testfunktion existiert und testfkt.=true
            //                oder testfunktion existiert nicht)
            $this->fields[$field->name]->error=false;
          } else {
            // Feld leer und darf nicht leer sein, oder
            // Feld voll und testfkt.ex und testfunktion=false
            $errors=true;
            $this->fields[$field->name]->error=true;
            if(isset($errmsg)) {
              $this->fields[$field->name]->errormessage=$errmsg;
              unset($errmsg);
            }
          }
          break;
        case "pulldown":
        case "check-text":
        case "radio-text":
          if((isset($field->empty)) && (!$field->empty) &&
             ((!isset($_REQUEST[$field->name])) ||
              (trim($_REQUEST[$field->name])=="") ||
              (($_REQUEST[$field->name]=="_frei") &&
               ((!isset($_REQUEST[$field->name."_frei"])) ||
                (trim($_REQUEST[$field->name."_frei"])=="")
               )
              )
             )
            ) {
            $errors=true;
            $this->fields[$field->name]->error=true;
          } else {
            $this->fields[$field->name]->error=false;
          }
          break;
      }
//      echo '<p>eval: '.$field->name.': '.$_REQUEST[$field->name].'</p>';
    }
    return !$errors;
  }


  /*
   * liefert true, falls $name fehlerhaft ausgefüllt wurde
   */
  function is_error($name) {
    return $this->fields[$name]->error;   
  }

  /*
   * Liefert die individuelle Fehlermeldung, falls $name fehlerhaft
   * ausgefüllt wurde. Falls keine Meldung vorliegt, wird false
   * geliefert.
   */
  function geterrormessage($name) {
    if(isset($this->fields[$name]->errormessage))
      return $this->fields[$name]->errormessage;
    else
      return false;
  }

  /*
   * Zeigt gegebenenfalls eine Fehlermeldung an, falls $name nicht
   * korrekt ausgefüllt wurde
   */
  function show_error($name) {
    if($this->is_error($name)) {
      echo "<p>fehler</p>";
    }
  }

  /*
   * Zeigt den Titel zu einem Feld an. Ist das zugehörige Feld fehlerhaft 
   * ausgefüllt worden, wird es (z.B. farblich) markiert.
   *
   * $name: Name des Feldes
   * $text: auszugebener Text
   */
  function show_title($name,$text) {
    if($this->is_error($name))
      echo '<font color="red"><b>'.$text.'</b></font>';
    else
      echo $text;
  }

  /*
   * Zeigt die Daten an, die der Benutzer in das Formular, ob richtig oder
   * falsch ist egal, eingegeben hatte.
   */
  function show_value($name) {
    echo stripslashes($_REQUEST[$name]);
  }

  /*
   * Liefert Variablenwerte ohne vorherige Umkodierung/Zusammenfassung
   * zurück
   */
  function value($name) {
    if(is_array($_REQUEST[$name])) {
      $a=$_REQUEST[$name];
      return $a;
    }
    return stripslashes($_REQUEST[$name]);
  }

  /* Liefert Variablenwerte mit vorheriger Umkodierung/Zusammenfassung
   * zurück. Vor allem wichtig bei Typ check-text und radio-text, wo
   * der eigentliche Inhalt über mehrere Variablen verteilt ist, bzw.
   * teilweise gar nicht zum Zuge kommt (freies Textfeld ausgefüllt,
   * aber nicht angeklickt)
   */
  function get_value($name) {
    if(is_array($_REQUEST[$name])) {
      $a=$_REQUEST[$name];
      // Freies Textfeld?
      if(in_array("_frei",$a)) {
        if((isset($_REQUEST[$name.'_frei'])) &&
           ($_REQUEST[$name.'_frei']!=""))
          $a[]=$_REQUEST[$name.'_frei'];
        unset($a[$name.'_frei']);
      }

      return $a;
    } else if(($_REQUEST[$name]=='_frei') &&
              ($this->fields[$name]->typ=='radio-text')) {
      return stripslashes($_REQUEST[$name.'_frei']);
    } else
      return stripslashes($_REQUEST[$name]);
  }
  
  /*
   * gibt einfach nur " checked" aus, wenn $name den wert $value enthält.
   * Nötig für das Vorselektieren von Knöpfen
   */
  function show_checked($name,$value) {
    global $fields;
    if(($this->fields[$name]->typ!="checkbox") &&
       ($this->fields[$name]->typ!="check-text")) {
      if($this->value($name)==$value) {
        if($this->fields[$name]->typ=="pulldown")
          echo ' selected';
        else
          echo ' checked';
      }
    } else {
      if(in_array($value,$this->value($name))) 
        echo ' checked';
    }
  }

  function show_selected($name,$value) {
    global $fields;
    if(($this->fields[$name]->typ!="checkbox") &&
       ($this->fields[$name]->typ!="check-text")) {
      if($this->value($name)==$value) {
        echo ' selected';
      }
    }
  }


  /*
   * Registriert eine Variable als zum Formular gehörend
   *
   * $name:  Name der Variablen
   * $typ:   Art der Eingabe:
   *         - text:         Textfeld mit einfacher freier Eingabe
   *         - textarea:     Mehrzeiliger Text mit freier Eingabe
   *         - checkbox:     Ankreuzfelder, mehrere gleichzeitig
   *         - radiobutton:  Ankreuzfelder, nur eins gleichzeitig
   *         - pulldown:     Pulldown-Menu, nut eins gleichzeitig
   *         - check-text:   Ankreuzfelder+Textfeld, mehrere gleichzeitig
   *         - radio-text:   Ankreuzfelder+Textfeld, maximal eins
   * $empty: Darf das entsprechende Feld leer gelassen werden?
   *         bzw. mindestens kein angekreuzt bzw. ausgefüllt?
   * $validator: Information, wie der Inhalt auf Korrektheit geprüft
   *             werden soll
   * $errmsg: Fehlermeldung, die bei erkanntem Fehler ausgegeben 
   *          werden soll
   */
  function register($name,$typ,$empty=true,$validator=false,$errmsg=false) {
    $var->name=$name;
    $var->typ=$typ;
    $var->empty=$empty;
    $var->validator=$validator;
    $var->errmsg=$errmsg;
    $this->fields[$name]=$var;
  }

  /*
   * der Konstruktor
   */
  function formvalidate() {
  }
}
?>

--- NEW FILE: message.inc.php ---
<?
/*
 *  NewsPortal: Functions for handling single messages
 *
 *  Copyright (C) 2002-2006 Florian Amrhein
 *  E-Mail: newsportal at florian-amrhein.de
 *  Web: http://florian-amrhein.de
 *
 *  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
 */

function message_parse($rawmessage) {
  global $attachment_delete_alternative,$attachment_uudecode,$www_charset;
  global $iconv_enable;
  // Read the header of the message:
  $count_rawmessage=count($rawmessage);
  $message = new messageType;
  $rawheader=array();
  $i=0;
  while ($rawmessage[$i] != "") {
    $rawheader[]=$rawmessage[$i];
    $i++;
  }
  // Parse the Header:
  $message->header=parse_header($rawheader);
  // Now we know if the message is a mime-multipart message:
  $content_type=split("/",$message->header->content_type[0]);
  if ($content_type[0]=="multipart") {
    $message->header->content_type=array();
    // We have multible bodies, so we split the message into its parts
    $boundary="--".$message->header->content_type_boundary;
    // lets find the first part
    while($rawmessage[$i] != $boundary)
      $i++;
    $i++;
    $part=array();
    while($i<=$count_rawmessage) {
      if (($rawmessage[$i]==$boundary) || ($i==$count_rawmessage-1) ||
          ($rawmessage[$i]==$boundary.'--')) {
        $partmessage=message_parse($part);
        // merge the content-types of the message with those of the part
        for ($o=0; $o<count($partmessage->header->content_type); $o++) {
          $message->header->content_type[]=
            $partmessage->header->content_type[$o];
          $message->header->content_type_charset[]=
            $partmessage->header->content_type_charset[$o];
          $message->header->content_type_name[]=
            $partmessage->header->content_type_name[$o];
          $message->header->content_type_format[]=
            $partmessage->header->content_type_format[$o];
          $message->body[]=$partmessage->body[$o];
        }
        $part=array();
      } else {
        if ($i<$count_rawmessage)
          $part[]=$rawmessage[$i];
      }
      if ($rawmessage[$i]==$boundary.'--') break;
      $i++;
    }
    // Is this a multipart/alternative multipart-message? Do we have to
    // delete all non plain/text parts?
    if (($attachment_delete_alternative) &&
        ($content_type[1]=="alternative")) {
      $plaintext=false;
      for ($o=0; $o<count($message->header->content_type); $o++) {
        if ($message->header->content_type[$o]=="text/plain")
          $plaintext=true; // we found at least one text/plain
      }
      if ($plaintext) {    // now we can delete the other parts
        for ($o=0; $o<count($message->header->content_type); $o++) {
          if ($message->header->content_type[$o]!="text/plain") {
            unset($message->header->content_type[$o]);
            unset($message->header->content_type_name[$o]);
            unset($message->header->content_type_charset[$o]);
            unset($message->header->content_type_format[$o]);
            unset($message->body[$o]);
          }
        }
      }
    }
  } else {
    // No mime-attachments in the message:
    $body="";
    $uueatt=0; // as default we have no uuencoded attachments
    for($i++;$i<$count_rawmessage; $i++) {
      // do we have an inlay uuencoded file?
      if ((strtolower(substr($rawmessage[$i],0,5))!="begin") ||
          ($attachment_uudecode==false)) {
        $body.=$rawmessage[$i]."\n";
      // yes, it seems, we have!
      } else {
        $old_i=$i;
        $uue_infoline_raw=$rawmessage[$i];
        $uue_infoline=explode(" ",$uue_infoline_raw);
        $uue_data="";
        $i++;
        while($rawmessage[$i]!="end") {
          if (strlen(trim($rawmessage[$i])) > 2)
            $uue_data.=$rawmessage[$i]."\n";
          $i++;
        }
        // now write the data in an attachment
        $uueatt++;
        $message->body[$uueatt]=uudecode($uue_data);
        $message->header->content_type_name[$uueatt]="";
        for ($o=2; $o<count($uue_infoline); $o++)
          $message->header->content_type_name[$uueatt].=$uue_infoline[$o];
        $message->header->content_type[$uueatt]=
          get_mimetype_by_filename($message->header->content_type_name[$uueatt]);
      }
    }
    //if ($message->header->content_type[0]=="text/plain") {
    $body=decode_body($body,$message->header->content_transfer_encoding);
    $body=recode_charset($body,
                         $message->header->content_type_charset[0],
                         $www_charset);
    if ($body=="") $body=" ";
    //}
    $message->body[0]=$body;
  }
    if (!isset($message->header->content_type_charset))
      $message->header->content_type_charset=array($www_charset);
    if (!isset($message->header->content_type_name))
      $message->header->content_type_name=array("unnamed");
    if (!isset($message->header->content_type_format))
      $message->header->content_type_format=array("fixed");
  for ($o=0; $o<count($message->body); $o++) {
    if (!isset($message->header->content_type_charset[$o]))
      $message->header->content_type_charset[$o]=$www_charset;
    if (!isset($message->header->content_type_name[$o]))
      $message->header->content_type_name[$o]="unnamed";
    if (!isset($message->header->content_type_format[$o]))
      $message->header->content_type_format[$o]="fixed";
  }
  return $message;
}


/*
 * read an article from the newsserver or the spool-directory
 *
 * $id: the Message-ID of an article
 * $bodynum: the number of the attachment:
 *          -1: return only the header without any bodies or attachments.
 *           0: the body
 *           1: the first attachment...
 *
 * The function returns an article as an messageType or false if the article
 * doesn't exists on the newsserver or doesn't contain the given
 * attachment.
 */
function message_read($id,$bodynum=0,$group="") {
  global $cache_articles,$spooldir,$text_error,$ns;
  if (!testGroup($group)) {
    echo $text_error["read_access_denied"];
    return;
  }
  $message = new messageType;
  if ((isset($cache_articles)) && ($cache_articles == true)) {
    // Try to load a cached article
    if ((ereg('^[0-9]+$',$id)) && ($group != ''))
      $filename=$group.'_'.$id;
    else
      $filename=base64_encode($id);
    $cachefilename_header=$spooldir."/".$filename.'.header';
    $cachefilename_body=$spooldir."/".$filename.'.body';
    if (file_exists($cachefilename_header)) {
      $cachefile=fopen($cachefilename_header,"r");
      $message->header=unserialize(fread($cachefile,filesize($cachefilename_header)));
      fclose($cachefile);
    } else {
      unset($message->header);
    }
    // Is a non-existing attachment of an article requested?
    if ((isset($message->header)) &&
        ($bodynum!= -1) &&
        (!isset($message->header->content_type[$bodynum])))
      return false;
    if ((file_exists($cachefilename_body.$bodynum)) &&
        ($bodynum != -1)) {
      $cachefile=fopen($cachefilename_body.$bodynum,"r");
      $message->body[$bodynum]=
        fread($cachefile,filesize($cachefilename_body.$bodynum));
      fclose($cachefile);
    }
  }
  if ((!isset($message->header)) ||
      ((!isset($message->body[$bodynum])) &&
       ($bodynum != -1))) {
    if (!isset($ns)) {
      $ns=nntp_open();
    }
    if ($group != "") {
      fputs($ns,"GROUP ".$group."\r\n");
      $line=line_read($ns);
    }
    fputs($ns,'ARTICLE '.$id."\r\n");
    $line=line_read($ns);
    if (substr($line,0,3) != "220") {
      // requested article doesn't exist on the newsserver. Now we
      // should check, if the thread stored in the spool-directory
      // also doesnt't contain that article...
      thread_cache_removearticle($group,$id);
      return false;
    }
    $rawmessage=array();
    $line=line_read($ns);
    while(strcmp($line,".") != 0) {
      $rawmessage[]=$line;
      $line=line_read($ns);
    }
    $message=message_parse($rawmessage);
    if (ereg('^[0-9]+$',$id)) $message->header->number=$id;
    // write header, body and attachments to the cache
    if ((isset($cache_articles)) && ($cache_articles == true)) {
      $cachefile=fopen($cachefilename_header,"w");
      if ($cachefile) {
        fputs($cachefile,serialize($message->header));
      }
      fclose($cachefile);
      for ($i=0; $i<count($message->header->content_type); $i++) {
        if (isset($message->body[$i])) {
          $cachefile=fopen($cachefilename_body.$i,"w");
          fwrite($cachefile,$message->body[$i]);
          fclose($cachefile);
        }
      }
    }
  }
  return $message;
}

function textwrap($text, $wrap=80, $break="\n",$maxlen=false){
  $len = strlen($text);
  if ($len > $wrap) {
    $h = '';        // massaged text
    $lastWhite = 0; // position of last whitespace char
    $lastChar = 0;  // position of last char
    $lastBreak = 0; // position of last break
    // while there is text to process
    while ($lastChar < $len && (($maxlen==false) || (strlen($h)<$maxlen))) {
      $char = substr($text, $lastChar, 1); // get the next character
      // if we are beyond the wrap boundry and there is a place to break
      if (($lastChar - $lastBreak > $wrap) && ($lastWhite > $lastBreak)) {
        $h .= substr($text, $lastBreak, ($lastWhite - $lastBreak)) . $break;
        $lastChar = $lastWhite + 1;
        $lastBreak = $lastChar;
      }
      // You may wish to include other characters as valid whitespace...
      if ($char == ' ' || $char == chr(13) || $char == chr(10)) {
        $lastWhite = $lastChar; // note the position of the last whitespace
      }
      $lastChar = $lastChar + 1; // advance the last character position by one
    }
    $h .= substr($text, $lastBreak); // build line
  } else {
    $h = $text; // in this case everything can fit on one line
  }
  return $h;
}
/*
 * Displays a (Sub)-Thread. Is used in article.php
 *
 * $id:    Message-ID (not number!) of an article in the thread
 * $group: name of the newsgroup
 */
function message_thread($id,$group,$thread,$highlightids=false) {
  $current=$id;
  // set the highlightid, if not set
  if(!$highlightids)
    $highlightids=array($current);
  flush();
  // find the first article in the subthread of $id
  while(isset($thread[$id]->references)) {
    foreach($thread[$id]->references as $reference) {
      if((trim($reference)!='') && (isset($thread[$reference]))) {
        $id=$reference;
        continue 2;
      }
    }
    break;
  }
  $liste=array();
  $liste[]=$id;
  $tmp=0;
  thread_show_head();
  echo thread_show_recursive($thread,$liste,1,"",$group,0,100,$tmp,$highlightids);
  thread_show_tail();
}

/*
 * Print the header of a message to the webpage
 *
 * $head: the header of the message as an headerType
 * $group: the name of the newsgroup, is needed for the links to post.php3
 *         and the header.
 */
function show_header($head,$group) {
  global $article_show,$text_header,$file_article,$attachment_show;
  global $file_attachment,$anonym_address;
  echo '<div class="np_article_header">';
  if ($article_show["Subject"]) echo $text_header["subject"].htmlspecialchars($head->subject)."<br>";
  if ($article_show["From"]) {
    echo $text_header["from"];
    if($head->from==$anonym_address) {
      // this is the anonymous address, so only show the name
      echo htmlspecialchars($head->name);
    } else {
      if($article_show["From_link"])
        echo '<a href="mailto:'.htmlspecialchars($head->from).'">';
      if(isset($article_show["From_rewrite"]))
        echo eregi_replace($article_show["From_rewrite"][0],
                           $article_show["From_rewrite"][1],
                           htmlspecialchars($head->from));
      else
        echo htmlspecialchars($head->from);
      if($article_show["From_link"])
        echo '</a>';
      if ($head->name != "") echo ' ('.htmlspecialchars($head->name).')';
    }
    echo "<br>";
  }
  if ($article_show["Newsgroups"]) 
    echo $text_header["newsgroups"].htmlspecialchars(str_replace(',',', ',$head->newsgroups))."<br>\n";
  if (isset($head->followup) && ($article_show["Followup"]) && ($head->followup != "")) 
    echo $text_header["followup"].htmlspecialchars($head->followup)."<br>\n";
  if ((isset($head->organization)) && ($article_show["Organization"]) &&
     ($head->organization != ""))
    echo $text_header["organization"].
         html_parse(htmlspecialchars($head->organization))."<br>\n";
  if ($article_show["Date"])
    echo $text_header["date"].date($text_header["date_format"],$head->date)."<br>\n";
  if ($article_show["Message-ID"])
    echo $text_header["message-id"].htmlspecialchars($head->id)."<br>\n";
  if (($article_show["References"]) && (isset($head->references[0]))) {
    echo $text_header["references"];
    for ($i=0; $i<=count($head->references)-1; $i++) {
      $ref=$head->references[$i];
      echo ' '.'<a href="'.$file_article.'?group='.urlencode($group).
           '&id='.urlencode($ref).'">'.($i+1).'</a>';
    }
    echo "<br>";
  }
  if (isset($head->user_agent)) {
    if ((isset($article_show["User-Agent"])) &&
       ($article_show["User-Agent"])) {
      echo $text_header["user-agent"].htmlspecialchars($head->user_agent)."<br>\n";
    } else {
      echo "<!-- User-Agent: ".htmlspecialchars($head->user_agent)." -->\n";
    }
  }
  if ((isset($attachment_show)) && ($attachment_show==true) &&
      (isset($head->content_type[1]))) {
    echo $text_header["attachments"];
    for ($i=1; $i<count($head->content_type); $i++) {
      echo '<a href="'.$file_attachment.'?group='.urlencode($group).'&'.
           'id='.urlencode($head->number).'&'.
           'attachment='.$i.'">'.
           $head->content_type_name[$i].'</a> ('.
           $head->content_type[$i].')';
      if ($i<count($head->content_type)-1) echo ', ';
    }
  }
  echo '</div>';
}

/*
 * decodes a body. Splits the content of $body into an array of several
 * lines, respecting the special decoding issues of format=flowed
 * articles. Each returned line consists of two fields: text and
 * the quote depth (depth)
 */
function decode_textbody($body,$format="fixed") {
  $body=split("\n",$body);
  $nbody=array();
  $depth=0;
  $paragraph=""; // empty paragraph
  $lastline="";
  for($i=0; $i<count($body)+1; $i++) {
    // calculate the quote depth of the actual line
    $ndepth=0;
    $tdepth=0;
    for($j=0; $j<=strlen($body[$i]); $j++) {
      $tdepth=$j;
      if($body[$i][$j]=='>') {
        $ndepth++;
      } else {
        if(($body[$i][$j]!=' ') || ($body[$i][$j-1]==' ') || ($j==0)) {
          break;
        }
      }
    }
    // generate a new paragraph?
    if(($i>0) && (($ndepth!=$depth) || $format!="flowed" ||
       ($paragraph[strlen($paragraph)-1]!=' ')) || ($i==count($body))) {
      $tmp->text=$lastline=$paragraph;
      $tmp->depth=$depth;
      $paragraph="";
      if(phpversion()>=5)
        $nbody[]=clone($tmp);
      else
        $nbody[]=$tmp;
    }
    if($body[$i]=="-- " && $format=="flowed") $body[$i]="--";
    $paragraph.=substr($body[$i],$tdepth);
    $depth=$ndepth;
  }
  return $nbody;
}

/*
 * replaces multiple spaces in texts by &nbsp;es and convert special-chars
 * to their entities
 */
function text2html($text) {
  return eregi_replace("^ ","&nbsp;",
         str_replace("  ","&nbsp; ",
         str_replace("  ","&nbsp; ",
         str_replace("\n","<br>",
         htmlspecialchars($text)))));
}


/*
 * print an article to the webpage
 *
 * $group: The name of the newsgroup
 * $id: the ID of the article inside the group or the message-id
 * $attachment: The number of the attachment of the article.
 *              0 means the normal textbody.
 */
function message_show($group,$id,$attachment=0,$article_data=false,$maxlen=false) {
  global $file_article,$file_article_full;
  global $text_header,$text_article,$article_showthread;
  global $block_xnoarchive,$article_graphicquotes;
  if ($article_data == false)
    $article_data=message_read($id,$attachment,$group);
  $head=$article_data->header;
  $body=$article_data->body[$attachment];
  if ($head) {
    if (($block_xnoarchive) && (isset($head->xnoarchive)) &&
        ($head->xnoarchive=="yes")) {
      echo $text_article["block-xnoarchive"];
    } else
    if (($head->content_type[$attachment]=="text/plain") &&
        ($attachment==0)) {
      show_header($head,$group);
      $body=decode_textbody($body,
             $article_data->header->content_type_format[$attachment]);
      $depth=0;
      echo '<div class="np_article_body">';
      $currentlen=0; // needed if $maxlen is set
      for ($i=0; $i<=count($body) && 
                 (($currentlen<$maxlen) || ($maxlen==false)); $i++) {
        // HTMLized Quotings instead of boring > ?
        if($article_graphicquotes) {
          // HTMLized Quotings
          for($j=$depth; $j<$body[$i]->depth; $j++)
            echo '<blockquote class="np_article_quote">';
          for($j=$body[$i]->depth; $j<$depth; $j++)
            echo '</blockquote>';
          $t=html_parse(text2html($body[$i]->text)).'<br>';
          echo $t;
          $currentlen+=strlen($t);
          echo "\n";
          $depth=$body[$i]->depth;
        } else {
          // Boring old Quotings with >
          if($body[$i]->depth==0) {
            if(trim($body[$i]->text)=='')
              $t="<br>\n";
            else
              $t=html_parse(text2html($body[$i]->text))."<br>\n";
          } else {
            $t='<i>'.str_repeat('&gt;',$body[$i]->depth).' '.
              html_parse(text2html(
                 textwrap($body[$i]->text,72-$body[$i]->depth,
                  "\n".str_repeat('>',$body[$i]->depth).' '))).
              "</i><br>\n";
          }
          echo $t;
          $currentlen+=strlen($t);
        }
      }
      echo '</div>';
      if($maxlen!=false && $currentlen>=$maxlen) {
        echo '<br><a href="'.$file_article_full.'?id='.$id.'&group='.
             $group.'">'.$text_article["full_article"].'</a>';
      }
    } else {
      echo $body;
    }
  }
}

/*
 * Shows the little menu on article-flat.php where you can select the
 * different pages with the articles on it
 */
function articleflat_pageselect($group,$id,$article_count,$first) {
  global $articleflat_articles_per_page,$file_article,$file_framethread,$name;
  global $text_thread,$thread_show;
  $pages=ceil($article_count / $articleflat_articles_per_page);
  $return="";
  if ($article_count > $articleflat_articles_per_page)
    $return.= $text_thread["pages"];
    for ($i = 0; $i < $pages; $i++) {
      if ($first != $i*$articleflat_articles_per_page+1)
        $return.= '<a class="np_pages_unselected" href="'.
             $file_article.'?group='.$group.
             '&amp;id='.urlencode($id).
             '&amp;first='.($i*$articleflat_articles_per_page+1).'&amp;last='.
             ($i+1)*$articleflat_articles_per_page.'">';
      else
        $return.= '<span class="np_pages_selected">';
      $return.= $i+1;
      if ($i == $pages-1) {
        // $return.= $article_count;
      }
      if ($first != $i*$articleflat_articles_per_page+1)
        $return.= '</a>';
      else
        $return.= '</span>';
    }
  return $return;
}

--- NEW FILE: check.php ---
<?
if(($iconv_enable==true) &&
   (!function_exists("iconv")))
  die('There is no iconv-extension in PHP. set <tt>$iconv_enable=false</tt>
       in config.inc.php to disable automatic charset recoding.');
?>
--- NEW FILE: types.inc.php ---
<?
/*
 *  NewsPortal: Data type declarations
 *
 *  Copyright (C) 2002-2004 Florian Amrhein
 *  E-Mail: newsportal at florian-amrhein.de
 *  Web: http://florian-amrhein.de
 *
 *  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
 */


/*
 * the name and the description of a newsgroup
 */
class newsgroupType {
  var $name;
  var $description;
  var $count;
  var $text;
}

/*
 * Stores a complete article:
 * - The parsed Header as an headerType
 * - The bodies and attachments as an array of array of lines
 */
class messageType {
  var $header;
  var $body;
}



/*
 * Stores the Header of an article
 */
class headerType {
  var $number; // the Number of an article inside a group
  var $id;     // Message-ID
  var $from;   // eMail of the author
  var $name;   // Name of the author
  var $subject; // the subject
  var $newsgroups;  // the Newsgroups where the article belongs to
  var $followup;
  var $date;         // timestamp of the article
  var $date_thread;  // timestamp of the newest article in the thread
  var $organization;
  var $xnoarchive;
  var $references;     // all references to the article
  var $bestreference;  // nearest reference found
  var $content_transfer_encoding;
  var $mime_version;
  var $content_type;   // array, Content-Type of the Body (Index=0) and the
                       // Attachments (Index>0)
  var $content_type_charset;  // like content_type
  var $content_type_name;     // array of the names of the attachments
  var $content_type_boundary; // The boundary of an multipart-article.
  var $content_type_format;   // array, is the body in flowed format?
  var $answers;    // which articles are followups of this article?
  var $isAnswer;   // is the article an answer to an other article?
  var $username;
  var $user_agent;
  var $isReply;    // has this article "Re: " at the beginning of the subject?
  var $threadsize; // number of articles in this thread
}
?>
--- NEW FILE: post.inc.php ---
<?
/*
 *  NewsPortal: Functions for posting articles to a newsgroup
 *
 *  Copyright (C) 2002-2006 Florian Amrhein
 *  E-Mail: newsportal at florian-amrhein.de
 *  Web: http://florian-amrhein.de
 *
 *  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
 */

/*
 * Encode lines with 8bit-characters to quote-printable
 *
 * $line: the to be encoded line
 *
 * the function returns a sting containing the quoted-printable encoded
 * $line
 */
function quoted_printable_encode($line) {
  global $www_charset;
  $qp_table=array(
     '=00', '=01', '=02', '=03', '=04', '=05',
     '=06', '=07', '=08', '=09', '=0A', '=0B',
     '=0C', '=0D', '=0E', '=0F', '=10', '=11',
     '=12', '=13', '=14', '=15', '=16', '=17',
     '=18', '=19', '=1A', '=1B', '=1C', '=1D',
     '=1E', '=1F', '_',   '!',   '"',   '#',
     '$',   '%',   '&',   "'",   '(',   ')',
     '*',   '+',   ',',   '-',   '.',   '/',
     '0',   '1',   '2',   '3',   '4',   '5',
     '6',   '7',   '8',   '9',   ':',   ';',
     '<',   '=3D', '>',   '=3F', '@',   'A',
     'B',   'C',   'D',   'E',   'F',   'G',
     'H',   'I',   'J',   'K',   'L',   'M',
     'N',   'O',   'P',   'Q',   'R',   'S',
     'T',   'U',   'V',   'W',   'X',   'Y',
     'Z',   '[',   '\\',  ']',   '^',   '=5F',
     '',    'a',   'b',   'c',   'd',   'e',
     'f',   'g',   'h',   'i',   'j',   'k',
     'l',   'm',   'n',   'o',   'p',   'q',
     'r',   's',   't',   'u',   'v',   'w',
     'x',   'y',   'z',   '{',   '|',   '}',
     '~',   '=7F', '=80', '=81', '=82', '=83',
     '=84', '=85', '=86', '=87', '=88', '=89',
     '=8A', '=8B', '=8C', '=8D', '=8E', '=8F',
     '=90', '=91', '=92', '=93', '=94', '=95',
     '=96', '=97', '=98', '=99', '=9A', '=9B',
     '=9C', '=9D', '=9E', '=9F', '=A0', '=A1',
     '=A2', '=A3', '=A4', '=A5', '=A6', '=A7',
     '=A8', '=A9', '=AA', '=AB', '=AC', '=AD',
     '=AE', '=AF', '=B0', '=B1', '=B2', '=B3',
     '=B4', '=B5', '=B6', '=B7', '=B8', '=B9',
     '=BA', '=BB', '=BC', '=BD', '=BE', '=BF',
     '=C0', '=C1', '=C2', '=C3', '=C4', '=C5',
     '=C6', '=C7', '=C8', '=C9', '=CA', '=CB',
     '=CC', '=CD', '=CE', '=CF', '=D0', '=D1',
     '=D2', '=D3', '=D4', '=D5', '=D6', '=D7',
     '=D8', '=D9', '=DA', '=DB', '=DC', '=DD',
     '=DE', '=DF', '=E0', '=E1', '=E2', '=E3',
     '=E4', '=E5', '=E6', '=E7', '=E8', '=E9',
     '=EA', '=EB', '=EC', '=ED', '=EE', '=EF',
     '=F0', '=F1', '=F2', '=F3', '=F4', '=F5',
     '=F6', '=F7', '=F8', '=F9', '=FA', '=FB',
     '=FC', '=FD', '=FE', '=FF');
  // are there "forbidden" characters in the string?
  for($i=0; $i<strlen($line) && ord($line[$i])<=127 ; $i++);
  if ($i<strlen($line)) { // yes, there are. So lets encode them!
    $from=$i;
    for($to=strlen($line)-1; ord($line[$to])<=127; $to--);
    // lets scan for the start and the end of the to be encoded _words_
    for(;$from>0 && $line[$from] != ' '; $from--);
    if($from>0) $from++;
    for(;$to<strlen($line) && $line[$to] != ' '; $to++);
    // split the string into the to be encoded middle and the rest
    $begin=substr($line,0,$from);
    $middle=substr($line,$from,$to-$from);
    $end=substr($line,$to);
    // ok, now lets encode $middle...
    $newmiddle="";
    for($i=0; $i<strlen($middle); $i++)
      $newmiddle .= $qp_table[ord($middle[$i])];
    // now we glue the parts together...
    $line=$begin.'=?'.$www_charset.'?Q?'.$newmiddle.'?='.$end;
  }
  return $line;
}

/*
 * generate a message-id for posting.
 * $identity: a string containing informations about the article, to
 *     make a md5-hash out of it.
 *
 * returns: a complete message-id
 */
function generate_msgid($identity) {
  global $msgid_generate,$msgid_fqdn;
  switch($msgid_generate) {
    case "no":
      // no, we don't want to generate a message-id.
      return false;
      break;
    case "md5":
      return '<'.md5($identity).'$1@'.$msgid_fqdn.'>';
      break;
    default:
      return false;
      break;
  }
}

/*
 * Post an article to a newsgroup
 *
 * $subject: The Subject of the article
 * $from: The authors name and email of the article
 * $newsgroups: The groups to post to
 * $ref: The references of the article
 * $body: The article itself
 */
function message_post($subject,$from,$newsgroups,$ref,$body) {
  global $server,$port,$send_poster_host,$organization,$text_error;
  global $file_footer,$www_charset,$spooldir;
  global $msgid_generate,$msgid_fqdn;
  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."; format=flowed\r\n");
    fputs($ns,"Content-Transfer-Encoding: 8bit\r\n");
    fputs($ns,"User-Agent: NewsPortal/0.38 (http://florian-amrhein.de/newsportal)\r\n");
    if ($send_poster_host)
      @fputs($ns,'X-HTTP-Posting-Host: '.gethostbyaddr(getenv("REMOTE_ADDR"))."\r\n");
    if (($ref!=false) && (count($ref)>0)) {
      // strip references
      if(strlen(implode(" ",$ref))>900) {
        $ref_first=array_shift($ref);
        do {
          $ref=array_slice($ref,1);
        } while(strlen(implode(" ",$ref))>800);
        array_unshift($ref,$ref_first);
      }
      fputs($ns,'References: '.implode(" ",$ref)."\r\n");
    }
    if (isset($organization))
      fputs($ns,'Organization: '.quoted_printable_encode($organization)."\r\n");
    if ((isset($file_footer)) && ($file_footer!="")) {
      $footerfile=fopen($file_footer,"r");
      $body.="\n".fread($footerfile,filesize($file_footer));
      fclose($footerfile);
    }
    if($msgid=generate_msgid(
                 $subject.",".$from.",".$newsgroups.",".$ref.",".$body))
      fputs($ns,'Message-ID: '.$msgid."\r\n");
    $body=str_replace("\n.\r","\n..\r",$body);
    $body=str_replace("\r",'',$body);
    $b=split("\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"];
  }
  // let thread.php ignore the cache for this group, so this new
  // article will be visible instantly
  $groupsarr=explode(",",$newsgroups);
  foreach($groupsarr as $newsgroup) {
    $cachefile=$spooldir.'/'.$newsgroup.'-cache.txt';
    @unlink($cachefile);
  }
  return $message;
}
?>


More information about the cvs mailing list