Subversion Repositories wimsdev

Rev

Rev 8155 | Rev 8185 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
10 reyssat 1
/*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
2
 *
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
7563 bpr 17
/* Routines to write log files. */
10 reyssat 18
 
19
char logbuf[4*(MAX_LINELEN+1)];
20
char *logp=logbuf;
21
 
22
void write_logfile(char *fname, char *str)
23
{
24
    char *p;
25
    if((p=strchr(str,'\n'))!=NULL) *p=0;
26
    snprintf(logp,sizeof(logbuf)-(logp-logbuf),"%s %s\n",fname,str);
27
    logp+=strlen(logp);
28
}
29
 
30
void flushlog(void)
31
{
32
    int n, fd;
33
    n=logp-logbuf; logp=logbuf;
34
    if(n<=0) return;
35
    fd=open(temp_log,O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR);
36
    if(fd==-1) return;
3843 kbelabas 37
    (void)write(fd,logbuf,n); close(fd);
10 reyssat 38
}
39
 
7563 bpr 40
/* Write module log file. */
10 reyssat 41
void module_log(void)
42
{
7563 bpr 43
    /* log string is limited to 100 characters. */
10 reyssat 44
    char *logstr, *ip, *sess, lbuf[100], *p;
7563 bpr 45
 
10 reyssat 46
    if(robot_access || !modlog || strstr(session_prefix,"_check")!=NULL) return;
47
    logstr=getvar("wims_module_log");
48
    if(logstr==NULL || *logstr==0) return;
7563 bpr 49
    ip=remote_addr;
10 reyssat 50
    if(mode==mode_default) sess=getvar("wims_session");
51
    else sess="popup";
52
    if(ip==NULL || sess==NULL) return;
53
    mystrncpy(lbuf,logstr,sizeof(lbuf));
54
    p=strchr(sess,'_'); if(p==NULL) p=sess+strlen(sess);
55
    if(p<sess+4) p=sess; else p=p-4;
56
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s",
7563 bpr 57
     nowstr, p, ip, lbuf);
10 reyssat 58
    p=getvar(ro_name[ro_module]);
59
    if(p==NULL || *p==0) return;
60
    write_logfile(mkfname(NULL,"%s/%s",module_dir,p),tmplbuf);
61
}
62
 
7563 bpr 63
/* log http referers */
10 reyssat 64
void referer_log(void)
65
{
66
    char *c,*s,*ip,*r,*h,refstr[256];
67
 
68
    if(robot_access) return;
69
    c=getvar(ro_name[ro_cmd]);
70
    if(c==NULL) c="";
71
    if(mode==mode_default) s=getvar("wims_session"); else s="popup";
72
    if(s==NULL) s="----";
73
    else if(!new_session && strcmp(c,"intro")!=0) return;
74
    if(strlen(s)<4) s="----";
75
    if(strchr(s,'_')!=NULL) return;
76
    ip=remote_addr; if(*ip==0) return;
77
    r=getenv("HTTP_REFERER");
78
    if(r==NULL || *r==0) r="??";
7563 bpr 79
    /* skip some useless referers */
10 reyssat 80
    else {
7563 bpr 81
      if(strstr(r,cgi_name)!=NULL) return;
82
      if(strstr(r,"file:")!=NULL || strchr(r,'.')==NULL) r="??";
83
      if(strstr(r,"http")==NULL && strchr(r,'.')==NULL &&
84
       strstr(r,"bookmark")!=NULL) r="??bookmark";
10 reyssat 85
    }
86
    if(strncmp(r,"http://",strlen("http://"))==0) r+=strlen("http://");
7563 bpr 87
    /* Take references from the same site or not? No. */
10 reyssat 88
    h=getenv("HTTP_HOST");
89
    if(h!=NULL && *h!=0 && strncmp(r,h,strlen(h))==0) return;
7563 bpr 90
        /* stop before '#' */
10 reyssat 91
    mystrncpy(refstr,r,sizeof(refstr));
92
    r=strchr(refstr,'#'); if(r!=NULL) *r=0;
93
    for(r=refstr;r<refstr+strlen(refstr);r++) {
7563 bpr 94
      if(*r=='%' && *(r+1)=='7' && *(r+2)=='E') {
7843 bpr 95
        *r='~'; ovlstrcpy(r+1,r+3);
7563 bpr 96
      }
10 reyssat 97
    }
98
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %s %s\11%s",
7563 bpr 99
         nowstr,s+strlen(s)-4,ip,refstr);
