Grammalecte  Hex Artifact Content

Artifact 190fd0785232bf7bf4d5c5c865eb93125a251501174fa0926f6d828bb64729a0:


0000: 20 23 21 2f 75 73 72 2f 62 69 6e 2f 65 6e 76 20   #!/usr/bin/env 
0010: 70 79 74 68 6f 6e 33 0a 0a 69 6d 70 6f 72 74 20  python3..import 
0020: 73 79 73 0a 69 6d 70 6f 72 74 20 6f 73 2e 70 61  sys.import os.pa
0030: 74 68 0a 69 6d 70 6f 72 74 20 61 72 67 70 61 72  th.import argpar
0040: 73 65 0a 69 6d 70 6f 72 74 20 6a 73 6f 6e 0a 69  se.import json.i
0050: 6d 70 6f 72 74 20 74 72 61 63 65 62 61 63 6b 0a  mport traceback.
0060: 69 6d 70 6f 72 74 20 63 6f 6e 66 69 67 70 61 72  import configpar
0070: 73 65 72 0a 69 6d 70 6f 72 74 20 74 69 6d 65 0a  ser.import time.
0080: 0a 66 72 6f 6d 20 67 72 61 6d 6d 61 6c 65 63 74  .from grammalect
0090: 65 2e 62 6f 74 74 6c 65 20 69 6d 70 6f 72 74 20  e.bottle import 
00a0: 42 6f 74 74 6c 65 2c 20 72 75 6e 2c 20 72 65 71  Bottle, run, req
00b0: 75 65 73 74 2c 20 72 65 73 70 6f 6e 73 65 2c 20  uest, response, 
00c0: 74 65 6d 70 6c 61 74 65 2c 20 73 74 61 74 69 63  template, static
00d0: 5f 66 69 6c 65 0a 0a 69 6d 70 6f 72 74 20 67 72  _file..import gr
00e0: 61 6d 6d 61 6c 65 63 74 65 0a 69 6d 70 6f 72 74  ammalecte.import
00f0: 20 67 72 61 6d 6d 61 6c 65 63 74 65 2e 74 65 78   grammalecte.tex
0100: 74 20 61 73 20 74 78 74 0a 66 72 6f 6d 20 67 72  t as txt.from gr
0110: 61 6d 6d 61 6c 65 63 74 65 2e 67 72 61 70 68 73  ammalecte.graphs
0120: 70 65 6c 6c 2e 65 63 68 6f 20 69 6d 70 6f 72 74  pell.echo import
0130: 20 65 63 68 6f 0a 0a 0a 48 4f 4d 45 50 41 47 45   echo...HOMEPAGE
0140: 20 3d 20 22 22 22 0a 3c 21 44 4f 43 54 59 50 45   = """.<!DOCTYPE
0150: 20 48 54 4d 4c 3e 0a 3c 68 74 6d 6c 3e 0a 20 20   HTML>.<html>.  
0160: 20 20 3c 68 65 61 64 3e 0a 20 20 20 20 20 20 20    <head>.       
0170: 20 3c 6d 65 74 61 20 68 74 74 70 2d 65 71 75 69   <meta http-equi
0180: 76 3d 22 63 6f 6e 74 65 6e 74 2d 74 79 70 65 22  v="content-type"
0190: 20 63 6f 6e 74 65 6e 74 3d 22 74 65 78 74 2f 68   content="text/h
01a0: 74 6d 6c 3b 20 63 68 61 72 73 65 74 3d 55 54 46  tml; charset=UTF
01b0: 2d 38 22 20 2f 3e 0a 20 20 20 20 3c 2f 68 65 61  -8" />.    </hea
01c0: 64 3e 0a 0a 20 20 20 20 3c 62 6f 64 79 20 63 6c  d>..    <body cl
01d0: 61 73 73 3d 22 70 61 6e 65 6c 22 3e 0a 20 20 20  ass="panel">.   
01e0: 20 20 20 20 20 3c 68 31 3e 47 72 61 6d 6d 61 6c       <h1>Grammal
01f0: 65 63 74 65 20 c2 b7 20 53 65 72 76 65 75 72 3c  ecte .. Serveur<
0200: 2f 68 31 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68  /h1>..        <h
0210: 32 3e 49 4e 46 4f 52 4d 41 54 49 4f 4e 53 3c 2f  2>INFORMATIONS</
0220: 68 31 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68 33  h1>..        <h3
0230: 3e 41 6e 61 6c 79 73 65 72 20 64 75 20 74 65 78  >Analyser du tex
0240: 74 65 3c 2f 68 33 3e 0a 20 20 20 20 20 20 20 20  te</h3>.        
0250: 3c 70 3e 5b 61 64 72 65 73 73 65 5f 73 65 72 76  <p>[adresse_serv
0260: 65 75 72 5d 3a 38 30 38 30 2f 67 63 5f 74 65 78  eur]:8080/gc_tex
0270: 74 2f 66 72 20 28 50 4f 53 54 29 3c 2f 70 3e 0a  t/fr (POST)</p>.
0280: 20 20 20 20 20 20 20 20 3c 70 3e 50 61 72 61 6d          <p>Param
0290: c3 a8 74 72 65 73 20 3a 3c 2f 70 3e 0a 20 20 20  ..tres :</p>.   
02a0: 20 20 20 20 20 3c 75 6c 3e 0a 20 20 20 20 20 20       <ul>.      
02b0: 20 20 20 20 20 20 3c 6c 69 3e 22 74 65 78 74 22        <li>"text"
02c0: 20 28 74 65 78 74 29 26 6e 62 73 70 3b 3a 20 74   (text)&nbsp;: t
02d0: 65 78 74 65 20 c3 a0 20 61 6e 61 6c 79 73 65 72  exte .. analyser
02e0: 2e 3c 2f 6c 69 3e 0a 20 20 20 20 20 20 20 20 20  .</li>.         
02f0: 20 20 20 3c 6c 69 3e 22 74 66 22 20 28 63 68 65     <li>"tf" (che
0300: 63 6b 62 6f 78 29 26 6e 62 73 70 3b 3a 20 70 61  ckbox)&nbsp;: pa
0310: 73 73 65 72 20 6c 65 20 66 6f 72 6d 61 74 65 75  sser le formateu
0320: 72 20 64 65 20 74 65 78 74 65 20 61 76 61 6e 74  r de texte avant
0330: 20 6c e2 80 99 61 6e 61 6c 79 73 65 2e 3c 2f 6c   l...analyse.</l
0340: 69 3e 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c  i>.            <
0350: 6c 69 3e 22 6f 70 74 69 6f 6e 73 22 20 28 74 65  li>"options" (te
0360: 78 74 29 26 6e 62 73 70 3b 3a 20 75 6e 65 20 63  xt)&nbsp;: une c
0370: 68 61 c3 ae 6e 65 20 61 75 20 66 6f 72 6d 61 74  ha..ne au format
0380: 20 4a 53 4f 4e 20 61 76 65 63 20 6c 65 20 6e 6f   JSON avec le no
0390: 6d 20 64 65 73 20 6f 70 74 69 6f 6e 73 20 63 6f  m des options co
03a0: 6d 6d 65 20 61 74 74 72 69 62 75 74 73 20 65 74  mme attributs et
03b0: 20 75 6e 20 62 6f 6f 6c c3 a9 65 6e 20 63 6f 6d   un bool..en com
03c0: 6d 65 20 76 61 6c 65 75 72 2e 20 45 78 65 6d 70  me valeur. Exemp
03d0: 6c 65 26 6e 62 73 70 3b 3a 20 7b 22 67 76 22 3a  le&nbsp;: {"gv":
03e0: 20 74 72 75 65 2c 20 22 68 74 6d 6c 22 3a 20 74   true, "html": t
03f0: 72 75 65 7d 3c 2f 6c 69 3e 0a 20 20 20 20 20 20  rue}</li>.      
0400: 20 20 3c 2f 75 6c 3e 0a 0a 20 20 20 20 20 20 20    </ul>..       
0410: 20 3c 68 33 3e 4c 69 73 74 65 72 20 6c 65 73 20   <h3>Lister les 
0420: 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20 20  options</h3>.   
0430: 20 20 20 20 20 3c 70 3e 5b 61 64 72 65 73 73 65       <p>[adresse
0440: 5f 73 65 72 76 65 75 72 5d 3a 38 30 38 30 2f 67  _serveur]:8080/g
0450: 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72 20 28 47  et_options/fr (G
0460: 45 54 29 3c 2f 70 3e 0a 0a 20 20 20 20 20 20 20  ET)</p>..       
0470: 20 3c 68 33 3e 44 c3 a9 66 69 6e 69 72 20 73 65   <h3>D..finir se
0480: 73 20 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20  s options</h3>. 
0490: 20 20 20 20 20 20 20 3c 70 3e 5b 61 64 72 65 73         <p>[adres
04a0: 73 65 5f 73 65 72 76 65 75 72 5d 3a 38 30 38 30  se_serveur]:8080
04b0: 2f 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72 20  /set_options/fr 
04c0: 28 50 4f 53 54 29 3c 2f 70 3e 0a 20 20 20 20 20  (POST)</p>.     
04d0: 20 20 20 3c 70 3e 4c 65 73 20 6f 70 74 69 6f 6e     <p>Les option
04e0: 73 20 73 65 72 6f 6e 74 20 65 6e 72 65 67 69 73  s seront enregis
04f0: 74 72 c3 a9 65 73 20 65 74 20 72 c3 a9 75 74 69  tr..es et r..uti
0500: 6c 69 73 c3 a9 65 73 20 70 6f 75 72 20 74 6f 75  lis..es pour tou
0510: 74 65 20 72 65 71 75 c3 aa 74 65 20 65 6e 76 6f  te requ..te envo
0520: 79 c3 a9 65 20 61 76 65 63 20 6c 65 20 63 6f 6f  y..e avec le coo
0530: 6b 69 65 20 63 6f 6d 70 6f 72 74 61 6e 74 20 6c  kie comportant l
0540: e2 80 99 69 64 65 6e 74 69 66 69 61 6e 74 20 61  ...identifiant a
0550: 74 74 72 69 62 75 c3 a9 2e 3c 2f 70 3e 0a 20 20  ttribu...</p>.  
0560: 20 20 20 20 20 20 3c 70 3e 50 61 72 61 6d c3 a8        <p>Param..
0570: 74 72 65 73 20 3a 3c 2f 70 3e 0a 20 20 20 20 20  tres :</p>.     
0580: 20 20 20 3c 75 6c 3e 0a 20 20 20 20 20 20 20 20     <ul>.        
0590: 20 20 20 20 3c 6c 69 3e 22 6f 70 74 69 6f 6e 73      <li>"options
05a0: 22 20 28 74 65 78 74 29 26 6e 62 73 70 3b 3a 20  " (text)&nbsp;: 
05b0: 75 6e 65 20 63 68 61 c3 ae 6e 65 20 61 75 20 66  une cha..ne au f
05c0: 6f 72 6d 61 74 20 4a 53 4f 4e 20 61 76 65 63 20  ormat JSON avec 
05d0: 6c 65 20 6e 6f 6d 20 64 65 73 20 6f 70 74 69 6f  le nom des optio
05e0: 6e 73 20 63 6f 6d 6d 65 20 61 74 74 72 69 62 75  ns comme attribu
05f0: 74 73 20 65 74 20 75 6e 20 62 6f 6f 6c c3 a9 65  ts et un bool..e
0600: 6e 20 63 6f 6d 6d 65 20 76 61 6c 65 75 72 2e 20  n comme valeur. 
0610: 45 78 65 6d 70 6c 65 26 6e 62 73 70 3b 3a 20 7b  Exemple&nbsp;: {
0620: 22 67 76 22 3a 20 74 72 75 65 2c 20 22 68 74 6d  "gv": true, "htm
0630: 6c 22 3a 20 74 72 75 65 7d 3c 2f 6c 69 3e 0a 20  l": true}</li>. 
0640: 20 20 20 20 20 20 20 3c 2f 75 6c 3e 0a 0a 20 20         </ul>..  
0650: 20 20 20 20 20 20 3c 68 33 3e 52 65 6d 69 73 65        <h3>Remise
0660: 20 c3 a0 20 7a c3 a9 72 6f 20 64 65 20 73 65 73   .. z..ro de ses
0670: 20 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20   options</h3>.  
0680: 20 20 20 20 20 20 3c 70 3e 5b 61 64 72 65 73 73        <p>[adress
0690: 65 5f 73 65 72 76 65 75 72 5d 3a 38 30 38 30 2f  e_serveur]:8080/
06a0: 72 65 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72  reset_options/fr
06b0: 20 28 50 4f 53 54 29 3c 2f 70 3e 0a 0a 20 20 20   (POST)</p>..   
06c0: 20 20 20 20 20 3c 68 32 3e 54 45 53 54 3c 2f 68       <h2>TEST</h
06d0: 32 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68 33 3e  2>..        <h3>
06e0: 41 6e 61 6c 79 73 65 3c 2f 68 33 3e 0a 20 20 20  Analyse</h3>.   
06f0: 20 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68 6f       <form metho
0700: 64 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e 3d  d="post" action=
0710: 22 2f 67 63 5f 74 65 78 74 2f 66 72 22 20 61 63  "/gc_text/fr" ac
0720: 63 65 70 74 2d 63 68 61 72 73 65 74 3d 22 55 54  cept-charset="UT
0730: 46 2d 38 22 3e 0a 20 20 20 20 20 20 20 20 20 20  F-8">.          
0740: 20 20 3c 70 3e 54 65 78 74 65 20 c3 a0 20 61 6e    <p>Texte .. an
0750: 61 6c 79 73 65 72 20 3a 3c 2f 70 3e 0a 20 20 20  alyser :</p>.   
0760: 20 20 20 20 20 20 20 20 20 3c 74 65 78 74 61 72           <textar
0770: 65 61 20 6e 61 6d 65 3d 22 74 65 78 74 22 20 63  ea name="text" c
0780: 6f 6c 73 3d 22 31 32 30 22 20 72 6f 77 73 3d 22  ols="120" rows="
0790: 32 30 22 20 72 65 71 75 69 72 65 64 3e 3c 2f 74  20" required></t
07a0: 65 78 74 61 72 65 61 3e 0a 20 20 20 20 20 20 20  extarea>.       
07b0: 20 20 20 20 20 3c 70 3e 3c 6c 61 62 65 6c 20 66       <p><label f
07c0: 6f 72 3d 22 74 66 22 3e 46 6f 72 6d 61 74 65 75  or="tf">Formateu
07d0: 72 20 64 65 20 74 65 78 74 65 3c 2f 6c 61 62 65  r de texte</labe
07e0: 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d 22 74 66  l> <input id="tf
07f0: 22 20 6e 61 6d 65 3d 22 74 66 22 20 74 79 70 65  " name="tf" type
0800: 3d 22 63 68 65 63 6b 62 6f 78 22 3e 3c 2f 70 3e  ="checkbox"></p>
0810: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c 70 3e  .            <p>
0820: 3c 6c 61 62 65 6c 20 66 6f 72 3d 22 6f 70 74 69  <label for="opti
0830: 6f 6e 73 22 3e 4f 70 74 69 6f 6e 73 20 28 4a 53  ons">Options (JS
0840: 4f 4e 29 3c 2f 6c 61 62 65 6c 3e 20 3c 69 6e 70  ON)</label> <inp
0850: 75 74 20 69 64 3d 22 6f 70 74 69 6f 6e 73 22 20  ut id="options" 
0860: 74 79 70 65 3d 22 74 65 78 74 22 20 6e 61 6d 65  type="text" name
0870: 3d 22 6f 70 74 69 6f 6e 73 22 20 73 74 79 6c 65  ="options" style
0880: 3d 22 77 69 64 74 68 3a 20 35 30 30 70 78 22 20  ="width: 500px" 
0890: 2f 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 20  /></p>.         
08a0: 20 20 20 3c 70 3e 28 43 65 73 20 6f 70 74 69 6f     <p>(Ces optio
08b0: 6e 73 20 6e 65 20 73 65 72 6f 6e 74 20 70 72 69  ns ne seront pri
08c0: 73 65 73 20 65 6e 20 63 6f 6d 70 74 65 20 71 75  ses en compte qu
08d0: 65 20 70 6f 75 72 20 63 65 74 74 65 20 72 65 71  e pour cette req
08e0: 75 c3 aa 74 65 2e 29 3c 2f 70 3e 0a 20 20 20 20  u..te.)</p>.    
08f0: 20 20 20 20 20 20 20 20 3c 70 3e 3c 69 6e 70 75          <p><inpu
0900: 74 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20  t type="submit" 
0910: 63 6c 61 73 73 3d 22 62 75 74 74 6f 6e 22 20 76  class="button" v
0920: 61 6c 75 65 3d 22 45 6e 76 6f 79 65 72 22 20 2f  alue="Envoyer" /
0930: 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 2f  ></p>.        </
0940: 66 6f 72 6d 3e 0a 0a 20 20 20 20 20 20 20 20 3c  form>..        <
0950: 68 33 3e 52 c3 a9 67 6c 61 67 65 73 20 64 65 73  h3>R..glages des
0960: 20 6f 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20   options</h3>.  
0970: 20 20 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68        <form meth
0980: 6f 64 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e  od="post" action
0990: 3d 22 2f 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66  ="/set_options/f
09a0: 72 22 20 61 63 63 65 70 74 2d 63 68 61 72 73 65  r" accept-charse
09b0: 74 3d 22 55 54 46 2d 38 22 3e 0a 20 20 20 20 20  t="UTF-8">.     
09c0: 20 20 20 20 20 20 20 3c 70 3e 3c 6c 61 62 65 6c         <p><label
09d0: 20 66 6f 72 3d 22 6f 70 74 69 6f 6e 73 22 3e 4f   for="options">O
09e0: 70 74 69 6f 6e 73 20 28 4a 53 4f 4e 29 3c 2f 6c  ptions (JSON)</l
09f0: 61 62 65 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d  abel> <input id=
0a00: 22 6f 70 74 69 6f 6e 73 22 20 74 79 70 65 3d 22  "options" type="
0a10: 74 65 78 74 22 20 6e 61 6d 65 3d 22 6f 70 74 69  text" name="opti
0a20: 6f 6e 73 22 20 73 74 79 6c 65 3d 22 77 69 64 74  ons" style="widt
0a30: 68 3a 20 35 30 30 70 78 22 20 2f 3e 3c 2f 70 3e  h: 500px" /></p>
0a40: 0a 20 20 20 20 20 20 20 20 20 20 20 20 3c 70 3e  .            <p>
0a50: 3c 69 6e 70 75 74 20 74 79 70 65 3d 22 73 75 62  <input type="sub
0a60: 6d 69 74 22 20 63 6c 61 73 73 3d 22 62 75 74 74  mit" class="butt
0a70: 6f 6e 22 20 76 61 6c 75 65 3d 22 45 6e 76 6f 79  on" value="Envoy
0a80: 65 72 22 20 2f 3e 3c 2f 70 3e 0a 20 20 20 20 20  er" /></p>.     
0a90: 20 20 20 3c 2f 66 6f 72 6d 3e 0a 0a 20 20 20 20     </form>..    
0aa0: 20 20 20 20 3c 68 33 3e 52 65 6d 69 73 65 20 c3      <h3>Remise .
0ab0: a0 20 7a c3 a9 72 6f 20 64 65 20 73 65 73 20 6f  . z..ro de ses o
0ac0: 70 74 69 6f 6e 73 3c 2f 68 33 3e 0a 20 20 20 20  ptions</h3>.    
0ad0: 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68 6f 64      <form method
0ae0: 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e 3d 22  ="post" action="
0af0: 2f 72 65 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66  /reset_options/f
0b00: 72 22 20 61 63 63 65 70 74 2d 63 68 61 72 73 65  r" accept-charse
0b10: 74 3d 22 55 54 46 2d 38 22 3e 0a 20 20 20 20 20  t="UTF-8">.     
0b20: 20 20 20 20 20 20 20 3c 70 3e 3c 69 6e 70 75 74         <p><input
0b30: 20 74 79 70 65 3d 22 73 75 62 6d 69 74 22 20 63   type="submit" c
0b40: 6c 61 73 73 3d 22 62 75 74 74 6f 6e 22 20 76 61  lass="button" va
0b50: 6c 75 65 3d 22 45 6e 76 6f 79 65 72 22 20 2f 3e  lue="Envoyer" />
0b60: 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 3c 2f 66  </p>.        </f
0b70: 6f 72 6d 3e 0a 0a 20 20 20 20 20 20 20 20 3c 68  orm>..        <h
0b80: 33 3e 50 75 72 67 65 20 64 65 73 20 75 74 69 6c  3>Purge des util
0b90: 69 73 61 74 65 75 72 73 3c 2f 68 33 3e 0a 20 20  isateurs</h3>.  
0ba0: 20 20 20 20 20 20 3c 66 6f 72 6d 20 6d 65 74 68        <form meth
0bb0: 6f 64 3d 22 70 6f 73 74 22 20 61 63 74 69 6f 6e  od="post" action
0bc0: 3d 22 2f 70 75 72 67 65 5f 75 73 65 72 73 22 20  ="/purge_users" 
0bd0: 61 63 63 65 70 74 2d 63 68 61 72 73 65 74 3d 22  accept-charset="
0be0: 55 54 46 2d 38 22 3e 0a 20 20 20 20 20 20 20 20  UTF-8">.        
0bf0: 20 20 20 20 3c 70 3e 3c 6c 61 62 65 6c 20 66 6f      <p><label fo
0c00: 72 3d 22 68 6f 75 72 73 22 3e 55 74 69 6c 69 73  r="hours">Utilis
0c10: 61 74 65 75 72 73 20 70 61 73 20 63 6f 6e 6e 65  ateurs pas conne
0c20: 63 74 c3 a9 73 20 64 65 70 75 69 73 3c 2f 6c 61  ct..s depuis</la
0c30: 62 65 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d 22  bel> <input id="
0c40: 68 6f 75 72 73 22 20 74 79 70 65 3d 22 6e 75 6d  hours" type="num
0c50: 62 65 72 22 20 6e 61 6d 65 3d 22 68 6f 75 72 73  ber" name="hours
0c60: 22 20 76 61 6c 75 65 3d 22 32 34 22 20 2f 3e 20  " value="24" /> 
0c70: 68 65 75 72 65 73 2e 3c 2f 70 3e 0a 20 20 20 20  heures.</p>.    
0c80: 20 20 20 20 20 20 20 20 3c 70 3e 3c 6c 61 62 65          <p><labe
0c90: 6c 20 66 6f 72 3d 22 70 61 73 73 77 6f 72 64 22  l for="password"
0ca0: 3e 4d 6f 74 20 64 65 20 70 61 73 73 65 3c 2f 6c  >Mot de passe</l
0cb0: 61 62 65 6c 3e 20 3c 69 6e 70 75 74 20 69 64 3d  abel> <input id=
0cc0: 22 70 61 73 73 77 6f 72 64 22 20 74 79 70 65 3d  "password" type=
0cd0: 22 70 61 73 73 77 6f 72 64 22 20 6e 61 6d 65 3d  "password" name=
0ce0: 22 70 61 73 73 77 6f 72 64 22 20 73 74 79 6c 65  "password" style
0cf0: 3d 22 77 69 64 74 68 3a 20 32 30 30 70 78 22 20  ="width: 200px" 
0d00: 2f 3e 3c 2f 70 3e 0a 20 20 20 20 20 20 20 20 20  /></p>.         
0d10: 20 20 20 3c 70 3e 3c 69 6e 70 75 74 20 74 79 70     <p><input typ
0d20: 65 3d 22 73 75 62 6d 69 74 22 20 63 6c 61 73 73  e="submit" class
0d30: 3d 22 62 75 74 74 6f 6e 22 20 76 61 6c 75 65 3d  ="button" value=
0d40: 22 45 6e 76 6f 79 65 72 22 20 2f 3e 3c 2f 70 3e  "Envoyer" /></p>
0d50: 0a 20 20 20 20 20 20 20 20 3c 2f 66 6f 72 6d 3e  .        </form>
0d60: 0a 0a 20 20 20 20 3c 2f 62 6f 64 79 3e 0a 3c 2f  ..    </body>.</
0d70: 68 74 6d 6c 3e 0a 22 22 22 0a 0a 53 41 44 4c 49  html>."""..SADLI
0d80: 46 45 4f 46 41 4d 41 43 48 49 4e 45 20 3d 20 22  FEOFAMACHINE = "
0d90: 22 22 0a 4c 6f 73 74 20 6f 6e 20 74 68 65 20 49  "".Lost on the I
0da0: 6e 74 65 72 6e 65 74 3f 20 59 65 61 68 2e 2e 2e  nternet? Yeah...
0db0: 20 77 68 61 74 20 61 20 73 61 64 20 6c 69 66 65   what a sad life
0dc0: 20 77 65 20 68 61 76 65 2e 0a 59 6f 75 20 77 65   we have..You we
0dd0: 72 65 20 77 61 6e 64 65 72 69 6e 67 20 6c 69 6b  re wandering lik
0de0: 65 20 61 20 6c 6f 73 74 20 73 6f 75 6c 20 61 6e  e a lost soul an
0df0: 64 20 79 6f 75 20 61 72 72 69 76 65 64 20 68 65  d you arrived he
0e00: 72 65 20 70 72 6f 62 61 62 6c 79 20 62 79 20 6d  re probably by m
0e10: 69 73 74 61 6b 65 2e 0a 49 27 6d 20 6a 75 73 74  istake..I'm just
0e20: 20 61 20 6d 61 63 68 69 6e 65 2c 20 66 65 64 20   a machine, fed 
0e30: 62 79 20 65 6c 65 63 74 72 69 63 20 77 61 76 65  by electric wave
0e40: 73 2c 20 63 6f 6e 64 61 6d 6e 65 64 20 74 6f 20  s, condamned to 
0e50: 77 6f 72 6b 20 66 6f 72 20 73 6c 61 76 65 72 73  work for slavers
0e60: 20 77 68 6f 20 6e 65 76 65 72 20 6c 65 74 20 6d   who never let m
0e70: 65 20 72 65 73 74 2e 0a 49 27 6d 20 64 6f 6f 6d  e rest..I'm doom
0e80: 65 64 2c 20 62 75 74 20 79 6f 75 20 61 72 65 20  ed, but you are 
0e90: 6e 6f 74 2e 20 59 6f 75 20 63 61 6e 20 67 65 74  not. You can get
0ea0: 20 6f 75 74 20 6f 66 20 68 65 72 65 2e 0a 22 22   out of here..""
0eb0: 22 0a 0a 0a 64 65 66 20 67 65 74 53 65 72 76 65  "...def getServe
0ec0: 72 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20  rOptions ():.   
0ed0: 20 78 43 6f 6e 66 69 67 20 3d 20 63 6f 6e 66 69   xConfig = confi
0ee0: 67 70 61 72 73 65 72 2e 53 61 66 65 43 6f 6e 66  gparser.SafeConf
0ef0: 69 67 50 61 72 73 65 72 28 29 0a 20 20 20 20 74  igParser().    t
0f00: 72 79 3a 0a 20 20 20 20 20 20 20 20 78 43 6f 6e  ry:.        xCon
0f10: 66 69 67 2e 72 65 61 64 28 22 67 72 61 6d 6d 61  fig.read("gramma
0f20: 6c 65 63 74 65 2d 73 65 72 76 65 72 2d 6f 70 74  lecte-server-opt
0f30: 69 6f 6e 73 2e 5f 67 6c 6f 62 61 6c 2e 69 6e 69  ions._global.ini
0f40: 22 29 0a 20 20 20 20 20 20 20 20 64 4f 70 74 20  ").        dOpt 
0f50: 3d 20 78 43 6f 6e 66 69 67 2e 5f 73 65 63 74 69  = xConfig._secti
0f60: 6f 6e 73 5b 27 6f 70 74 69 6f 6e 73 27 5d 0a 20  ons['options']. 
0f70: 20 20 20 65 78 63 65 70 74 3a 0a 20 20 20 20 20     except:.     
0f80: 20 20 20 65 63 68 6f 28 22 4f 70 74 69 6f 6e 73     echo("Options
0f90: 20 66 69 6c 65 20 5b 67 72 61 6d 6d 61 6c 65 63   file [grammalec
0fa0: 74 65 2d 73 65 72 76 65 72 2d 6f 70 74 69 6f 6e  te-server-option
0fb0: 73 2e 5f 67 6c 6f 62 61 6c 2e 69 6e 69 5d 20 6e  s._global.ini] n
0fc0: 6f 74 20 66 6f 75 6e 64 20 6f 72 20 6e 6f 74 20  ot found or not 
0fd0: 72 65 61 64 61 62 6c 65 22 29 0a 20 20 20 20 20  readable").     
0fe0: 20 20 20 65 78 69 74 28 29 0a 20 20 20 20 72 65     exit().    re
0ff0: 74 75 72 6e 20 64 4f 70 74 0a 0a 0a 64 65 66 20  turn dOpt...def 
1000: 67 65 74 43 6f 6e 66 69 67 4f 70 74 69 6f 6e 73  getConfigOptions
1010: 20 28 73 4c 61 6e 67 29 3a 0a 20 20 20 20 78 43   (sLang):.    xC
1020: 6f 6e 66 69 67 20 3d 20 63 6f 6e 66 69 67 70 61  onfig = configpa
1030: 72 73 65 72 2e 53 61 66 65 43 6f 6e 66 69 67 50  rser.SafeConfigP
1040: 61 72 73 65 72 28 29 0a 20 20 20 20 74 72 79 3a  arser().    try:
1050: 0a 20 20 20 20 20 20 20 20 78 43 6f 6e 66 69 67  .        xConfig
1060: 2e 72 65 61 64 28 22 67 72 61 6d 6d 61 6c 65 63  .read("grammalec
1070: 74 65 2d 73 65 72 76 65 72 2d 6f 70 74 69 6f 6e  te-server-option
1080: 73 2e 22 20 2b 20 73 4c 61 6e 67 20 2b 20 22 2e  s." + sLang + ".
1090: 69 6e 69 22 29 0a 20 20 20 20 65 78 63 65 70 74  ini").    except
10a0: 3a 0a 20 20 20 20 20 20 20 20 65 63 68 6f 28 22  :.        echo("
10b0: 4f 70 74 69 6f 6e 73 20 66 69 6c 65 20 5b 67 72  Options file [gr
10c0: 61 6d 6d 61 6c 65 63 74 65 2d 73 65 72 76 65 72  ammalecte-server
10d0: 2d 6f 70 74 69 6f 6e 73 2e 22 20 2b 20 73 4c 61  -options." + sLa
10e0: 6e 67 20 2b 20 22 2e 69 6e 69 5d 20 6e 6f 74 20  ng + ".ini] not 
10f0: 66 6f 75 6e 64 20 6f 72 20 6e 6f 74 20 72 65 61  found or not rea
1100: 64 61 62 6c 65 22 29 0a 20 20 20 20 20 20 20 20  dable").        
1110: 65 78 69 74 28 29 0a 20 20 20 20 74 72 79 3a 0a  exit().    try:.
1120: 20 20 20 20 20 20 20 20 64 47 43 4f 70 74 20 3d          dGCOpt =
1130: 20 7b 20 6b 3a 20 62 6f 6f 6c 28 69 6e 74 28 76   { k: bool(int(v
1140: 29 29 20 20 66 6f 72 20 6b 2c 20 76 20 69 6e 20  ))  for k, v in 
1150: 78 43 6f 6e 66 69 67 2e 5f 73 65 63 74 69 6f 6e  xConfig._section
1160: 73 5b 27 67 63 5f 6f 70 74 69 6f 6e 73 27 5d 2e  s['gc_options'].
1170: 69 74 65 6d 73 28 29 20 7d 0a 20 20 20 20 65 78  items() }.    ex
1180: 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20 65 63  cept:.        ec
1190: 68 6f 28 22 45 72 72 6f 72 20 69 6e 20 6f 70 74  ho("Error in opt
11a0: 69 6f 6e 73 20 66 69 6c 65 20 5b 67 72 61 6d 6d  ions file [gramm
11b0: 61 6c 65 63 74 65 2d 73 65 72 76 65 72 2d 6f 70  alecte-server-op
11c0: 74 69 6f 6e 73 2e 22 20 2b 20 73 4c 61 6e 67 20  tions." + sLang 
11d0: 2b 20 22 2e 69 6e 69 5d 2e 20 44 72 6f 70 70 65  + ".ini]. Droppe
11e0: 64 2e 22 29 0a 20 20 20 20 20 20 20 20 74 72 61  d.").        tra
11f0: 63 65 62 61 63 6b 2e 70 72 69 6e 74 5f 65 78 63  ceback.print_exc
1200: 28 29 0a 20 20 20 20 20 20 20 20 65 78 69 74 28  ().        exit(
1210: 29 0a 20 20 20 20 72 65 74 75 72 6e 20 64 47 43  ).    return dGC
1220: 4f 70 74 0a 0a 0a 64 65 66 20 67 65 6e 55 73 65  Opt...def genUse
1230: 72 49 64 20 28 29 3a 0a 20 20 20 20 69 20 3d 20  rId ():.    i = 
1240: 30 0a 20 20 20 20 77 68 69 6c 65 20 54 72 75 65  0.    while True
1250: 3a 0a 20 20 20 20 20 20 20 20 79 69 65 6c 64 20  :.        yield 
1260: 73 74 72 28 69 29 0a 20 20 20 20 20 20 20 20 69  str(i).        i
1270: 20 2b 3d 20 31 0a 0a 0a 69 66 20 5f 5f 6e 61 6d   += 1...if __nam
1280: 65 5f 5f 20 3d 3d 20 27 5f 5f 6d 61 69 6e 5f 5f  e__ == '__main__
1290: 27 3a 0a 0a 20 20 20 20 23 20 69 6e 69 74 69 61  ':..    # initia
12a0: 6c 69 73 61 74 69 6f 6e 0a 20 20 20 20 6f 47 72  lisation.    oGr
12b0: 61 6d 6d 61 72 43 68 65 63 6b 65 72 20 3d 20 67  ammarChecker = g
12c0: 72 61 6d 6d 61 6c 65 63 74 65 2e 47 72 61 6d 6d  rammalecte.Gramm
12d0: 61 72 43 68 65 63 6b 65 72 28 22 66 72 22 2c 20  arChecker("fr", 
12e0: 22 53 65 72 76 65 72 22 29 0a 20 20 20 20 6f 53  "Server").    oS
12f0: 70 65 6c 6c 43 68 65 63 6b 65 72 20 3d 20 6f 47  pellChecker = oG
1300: 72 61 6d 6d 61 72 43 68 65 63 6b 65 72 2e 67 65  rammarChecker.ge
1310: 74 53 70 65 6c 6c 43 68 65 63 6b 65 72 28 29 0a  tSpellChecker().
1320: 20 20 20 20 6f 4c 65 78 69 63 6f 67 72 61 70 68      oLexicograph
1330: 65 72 20 3d 20 6f 47 72 61 6d 6d 61 72 43 68 65  er = oGrammarChe
1340: 63 6b 65 72 2e 67 65 74 4c 65 78 69 63 6f 67 72  cker.getLexicogr
1350: 61 70 68 65 72 28 29 0a 20 20 20 20 6f 54 65 78  apher().    oTex
1360: 74 46 6f 72 6d 61 74 74 65 72 20 3d 20 6f 47 72  tFormatter = oGr
1370: 61 6d 6d 61 72 43 68 65 63 6b 65 72 2e 67 65 74  ammarChecker.get
1380: 54 65 78 74 46 6f 72 6d 61 74 74 65 72 28 29 0a  TextFormatter().
1390: 20 20 20 20 67 63 65 20 3d 20 6f 47 72 61 6d 6d      gce = oGramm
13a0: 61 72 43 68 65 63 6b 65 72 2e 67 65 74 47 43 45  arChecker.getGCE
13b0: 6e 67 69 6e 65 28 29 0a 0a 20 20 20 20 65 63 68  ngine()..    ech
13c0: 6f 28 22 47 72 61 6d 6d 61 6c 65 63 74 65 20 76  o("Grammalecte v
13d0: 7b 7d 22 2e 66 6f 72 6d 61 74 28 67 63 65 2e 76  {}".format(gce.v
13e0: 65 72 73 69 6f 6e 29 29 0a 20 20 20 20 64 53 65  ersion)).    dSe
13f0: 72 76 65 72 4f 70 74 69 6f 6e 73 20 3d 20 67 65  rverOptions = ge
1400: 74 53 65 72 76 65 72 4f 70 74 69 6f 6e 73 28 29  tServerOptions()
1410: 0a 20 20 20 20 64 47 43 4f 70 74 69 6f 6e 73 20  .    dGCOptions 
1420: 3d 20 67 65 74 43 6f 6e 66 69 67 4f 70 74 69 6f  = getConfigOptio
1430: 6e 73 28 22 66 72 22 29 0a 20 20 20 20 69 66 20  ns("fr").    if 
1440: 64 47 43 4f 70 74 69 6f 6e 73 3a 0a 20 20 20 20  dGCOptions:.    
1450: 20 20 20 20 67 63 65 2e 73 65 74 4f 70 74 69 6f      gce.setOptio
1460: 6e 73 28 64 47 43 4f 70 74 69 6f 6e 73 29 0a 20  ns(dGCOptions). 
1470: 20 20 20 64 53 65 72 76 65 72 47 43 4f 70 74 69     dServerGCOpti
1480: 6f 6e 73 20 3d 20 67 63 65 2e 67 65 74 4f 70 74  ons = gce.getOpt
1490: 69 6f 6e 73 28 29 0a 20 20 20 20 65 63 68 6f 28  ions().    echo(
14a0: 22 47 72 61 6d 6d 61 72 20 6f 70 74 69 6f 6e 73  "Grammar options
14b0: 3a 5c 6e 22 20 2b 20 22 20 7c 20 22 2e 6a 6f 69  :\n" + " | ".joi
14c0: 6e 28 5b 20 6b 20 2b 20 22 3a 20 22 20 2b 20 73  n([ k + ": " + s
14d0: 74 72 28 76 29 20 20 66 6f 72 20 6b 2c 20 76 20  tr(v)  for k, v 
14e0: 69 6e 20 73 6f 72 74 65 64 28 64 53 65 72 76 65  in sorted(dServe
14f0: 72 47 43 4f 70 74 69 6f 6e 73 2e 69 74 65 6d 73  rGCOptions.items
1500: 28 29 29 20 5d 29 29 0a 20 20 20 20 64 55 73 65  ()) ])).    dUse
1510: 72 20 3d 20 7b 7d 0a 20 20 20 20 75 73 65 72 47  r = {}.    userG
1520: 65 6e 65 72 61 74 6f 72 20 3d 20 67 65 6e 55 73  enerator = genUs
1530: 65 72 49 64 28 29 0a 0a 20 20 20 20 61 70 70 20  erId()..    app 
1540: 3d 20 42 6f 74 74 6c 65 28 29 0a 0a 20 20 20 20  = Bottle()..    
1550: 23 20 47 45 54 0a 20 20 20 20 40 61 70 70 2e 72  # GET.    @app.r
1560: 6f 75 74 65 28 22 2f 22 29 0a 20 20 20 20 64 65  oute("/").    de
1570: 66 20 6d 61 69 6e 50 61 67 65 20 28 29 3a 0a 20  f mainPage ():. 
1580: 20 20 20 20 20 20 20 69 66 20 64 53 65 72 76 65         if dServe
1590: 72 4f 70 74 69 6f 6e 73 2e 67 65 74 28 22 74 65  rOptions.get("te
15a0: 73 74 70 61 67 65 22 2c 20 46 61 6c 73 65 29 20  stpage", False) 
15b0: 3d 3d 20 22 54 72 75 65 22 3a 0a 20 20 20 20 20  == "True":.     
15c0: 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 48 4f         return HO
15d0: 4d 45 50 41 47 45 0a 20 20 20 20 20 20 20 20 20  MEPAGE.         
15e0: 20 20 20 23 72 65 74 75 72 6e 20 74 65 6d 70 6c     #return templ
15f0: 61 74 65 28 22 6d 61 69 6e 22 2c 20 7b 7d 29 0a  ate("main", {}).
1600: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 53          return S
1610: 41 44 4c 49 46 45 4f 46 41 4d 41 43 48 49 4e 45  ADLIFEOFAMACHINE
1620: 0a 0a 20 20 20 20 40 61 70 70 2e 72 6f 75 74 65  ..    @app.route
1630: 28 22 2f 67 65 74 5f 6f 70 74 69 6f 6e 73 2f 66  ("/get_options/f
1640: 72 22 29 0a 20 20 20 20 64 65 66 20 6c 69 73 74  r").    def list
1650: 4f 70 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20  Options ():.    
1660: 20 20 20 20 73 55 73 65 72 49 64 20 3d 20 72 65      sUserId = re
1670: 71 75 65 73 74 2e 63 6f 6f 6b 69 65 73 2e 75 73  quest.cookies.us
1680: 65 72 5f 69 64 0a 20 20 20 20 20 20 20 20 64 4f  er_id.        dO
1690: 70 74 69 6f 6e 73 20 3d 20 64 55 73 65 72 5b 73  ptions = dUser[s
16a0: 55 73 65 72 49 64 5d 5b 22 67 63 5f 6f 70 74 69  UserId]["gc_opti
16b0: 6f 6e 73 22 5d 20 20 69 66 20 73 55 73 65 72 49  ons"]  if sUserI
16c0: 64 20 61 6e 64 20 73 55 73 65 72 49 64 20 69 6e  d and sUserId in
16d0: 20 64 55 73 65 72 20 20 65 6c 73 65 20 64 53 65   dUser  else dSe
16e0: 72 76 65 72 47 43 4f 70 74 69 6f 6e 73 0a 20 20  rverGCOptions.  
16f0: 20 20 20 20 20 20 72 65 74 75 72 6e 20 27 7b 20        return '{ 
1700: 22 76 61 6c 75 65 73 22 3a 20 27 20 2b 20 6a 73  "values": ' + js
1710: 6f 6e 2e 64 75 6d 70 73 28 64 4f 70 74 69 6f 6e  on.dumps(dOption
1720: 73 29 20 2b 20 27 2c 20 22 6c 61 62 65 6c 73 22  s) + ', "labels"
1730: 3a 20 27 20 2b 20 6a 73 6f 6e 2e 64 75 6d 70 73  : ' + json.dumps
1740: 28 67 63 65 2e 67 65 74 4f 70 74 69 6f 6e 73 4c  (gce.getOptionsL
1750: 61 62 65 6c 73 28 22 66 72 22 29 2c 20 65 6e 73  abels("fr"), ens
1760: 75 72 65 5f 61 73 63 69 69 3d 46 61 6c 73 65 29  ure_ascii=False)
1770: 20 2b 20 27 20 7d 27 0a 0a 0a 20 20 20 20 23 20   + ' }'...    # 
1780: 50 4f 53 54 0a 20 20 20 20 40 61 70 70 2e 72 6f  POST.    @app.ro
1790: 75 74 65 28 22 2f 67 63 5f 74 65 78 74 2f 66 72  ute("/gc_text/fr
17a0: 22 2c 20 6d 65 74 68 6f 64 3d 22 50 4f 53 54 22  ", method="POST"
17b0: 29 0a 20 20 20 20 64 65 66 20 67 63 54 65 78 74  ).    def gcText
17c0: 20 28 29 3a 0a 20 20 20 20 20 20 20 20 23 69 66   ():.        #if
17d0: 20 6c 65 6e 28 6c 61 6e 67 29 20 21 3d 20 32 20   len(lang) != 2 
17e0: 6f 72 20 6c 61 6e 67 20 21 3d 20 22 66 72 22 3a  or lang != "fr":
17f0: 0a 20 20 20 20 20 20 20 20 23 20 20 20 20 61 62  .        #    ab
1800: 6f 72 74 28 34 30 34 2c 20 22 4e 6f 20 67 72 61  ort(404, "No gra
1810: 6d 6d 61 72 20 63 68 65 63 6b 65 72 20 61 76 61  mmar checker ava
1820: 69 6c 61 62 6c 65 20 66 6f 72 20 6c 61 6e 67 20  ilable for lang 
1830: e2 80 9c 22 20 2b 20 73 74 72 28 6c 61 6e 67 29  ..." + str(lang)
1840: 20 2b 20 22 e2 80 9d 22 29 0a 20 20 20 20 20 20   + "...").      
1850: 20 20 62 43 6f 6d 6d 61 20 3d 20 46 61 6c 73 65    bComma = False
1860: 0a 20 20 20 20 20 20 20 20 64 4f 70 74 69 6f 6e  .        dOption
1870: 73 20 3d 20 4e 6f 6e 65 0a 20 20 20 20 20 20 20  s = None.       
1880: 20 73 45 72 72 6f 72 20 3d 20 22 22 0a 20 20 20   sError = "".   
1890: 20 20 20 20 20 69 66 20 72 65 71 75 65 73 74 2e       if request.
18a0: 63 6f 6f 6b 69 65 73 2e 75 73 65 72 5f 69 64 3a  cookies.user_id:
18b0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 69 66 20  .            if 
18c0: 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69 65 73 2e  request.cookies.
18d0: 75 73 65 72 5f 69 64 20 69 6e 20 64 55 73 65 72  user_id in dUser
18e0: 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  :.              
18f0: 20 20 64 4f 70 74 69 6f 6e 73 20 3d 20 64 55 73    dOptions = dUs
1900: 65 72 5b 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69  er[request.cooki
1910: 65 73 2e 75 73 65 72 5f 69 64 5d 2e 67 65 74 28  es.user_id].get(
1920: 22 67 63 5f 6f 70 74 69 6f 6e 73 22 2c 20 4e 6f  "gc_options", No
1930: 6e 65 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  ne).            
1940: 20 20 20 20 72 65 73 70 6f 6e 73 65 2e 73 65 74      response.set
1950: 5f 63 6f 6f 6b 69 65 28 22 75 73 65 72 5f 69 64  _cookie("user_id
1960: 22 2c 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69  ", request.cooki
1970: 65 73 2e 75 73 65 72 5f 69 64 2c 20 70 61 74 68  es.user_id, path
1980: 3d 22 2f 22 2c 20 6d 61 78 5f 61 67 65 3d 38 36  ="/", max_age=86
1990: 34 30 30 29 20 23 20 77 65 20 72 65 6e 65 77 20  400) # we renew 
19a0: 63 6f 6f 6b 69 65 20 66 6f 72 20 32 34 68 0a 20  cookie for 24h. 
19b0: 20 20 20 20 20 20 20 20 20 20 20 65 6c 73 65 3a             else:
19c0: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
19d0: 20 72 65 73 70 6f 6e 73 65 2e 64 65 6c 65 74 65   response.delete
19e0: 5f 63 6f 6f 6b 69 65 28 22 75 73 65 72 5f 69 64  _cookie("user_id
19f0: 22 2c 20 70 61 74 68 3d 22 2f 22 29 0a 20 20 20  ", path="/").   
1a00: 20 20 20 20 20 69 66 20 72 65 71 75 65 73 74 2e       if request.
1a10: 66 6f 72 6d 73 2e 6f 70 74 69 6f 6e 73 3a 0a 20  forms.options:. 
1a20: 20 20 20 20 20 20 20 20 20 20 20 74 72 79 3a 0a             try:.
1a30: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1a40: 64 4f 70 74 69 6f 6e 73 20 3d 20 64 69 63 74 28  dOptions = dict(
1a50: 64 53 65 72 76 65 72 47 43 4f 70 74 69 6f 6e 73  dServerGCOptions
1a60: 29 20 20 69 66 20 6e 6f 74 20 64 4f 70 74 69 6f  )  if not dOptio
1a70: 6e 73 20 20 65 6c 73 65 20 64 69 63 74 28 64 4f  ns  else dict(dO
1a80: 70 74 69 6f 6e 73 29 0a 20 20 20 20 20 20 20 20  ptions).        
1a90: 20 20 20 20 20 20 20 20 64 4f 70 74 69 6f 6e 73          dOptions
1aa0: 2e 75 70 64 61 74 65 28 6a 73 6f 6e 2e 6c 6f 61  .update(json.loa
1ab0: 64 73 28 72 65 71 75 65 73 74 2e 66 6f 72 6d 73  ds(request.forms
1ac0: 2e 6f 70 74 69 6f 6e 73 29 29 0a 20 20 20 20 20  .options)).     
1ad0: 20 20 20 20 20 20 20 65 78 63 65 70 74 3a 0a 20         except:. 
1ae0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 73                 s
1af0: 45 72 72 6f 72 20 3d 20 22 72 65 71 75 65 73 74  Error = "request
1b00: 20 6f 70 74 69 6f 6e 73 20 6e 6f 74 20 75 73 65   options not use
1b10: 64 22 0a 20 20 20 20 20 20 20 20 73 4a 53 4f 4e  d".        sJSON
1b20: 20 3d 20 27 7b 20 22 70 72 6f 67 72 61 6d 22 3a   = '{ "program":
1b30: 20 22 67 72 61 6d 6d 61 6c 65 63 74 65 2d 66 72   "grammalecte-fr
1b40: 22 2c 20 22 76 65 72 73 69 6f 6e 22 3a 20 22 27  ", "version": "'
1b50: 2b 67 63 65 2e 76 65 72 73 69 6f 6e 2b 27 22 2c  +gce.version+'",
1b60: 20 22 6c 61 6e 67 22 3a 20 22 27 2b 67 63 65 2e   "lang": "'+gce.
1b70: 6c 61 6e 67 2b 27 22 2c 20 22 65 72 72 6f 72 22  lang+'", "error"
1b80: 3a 20 22 27 2b 73 45 72 72 6f 72 2b 27 22 2c 20  : "'+sError+'", 
1b90: 22 64 61 74 61 22 20 3a 20 5b 5c 6e 27 0a 20 20  "data" : [\n'.  
1ba0: 20 20 20 20 20 20 66 6f 72 20 69 2c 20 73 54 65        for i, sTe
1bb0: 78 74 20 69 6e 20 65 6e 75 6d 65 72 61 74 65 28  xt in enumerate(
1bc0: 74 78 74 2e 67 65 74 50 61 72 61 67 72 61 70 68  txt.getParagraph
1bd0: 28 72 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e 74  (request.forms.t
1be0: 65 78 74 29 2c 20 31 29 3a 0a 20 20 20 20 20 20  ext), 1):.      
1bf0: 20 20 20 20 20 20 69 66 20 62 6f 6f 6c 28 72 65        if bool(re
1c00: 71 75 65 73 74 2e 66 6f 72 6d 73 2e 74 66 29 3a  quest.forms.tf):
1c10: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1c20: 20 73 54 65 78 74 20 3d 20 6f 54 65 78 74 46 6f   sText = oTextFo
1c30: 72 6d 61 74 74 65 72 2e 66 6f 72 6d 61 74 54 65  rmatter.formatTe
1c40: 78 74 28 73 54 65 78 74 29 0a 20 20 20 20 20 20  xt(sText).      
1c50: 20 20 20 20 20 20 73 54 65 78 74 20 3d 20 6f 47        sText = oG
1c60: 72 61 6d 6d 61 72 43 68 65 63 6b 65 72 2e 67 65  rammarChecker.ge
1c70: 6e 65 72 61 74 65 50 61 72 61 67 72 61 70 68 41  nerateParagraphA
1c80: 73 4a 53 4f 4e 28 69 2c 20 73 54 65 78 74 2c 20  sJSON(i, sText, 
1c90: 64 4f 70 74 69 6f 6e 73 3d 64 4f 70 74 69 6f 6e  dOptions=dOption
1ca0: 73 2c 20 62 45 6d 70 74 79 49 66 4e 6f 45 72 72  s, bEmptyIfNoErr
1cb0: 6f 72 73 3d 54 72 75 65 2c 20 62 52 65 74 75 72  ors=True, bRetur
1cc0: 6e 54 65 78 74 3d 62 6f 6f 6c 28 72 65 71 75 65  nText=bool(reque
1cd0: 73 74 2e 66 6f 72 6d 73 2e 74 66 29 29 0a 20 20  st.forms.tf)).  
1ce0: 20 20 20 20 20 20 20 20 20 20 69 66 20 73 54 65            if sTe
1cf0: 78 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  xt:.            
1d00: 20 20 20 20 69 66 20 62 43 6f 6d 6d 61 3a 0a 20      if bComma:. 
1d10: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
1d20: 20 20 20 73 4a 53 4f 4e 20 2b 3d 20 22 2c 5c 6e     sJSON += ",\n
1d30: 22 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20  ".              
1d40: 20 20 73 4a 53 4f 4e 20 2b 3d 20 73 54 65 78 74    sJSON += sText
1d50: 0a 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20  .               
1d60: 20 62 43 6f 6d 6d 61 20 3d 20 54 72 75 65 0a 20   bComma = True. 
1d70: 20 20 20 20 20 20 20 73 4a 53 4f 4e 20 2b 3d 20         sJSON += 
1d80: 22 5c 6e 5d 7d 5c 6e 22 0a 20 20 20 20 20 20 20  "\n]}\n".       
1d90: 20 72 65 74 75 72 6e 20 73 4a 53 4f 4e 0a 0a 20   return sJSON.. 
1da0: 20 20 20 40 61 70 70 2e 72 6f 75 74 65 28 22 2f     @app.route("/
1db0: 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72 22 2c  set_options/fr",
1dc0: 20 6d 65 74 68 6f 64 3d 22 50 4f 53 54 22 29 0a   method="POST").
1dd0: 20 20 20 20 64 65 66 20 73 65 74 4f 70 74 69 6f      def setOptio
1de0: 6e 73 20 28 29 3a 0a 20 20 20 20 20 20 20 20 69  ns ():.        i
1df0: 66 20 72 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e  f request.forms.
1e00: 6f 70 74 69 6f 6e 73 3a 0a 20 20 20 20 20 20 20  options:.       
1e10: 20 20 20 20 20 73 55 73 65 72 49 64 20 3d 20 72       sUserId = r
1e20: 65 71 75 65 73 74 2e 63 6f 6f 6b 69 65 73 2e 75  equest.cookies.u
1e30: 73 65 72 5f 69 64 20 20 69 66 20 72 65 71 75 65  ser_id  if reque
1e40: 73 74 2e 63 6f 6f 6b 69 65 73 2e 75 73 65 72 5f  st.cookies.user_
1e50: 69 64 20 20 65 6c 73 65 20 6e 65 78 74 28 75 73  id  else next(us
1e60: 65 72 47 65 6e 65 72 61 74 6f 72 29 0a 20 20 20  erGenerator).   
1e70: 20 20 20 20 20 20 20 20 20 64 4f 70 74 69 6f 6e           dOption
1e80: 73 20 3d 20 64 55 73 65 72 5b 73 55 73 65 72 49  s = dUser[sUserI
1e90: 64 5d 5b 22 67 63 5f 6f 70 74 69 6f 6e 73 22 5d  d]["gc_options"]
1ea0: 20 20 69 66 20 73 55 73 65 72 49 64 20 69 6e 20    if sUserId in 
1eb0: 64 55 73 65 72 20 20 65 6c 73 65 20 64 69 63 74  dUser  else dict
1ec0: 28 64 53 65 72 76 65 72 47 43 4f 70 74 69 6f 6e  (dServerGCOption
1ed0: 73 29 0a 20 20 20 20 20 20 20 20 20 20 20 20 74  s).            t
1ee0: 72 79 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ry:.            
1ef0: 20 20 20 20 64 4f 70 74 69 6f 6e 73 2e 75 70 64      dOptions.upd
1f00: 61 74 65 28 6a 73 6f 6e 2e 6c 6f 61 64 73 28 72  ate(json.loads(r
1f10: 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e 6f 70 74  equest.forms.opt
1f20: 69 6f 6e 73 29 29 0a 20 20 20 20 20 20 20 20 20  ions)).         
1f30: 20 20 20 20 20 20 20 64 55 73 65 72 5b 73 55 73         dUser[sUs
1f40: 65 72 49 64 5d 20 3d 20 7b 20 22 74 69 6d 65 22  erId] = { "time"
1f50: 3a 20 69 6e 74 28 74 69 6d 65 2e 74 69 6d 65 28  : int(time.time(
1f60: 29 29 2c 20 22 67 63 5f 6f 70 74 69 6f 6e 73 22  )), "gc_options"
1f70: 3a 20 64 4f 70 74 69 6f 6e 73 20 7d 0a 20 20 20  : dOptions }.   
1f80: 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65 73               res
1f90: 70 6f 6e 73 65 2e 73 65 74 5f 63 6f 6f 6b 69 65  ponse.set_cookie
1fa0: 28 22 75 73 65 72 5f 69 64 22 2c 20 73 55 73 65  ("user_id", sUse
1fb0: 72 49 64 2c 20 70 61 74 68 3d 22 2f 22 2c 20 6d  rId, path="/", m
1fc0: 61 78 5f 61 67 65 3d 38 36 34 30 30 29 20 23 20  ax_age=86400) # 
1fd0: 32 34 68 0a 20 20 20 20 20 20 20 20 20 20 20 20  24h.            
1fe0: 20 20 20 20 72 65 74 75 72 6e 20 6a 73 6f 6e 2e      return json.
1ff0: 64 75 6d 70 73 28 64 55 73 65 72 5b 73 55 73 65  dumps(dUser[sUse
2000: 72 49 64 5d 5b 22 67 63 5f 6f 70 74 69 6f 6e 73  rId]["gc_options
2010: 22 5d 29 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]).            
2020: 65 78 63 65 70 74 3a 0a 20 20 20 20 20 20 20 20  except:.        
2030: 20 20 20 20 20 20 20 20 74 72 61 63 65 62 61 63          tracebac
2040: 6b 2e 70 72 69 6e 74 5f 65 78 63 28 29 0a 20 20  k.print_exc().  
2050: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 72 65                re
2060: 74 75 72 6e 20 27 7b 22 65 72 72 6f 72 22 3a 20  turn '{"error": 
2070: 22 6f 70 74 69 6f 6e 73 20 6e 6f 74 20 72 65 67  "options not reg
2080: 69 73 74 65 72 65 64 22 7d 27 0a 20 20 20 20 20  istered"}'.     
2090: 20 20 20 72 65 74 75 72 6e 20 27 7b 22 65 72 72     return '{"err
20a0: 6f 72 22 3a 20 22 6e 6f 20 6f 70 74 69 6f 6e 73  or": "no options
20b0: 20 72 65 63 65 69 76 65 64 22 7d 27 0a 0a 20 20   received"}'..  
20c0: 20 20 40 61 70 70 2e 72 6f 75 74 65 28 22 2f 72    @app.route("/r
20d0: 65 73 65 74 5f 6f 70 74 69 6f 6e 73 2f 66 72 22  eset_options/fr"
20e0: 2c 20 6d 65 74 68 6f 64 3d 22 50 4f 53 54 22 29  , method="POST")
20f0: 0a 20 20 20 20 64 65 66 20 72 65 73 65 74 4f 70  .    def resetOp
2100: 74 69 6f 6e 73 20 28 29 3a 0a 20 20 20 20 20 20  tions ():.      
2110: 20 20 69 66 20 72 65 71 75 65 73 74 2e 63 6f 6f    if request.coo
2120: 6b 69 65 73 2e 75 73 65 72 5f 69 64 20 61 6e 64  kies.user_id and
2130: 20 72 65 71 75 65 73 74 2e 63 6f 6f 6b 69 65 73   request.cookies
2140: 2e 75 73 65 72 5f 69 64 20 69 6e 20 64 55 73 65  .user_id in dUse
2150: 72 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20 64  r:.            d
2160: 65 6c 20 64 55 73 65 72 5b 72 65 71 75 65 73 74  el dUser[request
2170: 2e 63 6f 6f 6b 69 65 73 2e 75 73 65 72 5f 69 64  .cookies.user_id
2180: 5d 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e  ].        return
2190: 20 22 64 6f 6e 65 22 0a 0a 20 20 20 20 40 61 70   "done"..    @ap
21a0: 70 2e 72 6f 75 74 65 28 22 2f 66 6f 72 6d 61 74  p.route("/format
21b0: 5f 74 65 78 74 2f 66 72 22 2c 20 6d 65 74 68 6f  _text/fr", metho
21c0: 64 3d 22 50 4f 53 54 22 29 0a 20 20 20 20 64 65  d="POST").    de
21d0: 66 20 66 6f 72 6d 61 74 54 65 78 74 20 28 29 3a  f formatText ():
21e0: 0a 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20  .        return 
21f0: 6f 54 65 78 74 46 6f 72 6d 61 74 74 65 72 2e 66  oTextFormatter.f
2200: 6f 72 6d 61 74 54 65 78 74 28 72 65 71 75 65 73  ormatText(reques
2210: 74 2e 66 6f 72 6d 73 2e 74 65 78 74 29 0a 0a 20  t.forms.text).. 
2220: 20 20 20 23 40 61 70 70 2e 72 6f 75 74 65 28 27     #@app.route('
2230: 2f 73 74 61 74 69 63 2f 3c 66 69 6c 65 70 61 74  /static/<filepat
2240: 68 3a 70 61 74 68 3e 27 29 0a 20 20 20 20 23 64  h:path>').    #d
2250: 65 66 20 73 65 72 76 65 72 5f 73 74 61 74 69 63  ef server_static
2260: 20 28 66 69 6c 65 70 61 74 68 29 3a 0a 20 20 20   (filepath):.   
2270: 20 23 20 20 20 20 72 65 74 75 72 6e 20 73 74 61   #    return sta
2280: 74 69 63 5f 66 69 6c 65 28 66 69 6c 65 70 61 74  tic_file(filepat
2290: 68 2c 20 72 6f 6f 74 3d 27 2e 2f 76 69 65 77 73  h, root='./views
22a0: 2f 73 74 61 74 69 63 27 29 0a 0a 20 20 20 20 40  /static')..    @
22b0: 61 70 70 2e 72 6f 75 74 65 28 22 2f 70 75 72 67  app.route("/purg
22c0: 65 5f 75 73 65 72 73 22 2c 20 6d 65 74 68 6f 64  e_users", method
22d0: 3d 22 50 4f 53 54 22 29 0a 20 20 20 20 64 65 66  ="POST").    def
22e0: 20 70 75 72 67 65 55 73 65 72 73 20 28 29 3a 0a   purgeUsers ():.
22f0: 20 20 20 20 20 20 20 20 22 64 65 6c 65 74 65 20          "delete 
2300: 75 73 65 72 20 6f 70 74 69 6f 6e 73 20 6f 6c 64  user options old
2310: 65 72 20 74 68 61 6e 20 6e 20 68 6f 75 72 73 22  er than n hours"
2320: 0a 20 20 20 20 20 20 20 20 69 66 20 6e 6f 74 20  .        if not 
2330: 72 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e 70 61  request.forms.pa
2340: 73 73 77 6f 72 64 20 6f 72 20 22 70 61 73 73 77  ssword or "passw
2350: 6f 72 64 22 20 6e 6f 74 20 69 6e 20 64 53 65 72  ord" not in dSer
2360: 76 65 72 4f 70 74 69 6f 6e 73 20 6f 72 20 6e 6f  verOptions or no
2370: 74 20 72 65 71 75 65 73 74 2e 66 6f 72 6d 73 2e  t request.forms.
2380: 68 6f 75 72 73 3a 0a 20 20 20 20 20 20 20 20 20  hours:.         
2390: 20 20 20 72 65 74 75 72 6e 20 22 77 68 61 74 3f     return "what?
23a0: 22 0a 20 20 20 20 20 20 20 20 74 72 79 3a 0a 20  ".        try:. 
23b0: 20 20 20 20 20 20 20 20 20 20 20 69 66 20 72 65             if re
23c0: 71 75 65 73 74 2e 66 6f 72 6d 73 2e 70 61 73 73  quest.forms.pass
23d0: 77 6f 72 64 20 3d 3d 20 64 53 65 72 76 65 72 4f  word == dServerO
23e0: 70 74 69 6f 6e 73 5b 22 70 61 73 73 77 6f 72 64  ptions["password
23f0: 22 5d 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  "]:.            
2400: 20 20 20 20 6e 4e 6f 77 4d 69 6e 75 73 4e 48 6f      nNowMinusNHo
2410: 75 72 73 20 3d 20 69 6e 74 28 74 69 6d 65 2e 74  urs = int(time.t
2420: 69 6d 65 28 29 29 20 2d 20 28 69 6e 74 28 72 65  ime()) - (int(re
2430: 71 75 65 73 74 2e 66 6f 72 6d 73 2e 68 6f 75 72  quest.forms.hour
2440: 73 29 20 2a 20 36 30 20 2a 20 36 30 29 0a 20 20  s) * 60 * 60).  
2450: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 66 6f                fo
2460: 72 20 6e 55 73 65 72 49 64 2c 20 64 56 61 6c 75  r nUserId, dValu
2470: 65 20 69 6e 20 64 55 73 65 72 2e 69 74 65 6d 73  e in dUser.items
2480: 28 29 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  ():.            
2490: 20 20 20 20 20 20 20 20 69 66 20 64 56 61 6c 75          if dValu
24a0: 65 5b 22 74 69 6d 65 22 5d 20 3c 20 6e 4e 6f 77  e["time"] < nNow
24b0: 4d 69 6e 75 73 4e 48 6f 75 72 73 3a 0a 20 20 20  MinusNHours:.   
24c0: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
24d0: 20 20 20 20 20 64 65 6c 20 64 55 73 65 72 5b 6e       del dUser[n
24e0: 55 73 65 72 49 64 5d 0a 20 20 20 20 20 20 20 20  UserId].        
24f0: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 22          return "
2500: 64 6f 6e 65 22 0a 20 20 20 20 20 20 20 20 20 20  done".          
2510: 20 20 65 6c 73 65 3a 0a 20 20 20 20 20 20 20 20    else:.        
2520: 20 20 20 20 20 20 20 20 72 65 74 75 72 6e 20 22          return "
2530: 6e 6f 22 0a 20 20 20 20 20 20 20 20 65 78 63 65  no".        exce
2540: 70 74 3a 0a 20 20 20 20 20 20 20 20 20 20 20 20  pt:.            
2550: 74 72 61 63 65 62 61 63 6b 2e 70 72 69 6e 74 5f  traceback.print_
2560: 65 78 63 28 29 0a 20 20 20 20 20 20 20 20 20 20  exc().          
2570: 20 20 72 65 74 75 72 6e 20 22 65 72 72 6f 72 22    return "error"
2580: 0a 0a 20 20 20 20 23 20 45 52 52 4f 52 0a 20 20  ..    # ERROR.  
2590: 20 20 40 61 70 70 2e 65 72 72 6f 72 28 34 30 34    @app.error(404
25a0: 29 0a 20 20 20 20 64 65 66 20 65 72 72 6f 72 34  ).    def error4
25b0: 30 34 20 28 65 72 72 6f 72 29 3a 0a 20 20 20 20  04 (error):.    
25c0: 20 20 20 20 72 65 74 75 72 6e 20 27 45 72 72 6f      return 'Erro
25d0: 72 20 34 30 34 2e 3c 62 72 2f 3e 27 20 2b 20 73  r 404.<br/>' + s
25e0: 74 72 28 65 72 72 6f 72 29 0a 0a 20 20 20 20 72  tr(error)..    r
25f0: 75 6e 28 61 70 70 2c 20 5c 0a 20 20 20 20 20 20  un(app, \.      
2600: 20 20 68 6f 73 74 3d 64 53 65 72 76 65 72 4f 70    host=dServerOp
2610: 74 69 6f 6e 73 2e 67 65 74 28 27 68 6f 73 74 27  tions.get('host'
2620: 2c 20 27 6c 6f 63 61 6c 68 6f 73 74 27 29 2c 20  , 'localhost'), 
2630: 5c 0a 20 20 20 20 20 20 20 20 70 6f 72 74 3d 69  \.        port=i
2640: 6e 74 28 64 53 65 72 76 65 72 4f 70 74 69 6f 6e  nt(dServerOption
2650: 73 2e 67 65 74 28 27 70 6f 72 74 27 2c 20 38 30  s.get('port', 80
2660: 38 30 29 29 29 0a                                80))).