Source for file cmd_spell.php

Documentation is available at cmd_spell.php

  1. <?php
  2. /**
  3.  * Command line spellcheck class
  4.  *
  5.  * $params = array();
  6.  * $params['spell_command'] = 'ispell -d american -a';
  7.  * $params['use_proc_open'] = false; // (check_php_version(4,3))
  8.  * $params['temp_dir'] = '/tmp/'; // $attachment_dir
  9.  * $params['userdic'] = array(); // user's dictionary
  10.  * $params['debug'] = true;
  11.  * 
  12.  * $spell = new cmd_spell($params);
  13.  * // check $spell->error buffer
  14.  * 
  15.  * $text = "Quick brownn fox brownn\n\nbrownn squirrel.\ntwentytwo owttnewt";
  16.  * 
  17.  * $results = $spell->check_text($text);
  18.  * // check $spell->error buffer
  19.  * // parse $results
  20.  *
  21.  * @copyright 1999-2020 The SquirrelMail Project Team
  22.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  23.  * @version $Id: cmd_spell.php 14845 2020-01-07 08:09:34Z pdontthink $
  24.  * @package plugins
  25.  * @subpackage squirrelspell
  26.  */
  27.  
  28. /**
  29.  * Command line spellcheck class, compatible with ispell and aspell.
  30.  * @package plugins
  31.  * @subpackage squirrelspell
  32.  */
  33. class cmd_spell extends squirrelspell {
  34.     /**
  35.      * @var string 
  36.      */
  37.     var $spell_command = '';
  38.     var $userdic = array();
  39.     /**
  40.      * Controls which function is used to execute ispell. proc_open()
  41.      * should be used in PHP 4.3+. exec() can be used in older PHP versions.
  42.      * @var boolean 
  43.      */
  44.     var $use_proc_open = false;
  45.     /**
  46.      * @var string 
  47.      */
  48.     var $temp_dir = '';
  49.     /**
  50.      */
  51.     var $debug = false;
  52.  
  53.     var $missed_words = array();
  54.  
  55.     /**
  56.      * Constructor function
  57.      * @param array $aParams 
  58.      */
  59.     function cmd_spell($aParams=array()) {
  60.         if (isset($aParams['spell_command'])) {
  61.             return $this->set_error('Spellcheck command is not set.');
  62.         else {
  63.             $this->spell_command = $aParams['spell_command'];
  64.         }
  65.  
  66.         if (isset($aParams['userdic'])) {
  67.             $this->userdic = $aParams['userdic'];
  68.         }
  69.  
  70.         if (isset($aParams['use_proc_open'])) {
  71.             $this->use_proc_open = (bool) $aParams['use_proc_open'];
  72.         }
  73.  
  74.         if (isset($aParams['temp_dir'])) {
  75.             $this->temp_dir = $aParams['temp_dir'];
  76.             // add slash to attachment directory, if it does not end with slash. 
  77.             if (substr($this->temp_dir-1!= '/'{
  78.                 $this->temp_dir = $this->temp_dir . '/';
  79.             }
  80.         elseif (!$this->use_proc_open{
  81.             return $this->set_error('Temporally directory is not set.');
  82.         }
  83.  
  84.         if (isset($aParams['debug']&& (bool) $aParams['debug']{
  85.             $this->debug = true;
  86.             error_reporting(E_ALL);
  87.             ini_set('display_errors',1);
  88.         }
  89.  
  90.     }
  91.  
  92.     /**
  93.      * @param string $sText 
  94.      * @return mixed array with command output or false.
  95.      */
  96.     function proc_open_spell($sText{
  97.         $descriptorspec array(
  98.              => array('pipe''r'),  // stdin is a pipe that the child will read from
  99.              => array('pipe''w'),  // stdout is a pipe that the child will write to
  100.              => array('pipe''w')// stderr is a pipe that the child will write to
  101.              );
  102.  
  103.         if ($this->debug{
  104.             $spell_proc proc_open($this->spell_command$descriptorspec$pipes);
  105.         else {
  106.             $spell_proc @proc_open($this->spell_command$descriptorspec$pipes);
  107.         }
  108.  
  109.         if is_resource($spell_proc) ) {
  110.             return $this->set_error(sprintf(_("Could not run the spellchecker command (%s)."),
  111.                                             $this->spell_command));
  112.         }
  113.  
  114.         if @fwrite($pipes[0],$sText) ) {
  115.             $this->set_error(_("Error while writing to pipe."));
  116.             // close all three $pipes here.
  117.             for($i=0$i<=2$i++{
  118.                 // disable all fclose error messages
  119.                 @fclose($pipes[$i]);
  120.             }
  121.             return false;
  122.         }
  123.  
  124.         fclose($pipes[0]);
  125.  
  126.         $sqspell_output array();
  127.         for($i=1$i<=2$i++{
  128.             while(!feof($pipes[$i])) {
  129.                 array_push($sqspell_outputrtrim(fgetss($pipes[$i],999),"\r\n"));
  130.             }
  131.             fclose($pipes[$i]);
  132.         }
  133.  
  134.         if (proc_close($spell_proc)) {
  135.             $error '';
  136.             foreach ($sqspell_output as $line{
  137.                 $error.= $line "\n";
  138.             }
  139.             return $this->set_error($error);
  140.         else {
  141.             return $sqspell_output;
  142.         }
  143.     }
  144.  
  145.     /**
  146.      * @param string $sText 
  147.      * @return mixed array with command output or false.
  148.      */
  149.     function exec_spell($sText{
  150.         // find unused file in attachment directory
  151.         do {
  152.             $floc $this->temp_dir . md5($sText microtime());
  153.         while (file_exists($floc));
  154.  
  155.         if ($this->debug{
  156.             $fp fopen($floc'w');
  157.         else {
  158.             $fp @fopen($floc'w');
  159.         }
  160.         if is_resource($fp) ) {
  161.             return $this->set_error(sprintf(_("Could not open temporary file '%s'."),
  162.                                      $floc) );
  163.         }
  164.  
  165.         if @fwrite($fp$sText) ) {
  166.             $this->set_error(sprintf(_("Error while writing to temporary file '%s'."),
  167.                                      $floc) );
  168.             // close file descriptor
  169.             fclose($fp);
  170.             return false;
  171.         }
  172.         fclose($fp);
  173.  
  174.         exec("$this->spell_command < $floc 2>&1"$sqspell_output$exitcode);
  175.  
  176.         unlink($floc);
  177.  
  178.         if ($exitcode{
  179.             $error '';
  180.             foreach ($sqspell_output as $line{
  181.                 $error.= $line "\n";
  182.             }
  183.             return $this->set_error($error);
  184.         else {
  185.             return $sqspell_output;
  186.         }
  187.     }
  188.  
  189.     /**
  190.      * Prepares string for ispell/aspell parsing
  191.      * 
  192.      * Function adds an extra space at the beginning of each line. This way
  193.      * ispell/aspell don't treat these as command characters.
  194.      * @param string $sText 
  195.      * @return string 
  196.      */
  197.     function prepare_text($sText{
  198.         // prepend space to every sqspell_new_text line
  199.         $sText str_replace("\r\n","\n",$sText);
  200.         $ret '';
  201.         foreach (explode("\n",$sTextas $line{
  202.             $ret.= ' ' $line "\n";
  203.         }
  204.         return $ret;
  205.     }
  206.  
  207.     /**
  208.      * Checks block of text
  209.      * @param string $sText text
  210.      * @return array 
  211.      */
  212.     function check_text($sText{
  213.         $this->missed_words = array();
  214.  
  215.         $sText $this->prepare_text($sText);
  216.  
  217.         if ($this->use_proc_open{
  218.             $sqspell_output $this->proc_open_spell($sText);
  219.         else {
  220.             $sqspell_output $this->exec_spell($sText);
  221.         }
  222.  
  223.         /**
  224.          * Define some variables to be used during the processing.
  225.          */
  226.         $current_line=0;
  227.         /**
  228.          * Now we process the output of sqspell_command (ispell or aspell in
  229.          * ispell compatibility mode, whichever). I'm going to be scarce on
  230.          * comments here, since you can just look at the ispell/aspell output
  231.          * and figure out what's going on. ;) The best way to describe this is
  232.          * "Dark Magic".
  233.          */
  234.         for ($i=0$i<sizeof($sqspell_output)$i++){
  235.             switch (substr($sqspell_output[$i]01)){
  236.             /**
  237.              * Line is empty.
  238.              * Ispell adds empty lines when an end of line is reached
  239.              */
  240.             case '':
  241.                 $current_line++;
  242.                 break;
  243.             /**
  244.              * Line begins with "&".
  245.              * This means there's a misspelled word and a few suggestions.
  246.              */
  247.             case '&':
  248.                 list($left$rightexplode(": "$sqspell_output[$i]);
  249.                 $tmparray explode(" "$left);
  250.                 $sqspell_word=$tmparray[1];
  251.                 /**
  252.                  * Check if the word is in user dictionary.
  253.                  */
  254.                 if (in_array($sqspell_word,$this->userdic)){
  255.                     $sqspell_symb=intval($tmparray[3])-1;
  256.                     // add suggestions
  257.                     if (!isset($this->missed_words[$sqspell_word])) {
  258.                         foreach(explode(',',$rightas $word{
  259.                             $this->missed_words[$sqspell_word]['suggestions'][trim($word);
  260.                         }
  261.                     }
  262.                     // add location
  263.                     $this->missed_words[$sqspell_word]['locations']["$current_line:$sqspell_symb";
  264.                 }
  265.                 break;
  266.             /**
  267.              * Line begins with "#".
  268.              * This means a misspelled word and no suggestions.
  269.              */
  270.             case '#':
  271.                 $tmparray explode(" "$sqspell_output[$i]);
  272.                 $sqspell_word=$tmparray[1];
  273.                 /**
  274.                  *
  275.                  * Check if the word is in user dictionary.
  276.                  */
  277.                 if (!in_array($sqspell_word,$this->userdic)){
  278.                     $sqspell_symb=intval($tmparray[2])-1;
  279.                     // no suggestions
  280.                     $this->missed_words[$sqspell_word]['suggestions'array();
  281.                     // add location
  282.                     $this->missed_words[$sqspell_word]['locations']["$current_line:$sqspell_symb";
  283.                 }
  284.                 break;
  285.             }
  286.         }
  287.         return $this->missed_words;
  288.     }
  289. }
  290.  
  291.  
  292. /**
  293.  * Define the command used to spellcheck the document.
  294.  */
  295. #$sqspell_command=$SQSPELL_APP[$sqspell_use_app];

Documentation generated on Mon, 13 Jan 2020 04:22:04 +0100 by phpDocumentor 1.4.3