10 reyssat 100
    write_logfile("referer.log",tmplbuf);
101
}
102
 
7563 bpr 103
/* Log new creation of sessions. For server counting use. */
10 reyssat 104
void session_log(char *c)
105
{
106
    int i;
107
    char *ip, *p, *agent, *s, *sess;
7563 bpr 108
 
10 reyssat 109
    ip=remote_addr; if(*ip==0) return;
110
    if(mode==mode_default) {
7563 bpr 111
      sess=getvar("wims_session");
112
      if(sess==NULL) return;
113
      if(strchr(sess,'_')!=NULL) return;
10 reyssat 114
    }
115
    else sess="popup";
116
    p=getenv("REMOTE_HOST"); if(p==NULL) p="";
117
    i=strlen(p); if(i>40) p+=i-40;
118
    agent=getenv("HTTP_USER_AGENT"); if(agent==NULL) agent="";
119
    s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
120
    if(s<sess+4) s=sess; else s=s-4;
6192 bpr 121
      /* limit agent name to 80 chars */
122
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %s %s\11%s\11%.80s",
7563 bpr 123
         nowstr, s, ip, p, agent);
10 reyssat 124
    write_logfile("session.log",tmplbuf);
125
}
126
 
7563 bpr 127
/* Log user information. */
10 reyssat 128
void user_log(char *c)
129
{
130
    char fname[MAX_FNAME+1], logbuf[MAX_LINELEN+1], cbuf[256], sbuf[32], shbuf[32];
131
    char *user, *classe, *sh, *sess, *exo, *cc, *ip, *allow, *pend;
132
    char *ex;
133
    double sc,Sc;
134
    int i, scorelog;
7563 bpr 135
 
10 reyssat 136
    if(robot_access || strstr("session_prefix","_check")!=NULL) return;
137
    user=getvar("wims_user"); classe=getvar("wims_class");
138
    sc=0;
139
    if(isexam) {
7563 bpr 140
      if(user==NULL || classe==NULL || *user==0 || *classe==0) return;
141
      sh=getvar("worksheet"); if(sh==NULL) return;
142
      mystrncpy(shbuf,sh,sizeof(shbuf));
143
      exo=strchr(shbuf,'.'); if(exo==NULL) return;
144
      *exo++=0; sh=shbuf;
145
      if(mode==mode_default) sess=getvar("wims_session");
146
      else sess="popup";
147
      if(sess==NULL) return;
148
      mystrncpy(sbuf,sess,sizeof(sbuf));
149
      sess=strchr(sbuf,'_'); if(sess==NULL) return;
150
      *sess=0; sess=sbuf; ex="E";
151
      accessfile(logbuf,"r","%s/.E%s",class_dir,sh);
152
      if(strchr(logbuf,'#')!=NULL || strcmp(user,"supervisor")==0) simuxam=1;
153
      else {
154
        accessfile(logbuf,"r","%s/%s/examsimu.%d", session_dir,sess,sh);
155
        if(strstr(logbuf,"yes")!=NULL) user_error("expired_exam");
156
      }
157
      mkfname(examlogd,"%s/examlog/%s/%s",class_dir,user,sess);
158
      mkfname(examlogf,"%s/%s.%s",examlogd,sh,exo);
10 reyssat 159
    }
160
    else {
7563 bpr 161
     sh=getvar("wims_sheet");
162
     if(sh==NULL || *sh==0) return;
163
     exo=getvar("wims_exo"); if(exo==NULL) return;
164
     sess=getvar("wims_session");
165
     if(sess==NULL) return;
166
     ex="";
167
 
10 reyssat 168
    }
169
    if(strcmp(c,"new")!=0 && strcmp(c,"renew")!=0
170
       && strcmp(c,"rafale")!=0
171
       && strcmp(c,"hint")!=0 && parm_restore==0) {
7563 bpr 172
       char *s;
173
       s=getvar("module_score");
174
       if(s==NULL || *s==0) return;
8171 bpr 175
       sc=atof(s); if(!isfinite(sc)) {sc=0; return;}
7563 bpr 176
       snprintf(cbuf,sizeof(cbuf),"score %s",s);
177
       cc=cbuf;
10 reyssat 178
    }
179
    else cc=c;
180
    if(classe==NULL || *classe==0) i=1;
181
    else i=getscorestatus(classe,atoi(sh));
182
    pend=getvar("wims_scoring"); if(pend==NULL) pend="";
183
    if((i==0 || !exodepOK || strcmp(pend,"pending")!=0) && strcmp(cc,"rafale")!=0)
184
      allow="   noscore";
185
    else allow="";
186
    ip=remote_addr; if(*ip==0) ip="-"; scorelog=0;
187
    if(user==NULL || *user==0) {
7563 bpr 188
       classe="0"; allow="";
189
       mkfname(fname,"../sessions/%s/.score",sess);
10 reyssat 190
    }
191
    else {
7563 bpr 192
     char *pp;
193
     if(classe==NULL || *classe==0) return;
194
     pp=getvar("wims_scorereg");
195
     if((allow[0]==0 || (pp!=NULL && strcmp(pp,"suspend")==0)) && *ex!='E')
196
       scorelog=1;
197
     else
198
       mkfname(fname,"classes/%s/noscore/%s",classe,user);
10 reyssat 199
    }
200
    if(isexam && user!=NULL && *user!=0) {
7563 bpr 201
     allow=exam_sheetexo;
202
     snprintf(logbuf,sizeof(logbuf),":%s %2s %s         %s%s\n",
203
        nowstr,exo,cc,ip,allow);
204
     accessfile(logbuf,"a","%s/%s/examscore.%s", session_dir,sess,sh);
205
     Sc=currexamscore(atoi(sh));
206
     accessfile(logbuf,"r","%s/.E%s",class_dir,sh);
207
     if(simuxam==0) {     /* not simulation */
208
         if(sc>0) {
209
          snprintf(logbuf,sizeof(logbuf),
210
                "%s %.5f -1 %u %s %s\n",
211
                sh,Sc,(unsigned int) nowtime,ip,sess);
212
          accessfile(logbuf,"a","%s/score/%s.exam",
213
                  class_dir,user);
214
         }
215
     }
216
     else snprintf(exam_sheetexo+strlen(exam_sheetexo),
217
                sizeof(exam_sheetexo)-strlen(exam_sheetexo),
218
                "       S");
10 reyssat 219
    }
220
    snprintf(logbuf,sizeof(logbuf),"%s%s %s %2s %2s %s          %s%s",
7563 bpr 221
          ex,nowstr,sess,sh,exo,cc,ip,allow);
10 reyssat 222
    if(scorelog) {
7563 bpr 223
      snprintf(tmplbuf,sizeof(tmplbuf),"-c%s -u%s scorelog %s",
224
           classe,user,logbuf);
225
     _daemoncmd(tmplbuf);
10 reyssat 226
    }
227
    else write_logfile(fname,logbuf);
228
}
229
 
