[ Index ]
 

Code source de DokuWiki 2006-11-06

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/exe/ -> spellcheck.php (source)

   1  <?php
   2  /**
   3   * DokuWiki Spellcheck AJAX backend
   4   *
   5   * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
   6   * @author     Andreas Gohr <andi@splitbrain.org>
   7   */
   8  
   9  /**
  10   * Licence info: This spellchecker is inspired by code by Garrison Locke available
  11   * at http://www.broken-notebook.com/spell_checker/index.php (licensed under the Terms
  12   * of an BSD license). The code in this file was nearly completly rewritten for DokuWiki
  13   * and is licensed under GPL version 2 (See COPYING for details).
  14   *
  15   * Original Copyright notice follows:
  16   *
  17   * Copyright (c) 2005, Garrison Locke
  18   * All rights reserved.
  19   *
  20   * Redistribution and use in source and binary forms, with or without
  21   * modification, are permitted provided that the following conditions are met:
  22   *
  23   *   * Redistributions of source code must retain the above copyright notice,
  24   *     this list of conditions and the following disclaimer.
  25   *   * Redistributions in binary form must reproduce the above copyright notice,
  26   *     this list of conditions and the following disclaimer in the documentation
  27   *     and/or other materials provided with the distribution.
  28   *   * Neither the name of the http://www.broken-notebook.com nor the names of its
  29   *     contributors may be used to endorse or promote products derived from this
  30   *     software without specific prior written permission.
  31   *
  32   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  33   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  34   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  35   * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  36   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  38   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  39   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  41   * OF SUCH DAMAGE.
  42   */
  43  
  44  //fix for Opera XMLHttpRequests
  45  if(!count($_POST) && $HTTP_RAW_POST_DATA){
  46    parse_str($HTTP_RAW_POST_DATA, $_POST);
  47  }
  48  
  49  if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
  50  require_once  (DOKU_INC.'inc/init.php');
  51  session_write_close();
  52  require_once  (DOKU_INC.'inc/utf8.php');
  53  require_once  (DOKU_INC.'inc/aspell.php');
  54  require_once  (DOKU_INC.'inc/common.php');
  55  
  56  header('Content-Type: text/plain; charset=utf-8');
  57  
  58  //create spell object
  59  $spell = new Aspell($conf['lang'],null,'utf-8');
  60  $spell->setMode(PSPELL_FAST);
  61  
  62  //add personal dictionary
  63  if(@file_exists(DOKU_INC.'conf/words.aspell')){
  64    $spell->personal = DOKU_INC.'conf/words.aspell';
  65  }
  66  
  67  //call the requested function
  68  $call = 'spell_'.$_POST['call'];
  69  if(function_exists($call)){
  70    $call();
  71  }else{
  72    print "The called function does not exist!";
  73  }
  74  
  75  /**
  76   * replaces a link with blanks of same length
  77   * The first string is the complete link and
  78   * and the second optional string might be the
  79   * alternative text that would become part of
  80   * the result string and will be checked for
  81   * spelling errors again.
  82   *
  83   * callback for preg_replace_callback
  84   *
  85   * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
  86   * @author Andreas Gohr <andi@splitbrain.org>
  87   */
  88  function spaceslink($matches){
  89    $string  = unslash($matches[1]);
  90    $check   = unslash($matches[2]);
  91    $result  = '  '; //opening [[
  92    $result .= str_pad('',utf8_strlen($string),' ');
  93    $result .= $check;
  94    $result .= '  '; //closing ]]
  95  
  96    return $result;
  97  }
  98  
  99  /**
 100   * Spellchecker. Called by an AJAX request
 101   *
 102   * Runs the given Text through Aspell and prints XHTML with
 103   * markup. The first char represents the error code:
 104   *
 105   * 0 - No spelling mistakes
 106   * 1 - Spelling mistakes found
 107   * 2 - An error occured error message follows
 108   *
 109   * @author Andreas Gohr <andi@splitbrain.org>
 110   */
 111  function spell_check() {
 112    global $spell;
 113    $string = $_POST['data'];
 114    $misspell = false;
 115  
 116    // for streamlined line endings
 117    $string = preg_replace("/(\015\012)|(\015)/","\012",$string);
 118    $string = htmlspecialchars($string);
 119  
 120    // make sure multiple spaces and leading are kept
 121    $string = preg_replace('/^ /m','&nbsp;',$string);
 122    $string = preg_replace('/  /','&nbsp; ',$string);
 123  
 124    // we need the text as array later
 125    $data = explode("\n",$string);
 126  
 127    // don't check links and medialinks for spelling errors
 128    $string = preg_replace_callback('/\{\{(.*?)(\|(.*?))?(\}\})/','spaceslink',$string);
 129    $string = preg_replace_callback('/\[\[(.*?)(\|(.*?))?(\]\])/','spaceslink',$string);
 130  
 131    // run aspell in terse sgml mode, ignore nbsp as correct word
 132    if(!$spell->runAspell($string,$out,$err,array('!','+html','@nbsp'))){
 133      print '2'; //to indicate an error
 134      print "An error occured while trying to run the spellchecker:\n";
 135      print $err;
 136      return;
 137    }
 138  
 139    #use this to debug raw aspell output
 140    #print "1$out"; return;
 141  
 142    // go through the result
 143    $lines = split("\n",$out);
 144    $rcnt  = count($lines)-1;    // aspell result count
 145    $lcnt  = count($data)+1;     // original line counter
 146  
 147  
 148    for($i=$rcnt; $i>=0; $i--){
 149      $line = trim($lines[$i]);
 150      if($line[0] == '@') continue; // comment
 151      if($line[0] == '*') continue; // no mistake in this word
 152      if($line[0] == '+') continue; // root of word was found
 153      if($line[0] == '?') continue; // word was guessed
 154      if(empty($line)){
 155        // empty line -> new source line
 156        $lcnt--;
 157        continue;
 158      }
 159      // now get the misspelled words
 160      if(preg_match('/^& ([^ ]+) (\d+) (\d+): (.*)/',$line,$match)){
 161        // match with suggestions
 162        $word = $match[1];
 163        $off  = $match[3]-1;
 164        $sug  = split(', ',$match[4]);
 165      }elseif(preg_match('/^# ([^ ]+) (\d+)/',$line,$match)){
 166        // match without suggestions
 167        $word = $match[1];
 168        $off  = $match[2]-1;
 169        $sug  = null;
 170      }else{
 171        // couldn't parse output
 172        print '2';
 173        print "The spellchecker output couldn't be parsed.\n";
 174        print "Line $i:".$line;
 175        return;
 176      }
 177  
 178      $misspell = true;
 179      //aspell < 0.60 returns singlebyte offsets
 180      if($spell->version >= 600){
 181        $len  = utf8_strlen($word);
 182        $data[$lcnt] = utf8_substr_replace($data[$lcnt],spell_formatword($word,$sug),$off, $len);
 183      }else{
 184        $len  = strlen($word);
 185        $data[$lcnt] = substr_replace($data[$lcnt],spell_formatword($word,$sug),$off, $len);
 186      }
 187  
 188    }//end of output parsing
 189  
 190    // the first char returns the spell info
 191    if($misspell){
 192      $string = '1'.join('<br />',$data);
 193    }else{
 194      $string = '0'.join('<br />',$data);
 195    }
 196  
 197    if(!$_POST['utf8']){
 198      // encode multibyte chars as entities for broken Konqueror
 199      $string = utf8_tohtml($string);
 200    }
 201  
 202    //output
 203    print $string;
 204  }
 205  
 206  /**
 207   * Formats a word with needed markup for the Suggestion Popup
 208   *
 209   * @author Andreas Gohr <andi@splitbrain.org>
 210   */
 211  function spell_formatword($word,$suggestions=null){
 212    static $i = 1;
 213  
 214    if(is_array($suggestions)){
 215      //restrict to maximum of 7 elements
 216      $suggestions = array_slice($suggestions,0,7);
 217      $suggestions = array_map('htmlspecialchars',$suggestions);
 218  
 219      if(!$_POST['utf8']){
 220        //konqueror's broken UTF-8 handling needs this
 221        $suggestions = array_map('utf8_tohtml',$suggestions);
 222      }
 223  
 224      $suggestions = array_map('addslashes',$suggestions);
 225  
 226      $sug = ",'".join("','",$suggestions)."'"; // build javascript args
 227    }else{
 228      $sug = '';
 229    }
 230  
 231    $link = '<a href="javascript:ajax_spell.suggest('.$i.$sug.')" '.
 232            'class="spell_error" id="spell__error'.$i.'">'.htmlspecialchars($word).'</a>';
 233    $i++;
 234    return $link;
 235  }
 236  
 237  /**
 238   * Rewrite markuped XHTML back to plain Text. AJAX callback
 239   *
 240   * @author Andreas Gohr <andi@splitbrain.org>
 241   */
 242  function spell_resume(){
 243    $text = $_POST['data'];
 244  
 245    //some browsers insert newlines instead of spaces
 246    $text = preg_replace("/(\r\n|\n|\r)/", ' ', $text);
 247    $text = preg_replace("=<br */?>=i", "\n", $text);
 248  
 249    // remove HTML tags
 250    $text = strip_tags($text);
 251  
 252    // restore spaces
 253    $text = preg_replace('/&nbsp;/',' ',$text);
 254  
 255    // restore quoted special chars
 256    $text = unhtmlspecialchars($text);
 257  
 258    // check if UTF-8 is accepted
 259    if(!$_POST['utf8']){
 260      // protect '&' (gets removed in JS later)
 261      $text = str_replace('&','&amp;',$text);
 262      // encode multibyte chars as entities for broken Konqueror
 263      $text = utf8_tohtml($text);
 264    }
 265  
 266    // output
 267    print $text;
 268  }
 269  
 270  /**
 271   * Just send data back as received for UTF-8 testing
 272   */
 273  function spell_utf8test(){
 274    print $_POST['data'];
 275  }
 276  
 277  /**
 278   * Reverse htmlspecialchars
 279   *
 280   * @author <donwilson at gmail dot com>
 281   * @author Andreas Gohr <andi@splitbrain.org>
 282   */
 283  function unhtmlspecialchars($string, $quotstyle=ENT_COMPAT){
 284    $string = str_replace ( '&amp;', '&', $string );
 285    $string = str_replace ( '&lt;', '<', $string );
 286    $string = str_replace ( '&gt;', '>', $string );
 287  
 288    if($quotstyle != ENT_NOQUOTES){
 289      $string = str_replace ( '&quot;', '\"', $string );
 290    }
 291    if($quotstyle == ENT_QUOTES){
 292      $string = str_replace ( '&#39;', '\'', $string );
 293      $string = str_replace ( '&#039;', '\'', $string );
 294    }
 295  
 296    return $string;
 297  }
 298  
 299  //Setup VIM: ex: et ts=2 enc=utf-8 :
 300  ?>


Généré le : Tue Apr 3 20:47:31 2007 par Balluche grâce à PHPXref 0.7