1 /* condparser.cc
2 * This file belongs to Worker, a file manager for UN*X/X11.
3 * Copyright (C) 2004-2014 Ralf Hoffmann.
4 * You can contact me at: ralf@boomerangsworld.de
5 * or http://www.boomerangsworld.de/worker
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "condparser.h"
23 #include "aguix/lowlevelfunc.h"
24 #include "aguix/awindow.h"
25 #include "aguix/acontainer.h"
26 #include "aguix/fieldlistview.h"
27 #include "aguix/button.h"
28 #include "execlass.h"
29 #include "fileentry.hh"
30 #include "worker.h"
31 #include "datei.h"
32 #include "worker_locale.h"
33 #include "nwc_path.hh"
34
35 struct CondParser::deftokens CondParser::keywords[] = {
36 { "lasterror", CondParser::TOK_LASTERROR },
37 { "true", CondParser::TOK_TRUE },
38 { "false", CondParser::TOK_FALSE },
39 { "toNum", CondParser::TOK_TONUM },
40 { "toStr", CondParser::TOK_TOSTR },
41 { "isReg", CondParser::TOK_ISREG },
42 { "isSock", CondParser::TOK_ISSOCK },
43 { "isFIFO", CondParser::TOK_ISFIFO },
44 { "isSymlink", CondParser::TOK_ISSYMLINK },
45 { "isBrokenSymlink", CondParser::TOK_ISBROKENSYMLINK },
46 { "size", CondParser::TOK_SIZE },
47 { "perm", CondParser::TOK_PERM },
48 { "toLower", CondParser::TOK_TOLOWER },
49 { "toUpper", CondParser::TOK_TOUPPER },
50 { "contentStr", CondParser::TOK_CONTENTSTR },
51 { "contentNum", CondParser::TOK_CONTENTNUM },
52 { "name", CondParser::TOK_NAME },
53 { "fullname", CondParser::TOK_FULLNAME },
54 { "isLocal", CondParser::TOK_ISLOCAL }
55 };
56
57 struct CondParser::flaghelp CondParser::flags[] = {
58 { "true", -1, 44 },
59 { "false", -1, 45 },
60 { "toNum(...)", -1, 51 },
61 { "toStr(...)", -1, 52 },
62 { "isReg()", 579, -1 },
63 { "isSock()", 580, -1 },
64 { "isFIFO()", 581, -1 },
65 { "isSymlink()", 582, -1 },
66 { "isBrokenSymlink()", 1036, -1 },
67 { "isLocal()", 626, -1 },
68 { "size()", 583, -1 },
69 { "perm(mask)", 584, -1 },
70 { "toLower(...)", 585, -1 },
71 { "toUpper(...)", 586, -1 },
72 { "contentStr(<Start>[,<Length>])", 587, -1 },
73 { "contentNum(<Start>[,<Length>])", 588, -1 },
74 { "name()", 589, -1 },
75 { "fullname()", 590, -1 },
76 { "${...}", -1, 48 },
77 { "?{...}", -1, 47 },
78 { "{f}", 591, -1 },
79 { "{F}", 592, -1 },
80 { "lasterror", -1, 42 }
81 };
82
CondParser()83 CondParser::CondParser()
84 {
85 curpos = 0;
86 tokenval = -1;
87 ignore = 0;
88 scanbuf = NULL;
89 scanbuflen = -1;
90 lasterror = 0;
91 fe = NULL;
92 ignoreContent = false;
93 }
94
~CondParser()95 CondParser::~CondParser()
96 {
97 }
98
lookup(const char * s)99 int CondParser::lookup( const char *s )
100 {
101 unsigned int p;
102
103 for ( p = 0; p < ( sizeof(keywords) / sizeof( keywords[0] ) ); p++ )
104 if ( strcasecmp( keywords[p].str, s ) == 0 )
105 return keywords[p].token;
106 return TOK_NONE;
107 }
108
lex()109 int CondParser::lex()
110 {
111 int t;
112 int base = 10;
113
114 while ( 1 ) {
115 if ( curpos >= scanbuflen ) break;
116 t = scanbuf[curpos++];
117 if ( isspace( t ) ) {
118 } else if ( isdigit( t ) ) {
119 tokenval = t - '0';
120 if ( tokenval == 0 ) {
121 base = 8;
122 } else {
123 base = 10;
124 }
125 while ( isdigit( t = scanbuf[curpos++] ) ) {
126 if ( ( t - '0' ) >= base ) t = '0';
127 tokenval = base * tokenval + ( t - '0' );
128 }
129 curpos--;
130 return TOK_NUM;
131 } else if ( isalpha( t ) || ( t == '_' ) ) {
132 int b = 0;
133
134 while ( isalnum( t ) || ( t == '_' ) ) {
135 lexbuf[b] = t;
136 t = scanbuf[curpos++];
137 b = b + 1;
138 if ( ( b + 1 ) >= BUFSIZE ) {
139 // Pufferueberlauf
140 break;
141 }
142 }
143 lexbuf[b] = '\0';
144 if ( t != '\0' ) {
145 curpos--;
146 }
147 return lookup( lexbuf );
148 } else if ( t == '"' ) {
149 int b = 0;
150 int bs = 0;
151
152 for ( ;; ) {
153 t = scanbuf[curpos++];
154 if ( t == EOF )
155 break;
156 if ( ( t == '\\' ) && ( bs == 0 ) ) {
157 bs = 1;
158 continue;
159 }
160 if ( ( t == '"' ) && ( bs == 0 ) )
161 break;
162 bs = 0;
163 lexbuf[b] = t;
164 b = b + 1;
165 if ( ( b + 1 ) >= BUFSIZE ) {
166 // Pufferueberlauf
167 break;
168 }
169 }
170 lexbuf[b] = '\0';
171 return TOK_STRING;
172 } else if ( t == '&' ) {
173 t = scanbuf[curpos++];
174 if ( t == '&' )
175 return TOK_P_AND;
176 return TOK_NONE;
177 } else if ( t == '|' ) {
178 t = scanbuf[curpos++];
179 if ( t == '|' )
180 return TOK_P_OR;
181 return TOK_NONE;
182 } else if ( t == '=' ) {
183 t = scanbuf[curpos++];
184 if ( t == '=' )
185 return TOK_E;
186 return TOK_NONE;
187 } else if ( t == '!' ) {
188 t = scanbuf[curpos++];
189 if ( t == '=' )
190 return TOK_NE;
191 return TOK_NONE;
192 } else if ( t == '<' ) {
193 t = scanbuf[curpos++];
194 if ( t == '=' )
195 return TOK_LE;
196 curpos--;
197 return TOK_LT;
198 } else if ( t == '>' ) {
199 t = scanbuf[curpos++];
200 if ( t == '=' )
201 return TOK_GE;
202 curpos--;
203 return TOK_GT;
204 } else if ( t == '~' ) {
205 t = scanbuf[curpos++];
206 if ( t == '=' )
207 return TOK_REGEQ;
208 return TOK_NONE;
209 } else if ( t == '\0' ) {
210 return TOK_DONE;
211 } else {
212 tokenval = TOK_NONE;
213 return t;
214 }
215 }
216 return TOK_DONE;
217 }
218
match(int t)219 int CondParser::match( int t )
220 {
221 if ( lookahead == t ) {
222 lookahead = lex();
223 } else {
224 return 1;
225 }
226 return 0;
227 }
228
readBrace()229 char *CondParser::readBrace()
230 {
231 int startpos, endpos;
232 int bracecount = 0;
233 int t, ig = 0, len, readpos;
234 char *tstr;
235
236 startpos = curpos;
237 if ( scanbuf[curpos] == '{' ) {
238 do {
239 t = scanbuf[curpos++];
240 if ( t == '\0' ) break;
241 else if ( ( t == '\\' ) && ( ig == 0 ) ) {
242 ig = 1;
243 continue;
244 } else if ( ( t == '{' ) && ( ig == 0 ) ) {
245 bracecount++;
246 } else if ( ( t == '}' ) && ( ig == 0 ) ) {
247 bracecount--;
248 }
249 ig = 0;
250 } while ( bracecount > 0 );
251 }
252 endpos = curpos;
253
254 len = endpos - startpos;
255 tstr = (char*)_allocsafe( len + 1 );
256 if ( len > 0 ) {
257 strncpy( tstr, scanbuf + startpos, len );
258 }
259 tstr[len] = '\0';
260 /* now turn backslashed {/} to normal {/} and remove first and last brace */
261 t = 0; readpos = 1;
262 for( readpos = 1; readpos < ( len - 1); readpos++ ) {
263 if ( ( tstr[readpos] == '\\' ) &&
264 ( ( tstr[readpos + 1 ] == '{' ) || ( tstr[readpos + 1] == '}' ) ) ) {
265 tstr[t] = tstr[readpos + 1];
266 readpos++;
267 } else {
268 tstr[t] = tstr[readpos];
269 }
270 t++;
271 }
272 tstr[t] = '\0';
273 return tstr;
274 }
275
do_parse()276 int CondParser::do_parse()
277 {
278 erg_t *e = NULL;
279 int erg;
280
281 lookahead = lex();
282 if ( lookahead != TOK_DONE ) {
283 e = expr();
284 }
285 if ( e == NULL ) return -1; /* error */
286 erg = e->numval;
287 _freesafe( e->strval );
288 _freesafe( e );
289 if ( lookahead != TOK_DONE ) return -1; /* Not at the end => error */
290 return ( erg == 0 ) ? 0 : 1;
291 }
292
expr()293 CondParser::erg_t * CondParser::expr()
294 {
295 erg_t *e = NULL, *e2;
296 int oldignore;
297 int l;
298
299 if ( ( e = factor() ) == NULL ) return NULL;
300 while ( 1 ) {
301 switch ( lookahead ) {
302 case TOK_P_AND:
303 if ( match( TOK_P_AND ) ) {
304 _freesafe( e->strval );
305 _freesafe( e );
306 return NULL;
307 }
308
309 oldignore = ignore;
310 if ( e->numval == 0 ) ignore = 1;
311
312 if ( ( e2 = factor() ) == NULL ) {
313 _freesafe( e->strval );
314 _freesafe( e );
315 return NULL;
316 }
317
318 ignore = oldignore;
319
320 if ( e->numval != 0 ) {
321 e->numval = e2->numval;
322 }
323 _freesafe( e->strval );
324 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
325 e->wasstring = 0;
326 sprintf( e->strval, "%d", e->numval );
327 _freesafe( e2->strval );
328 _freesafe( e2 );
329 break;
330 case TOK_P_OR:
331 if ( match( TOK_P_OR ) ) {
332 _freesafe( e->strval );
333 _freesafe( e );
334 return NULL;
335 }
336
337 oldignore = ignore;
338 if ( e->numval != 0 ) ignore = 1;
339
340 if ( ( e2 = factor() ) == NULL ) {
341 _freesafe( e->strval );
342 _freesafe( e );
343 return NULL;
344 }
345
346 ignore = oldignore;
347
348 if ( e->numval == 0 ) {
349 e->numval = e2->numval;
350 }
351 _freesafe( e->strval );
352 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
353 e->wasstring = 0;
354 sprintf( e->strval, "%d", e->numval );
355 _freesafe( e2->strval );
356 _freesafe( e2 );
357 break;
358 case TOK_E:
359 case TOK_NE:
360 case TOK_LT:
361 case TOK_LE:
362 case TOK_GT:
363 case TOK_GE:
364 case TOK_REGEQ:
365 l = lookahead;
366 if ( match( lookahead ) ) {
367 _freesafe( e->strval );
368 _freesafe( e );
369 return NULL;
370 }
371
372 if ( ( e2 = factor() ) == NULL ) {
373 _freesafe( e->strval );
374 _freesafe( e );
375 return NULL;
376 }
377
378 if ( ( e->wasstring == 1 ) && ( e2->wasstring == 1 ) ) {
379 /* only do strcmp when both are strings */
380 switch ( l ) {
381 case TOK_NE:
382 e->numval = ( strcmp( e->strval, e2->strval ) != 0 );
383 break;
384 case TOK_LT:
385 e->numval = ( strcmp( e->strval, e2->strval ) < 0 );
386 break;
387 case TOK_LE:
388 e->numval = ( strcmp( e->strval, e2->strval ) <= 0 );
389 break;
390 case TOK_GT:
391 e->numval = ( strcmp( e->strval, e2->strval ) > 0 );
392 break;
393 case TOK_GE:
394 e->numval = ( strcmp( e->strval, e2->strval ) >= 0 );
395 break;
396 case TOK_REGEQ:
397 e->numval = ( re.match( e2->strval, e->strval ) == true );
398 //TODO:bei false k�nnte man e2 und e vertauschen
399 break;
400 default:
401 e->numval = ( strcmp( e->strval, e2->strval ) == 0 );
402 break;
403 }
404 } else {
405 switch ( l ) {
406 case TOK_NE:
407 e->numval = ( e->numval != e2->numval );
408 break;
409 case TOK_LT:
410 e->numval = ( e->numval < e2->numval );
411 break;
412 case TOK_LE:
413 e->numval = ( e->numval <= e2->numval );
414 break;
415 case TOK_GT:
416 e->numval = ( e->numval > e2->numval );
417 break;
418 case TOK_GE:
419 e->numval = ( e->numval >= e2->numval );
420 break;
421 case TOK_REGEQ:
422 // regular expression without strings is always false
423 e->numval = 0;
424 break;
425 default:
426 e->numval = ( e->numval == e2->numval );
427 break;
428 }
429 }
430 _freesafe( e->strval );
431 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
432 e->wasstring = 0;
433 sprintf( e->strval, "%d", e->numval );
434 _freesafe( e2->strval );
435 _freesafe( e2 );
436 break;
437 default:
438 return e;
439 }
440 }
441 return e;
442 }
443
444 #define W_FREEERG(e) do { \
445 if ( (e) != NULL ) { \
446 _freesafe( (e)->strval ); \
447 _freesafe( (e) ); \
448 } \
449 } while( 0 );
450
factor()451 CondParser::erg_t *CondParser::factor()
452 {
453 erg_t *e = NULL, *e2 = NULL;
454 int tnum;
455 char *tstr, *tstr2;
456 ExeClass *ec;
457 int exeerror;
458 const char *cstr;
459 int retval;
460
461 switch ( lookahead ) {
462 case '(':
463 if ( match( '(' ) ) return NULL;
464 if ( ( e = expr() ) == NULL ) return NULL;
465 if ( match( ')' ) ) {
466 W_FREEERG( e );
467 return NULL;
468 }
469 break;
470 case '-':
471 if ( match( '-' ) ) return NULL;
472 tnum = tokenval;
473 if ( match( TOK_NUM ) ) return NULL;
474 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
475 e->numval = tnum * -1;
476 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
477 e->wasstring = 0;
478 sprintf( e->strval, "%d", e->numval );
479 break;
480 case TOK_NUM:
481 tnum = tokenval;
482 if ( match( TOK_NUM ) ) return NULL;
483 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
484 e->numval = tnum;
485 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
486 e->wasstring = 0;
487 sprintf( e->strval, "%d", e->numval );
488 break;
489 case TOK_TRUE:
490 if ( match( TOK_TRUE ) ) return NULL;
491 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
492 e->numval = 1;
493 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
494 e->wasstring = 0;
495 sprintf( e->strval, "%d", e->numval );
496 break;
497 case TOK_FALSE:
498 if ( match( TOK_FALSE ) ) return NULL;
499 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
500 e->numval = 0;
501 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
502 e->wasstring = 0;
503 sprintf( e->strval, "%d", e->numval );
504 break;
505 case TOK_LASTERROR:
506 if ( match( TOK_LASTERROR ) ) return NULL;
507 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
508 e->numval = getLastError();
509 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
510 e->wasstring = 0;
511 sprintf( e->strval, "%d", e->numval );
512 resetLastError();
513 break;
514 case '?':
515 case '$':
516 tstr = readBrace();
517 if ( tstr != NULL ) {
518 if ( ignore == 0 ) {
519 /*execute tstr */
520 tstr2 = replaceFlags( tstr /*, a_max( EXE_STRING_LEN - 1024, 256 ) */);
521 _freesafe( tstr );
522 tstr = tstr2;
523
524 if ( tstr != NULL ) {
525 if ( fe->findOutputAndRV( tstr, &cstr, &retval ) != 0 ) {
526 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
527 ec = new ExeClass();
528 if ( fe != NULL ) {
529 tstr2 = NWC::Path::parentDir( fe->fullname, NULL );
530 if ( tstr2 != NULL ) {
531 ec->cdDir( tstr2 );
532 _freesafe( tstr2 );
533 }
534 }
535 ec->addCommand( "%s", tstr );
536 if ( ec->getOutputAndRV( &(e->strval), &retval, &exeerror ) == 0 ) {
537 if ( lookahead == '?' ) {
538 e->numval = retval;
539 if ( e->strval != NULL ) _freesafe( e->strval );
540 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
541 e->wasstring = 0;
542 sprintf( e->strval, "%d", e->numval );
543 } else {
544 e->wasstring = 1;
545 if ( e->strval == NULL ) {
546 e->strval = dupstring( "" );
547 }
548 e->numval = atoi( e->strval );
549 }
550
551 fe->addOutput( tstr, e->strval, retval );
552 } else {
553 e->strval = dupstring( "0" );
554 e->wasstring = 1;
555 e->numval = atoi( e->strval );
556 }
557 delete ec;
558
559 if ( exeerror != 0 ) {
560 #if 0
561 //TODO: Requester are not possible at the moment because
562 // this thread cannot access GUI functions currently
563 //TODO: I should show content of error file just like in wpucontext
564 if ( worker->getRequester() != NULL ) {
565 char *reqstr;
566 reqstr = (char*)_allocsafe( strlen( catalog.getLocale( 473 ) ) + strlen( tstr ) + 1 );
567 sprintf( reqstr, catalog.getLocale( 473 ), tstr );
568 worker->getRequester()->request( catalog.getLocale( 347 ), reqstr, catalog.getLocale( 11 ) );
569 _freesafe( reqstr );
570 }
571 #endif
572 W_FREEERG( e );
573 _freesafe( tstr );
574 return NULL;
575 }
576 } else {
577 if ( lookahead == '?' ) {
578 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
579 e->numval = retval;
580 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
581 e->wasstring = 0;
582 sprintf( e->strval, "%d", e->numval );
583 } else {
584 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
585 e->strval = dupstring( cstr );
586 e->wasstring = 1;
587 e->numval = atoi( e->strval );
588 }
589 }
590 _freesafe( tstr );
591 }
592 } else {
593 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
594 e->strval = dupstring( "0" );
595 e->wasstring = 1;
596 e->numval = atoi( e->strval );
597 _freesafe( tstr );
598 }
599 }
600 if ( match( lookahead ) ) {
601 W_FREEERG( e );
602 return NULL;
603 }
604 break;
605 case TOK_STRING:
606 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
607 e->wasstring = 1;
608 if ( ignore == 1 ) {
609 e->strval = dupstring( "0" );
610 } else {
611 e->strval = replaceFlags( lexbuf /*, a_max( EXE_STRING_LEN - 1024, 256 )*/, false );
612 if ( e->strval == NULL ) e->strval = dupstring( "0" );
613 }
614 e->numval = atoi( e->strval );
615 if ( match( TOK_STRING ) ) {
616 W_FREEERG( e );
617 return NULL;
618 }
619 break;
620 case TOK_TONUM:
621 if ( match( TOK_TONUM ) ) return NULL;
622 if ( match( '(' ) ) return NULL;
623 if ( ( e = expr() ) == NULL ) return NULL;
624 if ( match( ')' ) ) {
625 W_FREEERG( e );
626 return NULL;
627 }
628 _freesafe( e->strval );
629 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
630 e->wasstring = 0;
631 sprintf( e->strval, "%d", e->numval );
632 break;
633 case TOK_TOSTR:
634 if ( match( TOK_TOSTR ) ) return NULL;
635 if ( match( '(' ) ) return NULL;
636 if ( ( e = expr() ) == NULL ) return NULL;
637 if ( match( ')' ) ) {
638 W_FREEERG( e );
639 return NULL;
640 }
641 _freesafe( e->strval );
642 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
643 e->wasstring = 1;
644 sprintf( e->strval, "%d", e->numval );
645 break;
646 case TOK_ISREG:
647 if ( match( TOK_ISREG ) ) return NULL;
648 if ( match( '(' ) ) return NULL;
649 if ( match( ')' ) ) return NULL;
650 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
651 e->wasstring = 0;
652 if ( fe == NULL ) {
653 e->numval = 0;
654 } else {
655 e->numval = ( S_ISREG( fe->mode() ) ) ? 1 : 0;
656 }
657 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
658 sprintf( e->strval, "%d", e->numval );
659 break;
660 case TOK_ISSOCK:
661 if ( match( TOK_ISSOCK ) ) return NULL;
662 if ( match( '(' ) ) return NULL;
663 if ( match( ')' ) ) return NULL;
664 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
665 e->wasstring = 0;
666 if ( fe == NULL ) {
667 e->numval = 0;
668 } else {
669 #ifdef S_ISSOCK
670 e->numval = ( S_ISSOCK( fe->mode() ) ) ? 1 : 0;
671 #else
672 e->numval = 0;
673 #endif
674 }
675 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
676 sprintf( e->strval, "%d", e->numval );
677 break;
678 case TOK_ISFIFO:
679 if ( match( TOK_ISFIFO ) ) return NULL;
680 if ( match( '(' ) ) return NULL;
681 if ( match( ')' ) ) return NULL;
682 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
683 e->wasstring = 0;
684 if ( fe == NULL ) {
685 e->numval = 0;
686 } else {
687 e->numval = ( S_ISFIFO( fe->mode() ) ) ? 1 : 0;
688 }
689 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
690 sprintf( e->strval, "%d", e->numval );
691 break;
692 case TOK_ISSYMLINK:
693 if ( match( TOK_ISSYMLINK ) ) return NULL;
694 if ( match( '(' ) ) return NULL;
695 if ( match( ')' ) ) return NULL;
696 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
697 e->wasstring = 0;
698 if ( fe == NULL ) {
699 e->numval = 0;
700 } else {
701 e->numval = ( fe->isLink == true ) ? 1 : 0;
702 }
703 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
704 sprintf( e->strval, "%d", e->numval );
705 break;
706 case TOK_ISBROKENSYMLINK:
707 if ( match( TOK_ISBROKENSYMLINK ) ) return NULL;
708 if ( match( '(' ) ) return NULL;
709 if ( match( ')' ) ) return NULL;
710 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
711 e->wasstring = 0;
712 if ( fe == NULL ) {
713 e->numval = 0;
714 } else {
715 e->numval = ( fe->isLink == true && fe->isCorrupt == true ) ? 1 : 0;
716 }
717 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
718 sprintf( e->strval, "%d", e->numval );
719 break;
720 case TOK_SIZE:
721 if ( match( TOK_SIZE ) ) return NULL;
722 if ( match( '(' ) ) return NULL;
723 if ( match( ')' ) ) return NULL;
724 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
725 e->wasstring = 0;
726 if ( fe == NULL ) {
727 e->numval = 0;
728 } else {
729 e->numval = fe->size();
730 }
731 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
732 sprintf( e->strval, "%d", e->numval );
733 break;
734 case TOK_PERM:
735 if ( match( TOK_PERM ) ) return NULL;
736 if ( match( '(' ) ) return NULL;
737 if ( ( e = expr() ) == NULL ) return NULL;
738 if ( match( ')' ) ) {
739 W_FREEERG( e );
740 return NULL;
741 }
742 _freesafe( e->strval );
743 e->wasstring = 0;
744 if ( fe == NULL ) {
745 e->numval = 0;
746 } else {
747 e->numval = ( fe->mode() & e->numval );
748 }
749 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
750 sprintf( e->strval, "%d", e->numval );
751 break;
752 case TOK_TOLOWER:
753 if ( match( TOK_TOLOWER ) ) return NULL;
754 if ( match( '(' ) ) return NULL;
755 if ( ( e = expr() ) == NULL ) return NULL;
756 if ( match( ')' ) ) {
757 W_FREEERG( e );
758 return NULL;
759 }
760 for ( tstr = e->strval; *tstr != '\0'; tstr++ ) {
761 *tstr = tolower( *tstr );
762 }
763 break;
764 case TOK_TOUPPER:
765 if ( match( TOK_TOUPPER ) ) return NULL;
766 if ( match( '(' ) ) return NULL;
767 if ( ( e = expr() ) == NULL ) return NULL;
768 if ( match( ')' ) ) {
769 W_FREEERG( e );
770 return NULL;
771 }
772 for ( tstr = e->strval; *tstr != '\0'; tstr++ ) {
773 *tstr = toupper( *tstr );
774 }
775 break;
776 case TOK_CONTENTSTR:
777 if ( match( TOK_CONTENTSTR ) ) return NULL;
778 if ( match( '(' ) ) return NULL;
779 if ( ( e = expr() ) == NULL ) return NULL;
780 e2 = NULL;
781 if ( lookahead == ',' ) {
782 if ( match( ',' ) ) {
783 W_FREEERG( e );
784 return NULL;
785 }
786 if ( ( e2 = expr() ) == NULL ) {
787 W_FREEERG( e );
788 return NULL;
789 }
790 }
791 if ( match( ')' ) ) {
792 W_FREEERG( e );
793 W_FREEERG( e2 );
794 return NULL;
795 }
796 if ( fe == NULL ) {
797 e->numval = 0;
798 e->wasstring = 0;
799 _freesafe( e->strval );
800 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
801 sprintf( e->strval, "%d", e->numval );
802 } else {
803 if ( ignoreContent == false ) {
804 if ( e2 != NULL ) {
805 tstr = fe->getContentStr( e->numval, e2->numval );
806 } else {
807 tstr = fe->getContentStr( e->numval );
808 }
809 } else {
810 tstr = dupstring( "" );
811 }
812 if ( tstr != NULL ) {
813 _freesafe( e->strval );
814 e->strval = tstr;
815 e->numval = atoi( e->strval );
816 e->wasstring = 1;
817 } else {
818 e->numval = 0;
819 e->wasstring = 0;
820 _freesafe( e->strval );
821 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
822 sprintf( e->strval, "%d", e->numval );
823 }
824 }
825 W_FREEERG( e2 );
826 break;
827 case TOK_CONTENTNUM:
828 if ( match( TOK_CONTENTNUM ) ) return NULL;
829 if ( match( '(' ) ) return NULL;
830 if ( ( e = expr() ) == NULL ) return NULL;
831 e2 = NULL;
832 if ( lookahead == ',' ) {
833 if ( match( ',' ) ) {
834 W_FREEERG( e );
835 return NULL;
836 }
837 if ( ( e2 = expr() ) == NULL ) {
838 W_FREEERG( e );
839 return NULL;
840 }
841 }
842 if ( match( ')' ) ) {
843 W_FREEERG( e );
844 W_FREEERG( e2 );
845 return NULL;
846 }
847 if ( fe == NULL ) {
848 e->numval = 0;
849 e->wasstring = 0;
850 _freesafe( e->strval );
851 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
852 sprintf( e->strval, "%d", e->numval );
853 } else {
854 if ( ignoreContent == false ) {
855 if ( e2 != NULL ) {
856 e->numval = fe->getContentNum( e->numval, e2->numval );
857 } else {
858 e->numval = fe->getContentNum( e->numval );
859 }
860 } else {
861 e->numval = 0;
862 }
863 e->wasstring = 0;
864 _freesafe( e->strval );
865 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
866 sprintf( e->strval, "%d", e->numval );
867 }
868 W_FREEERG( e2 );
869 break;
870 case TOK_NAME:
871 if ( match( TOK_NAME ) ) return NULL;
872 if ( match( '(' ) ) return NULL;
873 if ( match( ')' ) ) return NULL;
874 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
875 if ( fe == NULL ) {
876 e->strval = dupstring( "0" );
877 } else {
878 e->strval = dupstring( fe->name );
879 }
880 e->wasstring = 1;
881 e->numval = atoi( e->strval );
882 break;
883 case TOK_FULLNAME:
884 if ( match( TOK_FULLNAME ) ) return NULL;
885 if ( match( '(' ) ) return NULL;
886 if ( match( ')' ) ) return NULL;
887 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
888 if ( fe == NULL ) {
889 e->strval = dupstring( "0" );
890 } else {
891 e->strval = dupstring( fe->fullname );
892 }
893 e->wasstring = 1;
894 e->numval = atoi( e->strval );
895 break;
896 case TOK_ISLOCAL:
897 if ( match( TOK_ISLOCAL ) ) return NULL;
898 if ( match( '(' ) ) return NULL;
899 if ( match( ')' ) ) return NULL;
900 e = (erg_t*)_allocsafe( sizeof( erg_t ) );
901 e->wasstring = 0;
902 if ( fe == NULL ) {
903 e->numval = 0;
904 } else {
905 e->numval = worker_islocal( fe->fullname );
906 }
907 e->strval = (char*)_allocsafe( A_BYTESFORNUMBER( e->numval ) );
908 sprintf( e->strval, "%d", e->numval );
909 break;
910 default:
911 return NULL;
912 }
913 return e;
914 }
915
parse(const char * str,FileEntry * tfe)916 int CondParser::parse( const char *str, FileEntry *tfe )
917 {
918 int erg;
919
920 if ( str == NULL ) return -1;
921 fe = tfe;
922 scanbuf = str;
923 scanbuflen = strlen( str );
924 curpos = 0;
925 erg = do_parse();
926 scanbuf = NULL;
927 scanbuflen = -1;
928 fe = NULL;
929 return erg;
930 }
931
getLastError() const932 int CondParser::getLastError() const
933 {
934 return lasterror;
935 }
936
resetLastError()937 void CondParser::resetLastError()
938 {
939 lasterror = 0;
940 }
941
942 #define PARSECAT( str1 ) \
943 do { \
944 if ( ( quote == true ) && ( force_noquoting == false ) ) { \
945 dstr[dpos] = '\0'; \
946 newdstr = AGUIX_catTrustedAndUnTrusted( dstr, ( str1 ) ); \
947 if ( (int)strlen( newdstr ) >= maxlen ) { \
948 _freesafe( dstr ); \
949 maxlen = 2 * (int)strlen( newdstr ); \
950 dstr = (char*)_allocsafe( maxlen + 1 ); \
951 } \
952 snprintf( dstr, maxlen, "%s", newdstr ); \
953 _freesafe( newdstr ); \
954 dstr[maxlen] = '\0'; \
955 dpos = (int)strlen( dstr ); \
956 } else { \
957 tlen = (int)strlen( ( str1 ) ); \
958 if ( ( dpos + tlen ) >= maxlen ) { \
959 maxlen = ( dpos + tlen ) * 2; \
960 newdstr = (char*)_allocsafe( maxlen + 1 ); \
961 strncpy( newdstr, dstr, dpos ); \
962 _freesafe( dstr ); \
963 dstr = newdstr; \
964 } \
965 strcpy( &dstr[dpos], ( str1 ) ); \
966 dpos += (int)strlen( ( str1 ) ); \
967 } \
968 } while ( 0 );
969
970 #define PUTCHARDSTR( ch ) \
971 do { \
972 if ( dpos >= maxlen ) { \
973 maxlen = dpos * 2; \
974 newdstr = (char*)_allocsafe( maxlen + 1 ); \
975 strncpy( newdstr, dstr, dpos ); \
976 _freesafe( dstr ); \
977 dstr = newdstr; \
978 } \
979 dstr[dpos++] = ch; \
980 } while ( 0 );
981
replaceFlags(const char * sstr,bool quote)982 char *CondParser::replaceFlags( const char *sstr, bool quote )
983 {
984 char *dstr = NULL, *buf1, ch, *newdstr;
985 int spos=0,dpos=0,bracketcount=0,bufpos=0;
986 int mode=0;
987 int tlen;
988 bool ende;
989 char *tstr;
990 std::string str1;
991 char *flagbuf;
992 int flagbuf_size;
993 bool force_noquoting;
994 int maxlen;
995
996 if ( sstr == NULL ) return NULL;
997 maxlen = strlen( sstr );
998 dstr = (char*)_allocsafe( maxlen + 1 );
999 flagbuf_size = strlen( sstr );
1000 flagbuf = (char*)_allocsafe( flagbuf_size + 1 );
1001 if(dstr!=NULL) {
1002 for(ende=false;ende==false;) {
1003 ch=sstr[spos++];
1004 if(ch=='\0') break;
1005 switch(mode) {
1006 case 1:
1007 // we are in a open bracket and waiting for close bracket
1008 if(ch=='{') {
1009 // other flag, perhaps useless, but perhaps it is in a String-requester
1010 // in any case just overtake it in the buffer
1011 if ( bufpos < flagbuf_size ) flagbuf[ bufpos++ ] = ch;
1012 bracketcount++;
1013 } else if(ch=='}') {
1014 // a closeing bracket
1015 if(bracketcount>1) {
1016 // this is a bracket in the bracket
1017 if ( bufpos < flagbuf_size ) flagbuf[ bufpos++ ] = ch;
1018 } else {
1019 // this is the awaited closebracket
1020 flagbuf[ bufpos ] = 0;
1021 // now flagbuf contains a flag which must be parsed
1022 mode=3;
1023 }
1024 bracketcount--;
1025 } else if(ch=='\\') {
1026 // backslash are only resolved on toplevel (bracketcount==0)
1027 // so overtake also this
1028 if ( bufpos < flagbuf_size ) flagbuf[ bufpos++ ] = ch;
1029 mode=4;
1030 } else {
1031 if ( bufpos < flagbuf_size ) flagbuf[ bufpos++ ] = ch;
1032 }
1033 break;
1034 case 2:
1035 PUTCHARDSTR( ch );
1036 mode=0;
1037 break;
1038 case 4:
1039 if ( bufpos < flagbuf_size ) flagbuf[ bufpos++ ] = ch;
1040 mode=1;
1041 break;
1042 default:
1043 // we are in no bracket
1044 if(ch=='\\') {
1045 // next character is protected and will be overtaken
1046 mode=2;
1047 } else if(ch!='{') {
1048 // a normal character
1049 PUTCHARDSTR( ch );
1050 } else {
1051 mode=1;
1052 bracketcount++;
1053 bufpos=0;
1054 }
1055 break;
1056 }
1057 if(mode==3) {
1058 if ( flagbuf[0] == '-' ) {
1059 force_noquoting = true;
1060 buf1 = flagbuf + 1;
1061 } else {
1062 force_noquoting = false;
1063 buf1 = flagbuf;
1064 }
1065 // parse buf1
1066 if ( strncmp( buf1, "f", 1 ) == 0 ) {
1067 if ( fe != NULL ) {
1068 tstr = fe->name;
1069 if ( tstr != NULL ) {
1070 PARSECAT( tstr );
1071 }
1072 }
1073 } else if ( strncmp( buf1, "F", 1 ) == 0 ) {
1074 if ( fe != NULL ) {
1075 tstr = fe->fullname;
1076 if ( tstr != NULL ) {
1077 PARSECAT( tstr );
1078 }
1079 }
1080 }
1081 mode=0;
1082 }
1083 }
1084 dstr[dpos]=0;
1085 }
1086 _freesafe( flagbuf );
1087 return dstr;
1088 }
1089
requestFlag()1090 const char *CondParser::requestFlag()
1091 {
1092 AGUIX *aguix = Worker::getAGUIX();
1093 AWindow *win;
1094 FieldListView *lv;
1095 AGMessage *msg;
1096 int endmode=-1;
1097 const char *returnstr;
1098 int i, trow, nr;
1099
1100 win = new AWindow( aguix, 10, 10, 10, 10, catalog.getLocale( 338 ), AWindow::AWINDOW_DIALOG );
1101 win->create();
1102
1103 AContainer *ac1 = win->setContainer( new AContainer( win, 1, 3 ), true );
1104 ac1->setMinSpace( 5 );
1105 ac1->setMaxSpace( 5 );
1106 ac1->setBorderWidth( 5 );
1107
1108 win->addMultiLineText( catalog.getLocale( 578 ), *ac1, 0, 0, NULL, NULL );
1109
1110 lv = (FieldListView*)ac1->add( new FieldListView( aguix,
1111 0,
1112 0,
1113 400,
1114 200,
1115 0 ),
1116 0, 1, AContainer::CO_MIN );
1117 lv->setHBarState(2);
1118 lv->setVBarState(2);
1119
1120 lv->setNrOfFields( 3 );
1121 lv->setFieldWidth( 1, 3 );
1122
1123 nr = sizeof( flags ) / sizeof( flags[0] );
1124
1125 for ( i = 0; i < nr; i++ ) {
1126 trow = lv->addRow();
1127 lv->setText( trow, 0, flags[i].flag );
1128 if ( flags[i].catID >= 0 ) {
1129 lv->setText( trow, 2, catalog.getLocale( flags[i].catID ) );
1130 } else {
1131 lv->setText( trow, 2, catalog.getLocaleFlag( flags[i].catflagID ) );
1132 }
1133 lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
1134 lv->setData( trow, i );
1135 }
1136
1137 AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
1138 ac1_1->setMinSpace( 5 );
1139 ac1_1->setMaxSpace( -1 );
1140 ac1_1->setBorderWidth( 0 );
1141 Button *okb =(Button*)ac1_1->add( new Button( aguix,
1142 0,
1143 0,
1144 catalog.getLocale( 11 ),
1145 0 ), 0, 0, AContainer::CO_FIX );
1146 Button *cancelb = (Button*)ac1_1->add( new Button( aguix,
1147 0,
1148 0,
1149 catalog.getLocale( 8 ),
1150 0 ), 1, 0, AContainer::CO_FIX );
1151
1152 win->setDoTabCycling( true );
1153 win->contMaximize( true );
1154 win->show();
1155 for(;endmode==-1;) {
1156 msg=aguix->WaitMessage(win);
1157 if(msg!=NULL) {
1158 switch(msg->type) {
1159 case AG_CLOSEWINDOW:
1160 if(msg->closewindow.window==win->getWindow()) endmode=1;
1161 break;
1162 case AG_BUTTONCLICKED:
1163 if(msg->button.button==okb) endmode=0;
1164 else if(msg->button.button==cancelb) endmode=1;
1165 break;
1166 }
1167 aguix->ReplyMessage(msg);
1168 }
1169 }
1170
1171 returnstr = NULL;
1172 if(endmode==0) {
1173 // ok
1174 trow = lv->getActiveRow();
1175 if ( lv->isValidRow( trow ) == true ) {
1176 i = lv->getData( trow, 0 );
1177 returnstr = flags[i].flag;
1178 }
1179 }
1180
1181 delete win;
1182
1183 return returnstr;
1184 }
1185
getOutput(const char * str,FileEntry * tfe)1186 char *CondParser::getOutput( const char *str, FileEntry *tfe )
1187 {
1188 if ( ( str == NULL ) || ( tfe == NULL ) ) return NULL;
1189 char *erg = NULL;
1190 int retval = 0;
1191 int exeerror = 0;
1192 ExeClass *ec;
1193 char *tstr, *tstr2;
1194
1195 fe = tfe;
1196 tstr = replaceFlags( str );
1197
1198 if ( tstr != NULL ) {
1199 ec = new ExeClass();
1200 tstr2 = NWC::Path::parentDir( fe->fullname, NULL );
1201 if ( tstr2 != NULL ) {
1202 ec->cdDir( tstr2 );
1203 _freesafe( tstr2 );
1204 }
1205 ec->addCommand( "%s", tstr );
1206 if ( ec->getOutputAndRV( &erg, &retval, &exeerror ) != 0 ) {
1207 erg = NULL;
1208 }
1209 delete ec;
1210 _freesafe( tstr );
1211 }
1212 fe = NULL;
1213 return erg;
1214 }
1215
setIgnoreContent(bool nv)1216 void CondParser::setIgnoreContent( bool nv )
1217 {
1218 ignoreContent = nv;
1219 }
1220
getIgnoreContent() const1221 bool CondParser::getIgnoreContent() const
1222 {
1223 return ignoreContent;
1224 }
1225