7563 bpr 230
/* Log class information. */
10 reyssat 231
void class_log(char *cl, char *l, char *ip)
232
{
233
    char logbuf[1024];
7563 bpr 234
 
10 reyssat 235
    if(robot_access) return;
236
    snprintf(logbuf,sizeof(logbuf),"%s %s       %s",
7563 bpr 237
          nowstr,ip,l);
10 reyssat 238
    write_logfile(mkfname(NULL,"classes/%s/.log",cl),logbuf);
239
}
240
 
7563 bpr 241
/* Log accesses to modules. For server counting use. */
10 reyssat 242
void access_log(char *c)
243
{
244
    int i;
245
    char *ip, *p, *sess, *s, *agent, *u, *cl;
246
    time_t logtime;
247
    char ag[128], tm[64];
7563 bpr 248
 
249
    ip=remote_addr;
10 reyssat 250
    if(*ip==0) ip="????????";
251
    if(mode==mode_default) sess=getvar("wims_session");
252
    else sess="popup";
253
    if(sess==NULL) sess="----------";
254
    p=getvar(ro_name[ro_module]);
255
    if(p==NULL || *p==0) p="-";
8155 bpr 256
/* limit module name to 40 chars */
10 reyssat 257
    i=strlen(p); if(i>40) p+=i-40;
258
    if(robot_access) {
7563 bpr 259
     agent=getenv("HTTP_USER_AGENT"); if(agent==NULL) agent="-";
260
     snprintf(ag,sizeof(ag)," %s",agent);
10 reyssat 261
    }
262
    else {
7563 bpr 263
     u=getvar("wims_user");
264
     if(u!=NULL && *u!=0) snprintf(ag,sizeof(ag)," %s,%s",u,getvar("wims_class"));
265
     else ag[0]=0;
10 reyssat 266
    }
267
    s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
268
    if(s<sess+4) s=sess; else s=s-4;
269
    tm[0]=0; logtime=time(0); if(logtime>nowtime+2) {
7563 bpr 270
     snprintf(tm,sizeof(tm)," (%lus)", logtime-nowtime);
10 reyssat 271
    }
272
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s\11%s%s%s",
7563 bpr 273
          nowstr, s, ip, c, p, tm, ag);
10 reyssat 274
    write_logfile("access.log",tmplbuf);
275
    user_log(c);
276
    cl=getvar("wims_class");
277
    if(cl!=NULL && *cl!=0) {
7563 bpr 278
     char *l;
279
     l=getvar("wims_class_log");
280
     if(l!=NULL && *l!=0) class_log(cl, l, ip);
10 reyssat 281
    }
282
}
283
 
7563 bpr 284
/* Log of mails. */
10 reyssat 285
void mail_log(char *c)
286
{
287
    int i;
288
    char *ip, *p, *sess, *s, *cl;
7563 bpr 289
 
290
    ip=remote_addr;
10 reyssat 291
    if(*ip==0) ip="????????";
292
    if(mode==mode_default) sess=getvar("wims_session");
293
    else sess="popup";
294
    if(sess==NULL) sess="----------";
295
    p=getvar(ro_name[ro_module]);
296
    if(p==NULL || *p==0) p="-";
8155 bpr 297
/* limit module name to 40 chars */
10 reyssat 298
    i=strlen(p); if(i>40) p+=i-40;
299
    s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
300
    if(s<sess+4) s=sess; else s=s-4;
301
    cl=getvar("wims_class"); if(cl==NULL) cl="";
302
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %.6s %s\11%s\11%s\11%s",
7563 bpr 303
          nowstr, s, ip, c, cl, p);
10 reyssat 304
    write_logfile("mail.log",tmplbuf);
305
}
306
 
7563 bpr 307
/* log posted data */
10 reyssat 308
void post_log(void)
309
{
310
    char *h, *l, logstr[2*MAX_LINELEN+2];
4347 reyssat 311
    char *authpwd, *p, *ll, *l1 ;
10 reyssat 312
 
313
    h=remote_addr;
314
    if(mpboundary[0]!=0) l="multipart/form-data"; else l=stdinbuf;
4347 reyssat 315
 
316
    ll=strdup(l);
317
    authpwd="auth_password=";
318
    if((p=strstr(l,authpwd))!=NULL ) {
319
      l1=strdup(l);
320
      mystrncpy(ll,l,p-l+strlen(authpwd)+1);
321
      strcat(ll,"xxxx");
7563 bpr 322
      mystrncpy(l1,p+strlen(authpwd),strlen(l));
4347 reyssat 323
      if((p=strstr(l1,"&"))!=NULL) strcat(ll,p);
324
    }
325
 
10 reyssat 326
    snprintf(logstr,sizeof(logstr),"%s %s       %s",
7563 bpr 327
         nowstr, h, ll);
10 reyssat 328
    write_logfile("post.log",logstr);
329
}
330
 
7563 bpr 331
/* It is this routine which is called by main(). */
10 reyssat 332
void write_logs(void)
333
{
334
    char *p;
335
    p=getvar(ro_name[ro_cmd]); if(p==NULL || *p==0) p="no_cmd";
336
    access_log(p); if(strstr(session_prefix,"_check")!=NULL) return;
337
    module_log(); referer_log();
338
    if(new_session) session_log(p);
339
}
340
 
341
void user_error_log(char msg[])
342
{
343
    char *s, *m, *c, *h, *q, *r, *sess, logstr[512];
344
    if(mode==mode_default) sess=getvar("wims_session");
345
    else sess="popup";
346
    if(sess==NULL) sess="----------";
347
    m=getvar(ro_name[ro_module]);if(m==NULL) m="";
348
    c=getvar(ro_name[ro_cmd]);if(c==NULL) c="";
349
    h=remote_addr;
350
    q=getenv("QUERY_STRING");if(q==NULL) q="";
351
    r=getenv("HTTP_REFERER");
352
    if(r==NULL || strstr(r,cgi_name)!=NULL) r="";
353
    s=strchr(sess,'_'); if(s==NULL) s=sess+strlen(sess);
354
    if(s<sess+4) s=sess; else s=s-4;
355
    snprintf(logstr,sizeof(logstr),"%s %.5s %s %s, module=%s cmd=%s: %s %s",
7563 bpr 356
         nowstr, s, h, msg, m, c, r, q);
10 reyssat 357
    write_logfile("user_error.log",logstr);
358
    if(user_error_nolog) return;
359
    access_log("user_error");referer_log();
360
}
361
 
362
void module_error_log(char msg[])
363
{
364
    char *s, *m, *c, logstr[256];
365
    if(strstr(msg,"debug")!=NULL || strstr(msg,"timeup")!=NULL) return;
366
    if(strstr(m_file.name,"sessions/")!=NULL) return;
367
    s=getvar(ro_name[ro_module]);
368
    if(s!=NULL) {
7563 bpr 369
     if(strncmp(s,"classes/",strlen("classes/"))==0 ||
370
        strncmp(s,"devel/",strlen("devel/"))==0) return;
10 reyssat 371
    }
372
    s=getvar("wims_session"); if(s==NULL) s="    ";
373
    m=getvar(ro_name[ro_module]);if(m==NULL) m="";
374
    c=getvar(ro_name[ro_cmd]);if(c==NULL) c="";
375
    snprintf(logstr,sizeof(logstr),"%s %.10s %s in %s/%s, line %d",
7563 bpr 376
         nowstr, s+2, msg, m, m_file.name, m_file.l+1);
10 reyssat 377
    write_logfile("module_error.log",logstr);
378
    access_log("module_error");
379
}
380
 
7563 bpr 381
/* Refused users due to threshold excess */
10 reyssat 382
void refuse_log(int th)
383
{
384
    char *load, *h;
7563 bpr 385
 
10 reyssat 386
    load=getvar("wims_server_load"); if(load==NULL) load="??";
387
    h=remote_addr;
388
    snprintf(tmplbuf,sizeof(tmplbuf),"%s %s\11%d:%s",
7563 bpr 389
          nowstr, h, th, load);
10 reyssat 390
    write_logfile("refuse.log",tmplbuf);
391
}
392
 
393
#define logdpid "../tmp/log/wimslogd.pid"
394
#define newlogd "../tmp/log/wimslogd.new"
395
 
396
void bringuplogd(void)
397
{
398
    char *arg[]={"../bin/wimslogd",NULL};
399
    struct stat st;
400
    pid_t pid;
401
 
8155 bpr 402
/* need to update wimslogd? */
10 reyssat 403
    if(stat(newlogd,&st)==0) {
7563 bpr 404
     if((S_IXUSR&st.st_mode)!=0 && st.st_size>40000 && st.st_size<200000)
405
       call_ssh("mv %s %s",newlogd,arg[0]);
406
     else call_ssh("rm -f %s",newlogd);
10 reyssat 407
    }
7563 bpr 408
    pid=fork(); if(pid) return;     /* parent */
8155 bpr 409
/* double fork to escape sysmask orphan. */
7563 bpr 410
    pid=fork(); if(pid) {     /* secondary parent */
411
     snprintf(tmplbuf,sizeof(tmplbuf),"%u",pid);
412
     mkdirs("../tmp/log");
413
     chmod("../tmp/log",S_IRUSR|S_IWUSR|S_IXUSR);
414
     accessfile(tmplbuf,"w",logdpid);
415
     exit(0);
10 reyssat 416
    }
417
    setreuid(geteuid(),geteuid());setregid(getegid(),getegid());
418
    snprintf(tmplbuf,sizeof(tmplbuf),"%u %u %u %u %u %u %d %d %d",
7563 bpr 419
          idle_time,idle_time2,idle_time3,
420
          OLD_LOG_FILES,GEN_LOG_LIMIT,
421
          MODULE_LOG_LIMIT,backup_hour,site_accounting,
422
          examlog_limit);
423
 
10 reyssat 424
    setenv("wimslogd",tmplbuf,1);
425
    execve(arg[0],arg,environ);
426
    fprintf(stderr,"Unable to execute wimslogd: %s\n",strerror(errno));
427
    exit(1);
428
}
429
 
430
void checklogd(void)
431
{
432
    int i,t;
433
    char *p1, *p2, *p, buf[MAX_LINELEN+1];
434
    sun.sun_family=PF_UNIX;
435
    snprintf(sun.sun_path,sizeof(sun.sun_path),"%s",ksockfile);
436
    p=getenv("REMOTE_ADDR"); if(p==NULL) p="";
437
    snprintf(buf+sizeof(int),sizeof(buf)-sizeof(int),"ping %s",p);
438
    t=kerneld(buf,sizeof(buf)); if(t<0) {
7563 bpr 439
     bringuplogd();
440
     for(i=0; i<10 && t<0; i++) {
441
         msleep(100);
442
         snprintf(buf+sizeof(int),sizeof(buf)-sizeof(int),"ping %s",p);
443
         t=kerneld(buf,sizeof(buf));
444
     }
10 reyssat 445
    }
446
    if(t<0) internal_error("Unable to bring up wimslogd.");
447
    p1=find_word_start(buf+sizeof(int)); p2=find_word_end(p1);
448
    if(*p2) *p2++=0;
449
    if(strcmp(p1,"OK")!=0) internal_error("wimslogd error.");
450
    if(*p2=='1') hostcquota=1; else hostcquota=0;
451
    p1=find_word_start(find_word_end(p2));
452
    p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1);
453
    mystrncpy(loadavg,p1,sizeof(loadavg));
454
    p2=find_word_start(p2);
455
    p1=find_word_end(p2); if(*p1) *p1++=0;
7563 bpr 456
 
10 reyssat 457
    p=getenv("SERVER_ADDR");
458
    if(*p2!=0 && memcmp(p,"10.",3)==0) p=p2;
459
    if(p!=NULL) {
7563 bpr 460
     i=strlen(cookieheader);
461
     snprintf(cookieheader+i, sizeof(cookieheader)-i,"%s/",p);
10 reyssat 462
    }
463
    p=getenv("HTTP_COOKIE"); cookiegot[0]=0;
464
    if(p!=NULL && (p2=strstr(p,cookieheader))!=NULL) {
7563 bpr 465
     mystrncpy(cookiegot,find_word_start(p+strlen(cookieheader)),sizeof(cookiegot));
466
     *find_word_end(cookiegot)=0;
10 reyssat 467
    }
468
}