Annotation of embedaddon/lighttpd/src/mod_ssi_expr.c, revision 1.1.1.2

1.1.1.2 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "buffer.h"
                      4: #include "log.h"
                      5: #include "mod_ssi.h"
                      6: #include "mod_ssi_expr.h"
                      7: #include "mod_ssi_exprparser.h"
                      8: 
                      9: #include <ctype.h>
                     10: #include <string.h>
                     11: 
                     12: typedef struct {
                     13:        const char *input;
                     14:        size_t offset;
                     15:        size_t size;
                     16: 
                     17:        int line_pos;
                     18: 
                     19:        int in_key;
                     20:        int in_brace;
                     21:        int in_cond;
                     22: } ssi_tokenizer_t;
                     23: 
                     24: ssi_val_t *ssi_val_init(void) {
                     25:        ssi_val_t *s;
                     26: 
                     27:        s = calloc(1, sizeof(*s));
                     28: 
                     29:        return s;
                     30: }
                     31: 
                     32: void ssi_val_free(ssi_val_t *s) {
                     33:        if (s->str) buffer_free(s->str);
                     34: 
                     35:        free(s);
                     36: }
                     37: 
                     38: int ssi_val_tobool(ssi_val_t *B) {
                     39:        if (B->type == SSI_TYPE_STRING) {
1.1.1.2 ! misho      40:                return !buffer_string_is_empty(B->str);
1.1       misho      41:        } else {
                     42:                return B->bo;
                     43:        }
                     44: }
                     45: 
                     46: static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p,
                     47:                              ssi_tokenizer_t *t, int *token_id, buffer *token) {
                     48:        int tid = 0;
                     49:        size_t i;
                     50: 
                     51:        UNUSED(con);
                     52: 
                     53:        for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
                     54:                char c = t->input[t->offset];
                     55:                data_string *ds;
                     56: 
                     57:                switch (c) {
                     58:                case '=':
                     59:                        tid = TK_EQ;
                     60: 
                     61:                        t->offset++;
                     62:                        t->line_pos++;
                     63: 
                     64:                        buffer_copy_string_len(token, CONST_STR_LEN("(=)"));
                     65: 
                     66:                        break;
                     67:                case '>':
                     68:                        if (t->input[t->offset + 1] == '=') {
                     69:                                t->offset += 2;
                     70:                                t->line_pos += 2;
                     71: 
                     72:                                tid = TK_GE;
                     73: 
                     74:                                buffer_copy_string_len(token, CONST_STR_LEN("(>=)"));
                     75:                        } else {
                     76:                                t->offset += 1;
                     77:                                t->line_pos += 1;
                     78: 
                     79:                                tid = TK_GT;
                     80: 
                     81:                                buffer_copy_string_len(token, CONST_STR_LEN("(>)"));
                     82:                        }
                     83: 
                     84:                        break;
                     85:                case '<':
                     86:                        if (t->input[t->offset + 1] == '=') {
                     87:                                t->offset += 2;
                     88:                                t->line_pos += 2;
                     89: 
                     90:                                tid = TK_LE;
                     91: 
                     92:                                buffer_copy_string_len(token, CONST_STR_LEN("(<=)"));
                     93:                        } else {
                     94:                                t->offset += 1;
                     95:                                t->line_pos += 1;
                     96: 
                     97:                                tid = TK_LT;
                     98: 
                     99:                                buffer_copy_string_len(token, CONST_STR_LEN("(<)"));
                    100:                        }
                    101: 
                    102:                        break;
                    103: 
                    104:                case '!':
                    105:                        if (t->input[t->offset + 1] == '=') {
                    106:                                t->offset += 2;
                    107:                                t->line_pos += 2;
                    108: 
                    109:                                tid = TK_NE;
                    110: 
                    111:                                buffer_copy_string_len(token, CONST_STR_LEN("(!=)"));
                    112:                        } else {
                    113:                                t->offset += 1;
                    114:                                t->line_pos += 1;
                    115: 
                    116:                                tid = TK_NOT;
                    117: 
                    118:                                buffer_copy_string_len(token, CONST_STR_LEN("(!)"));
                    119:                        }
                    120: 
                    121:                        break;
                    122:                case '&':
                    123:                        if (t->input[t->offset + 1] == '&') {
                    124:                                t->offset += 2;
                    125:                                t->line_pos += 2;
                    126: 
                    127:                                tid = TK_AND;
                    128: 
                    129:                                buffer_copy_string_len(token, CONST_STR_LEN("(&&)"));
                    130:                        } else {
                    131:                                log_error_write(srv, __FILE__, __LINE__, "sds",
                    132:                                                "pos:", t->line_pos,
                    133:                                                "missing second &");
                    134:                                return -1;
                    135:                        }
                    136: 
                    137:                        break;
                    138:                case '|':
                    139:                        if (t->input[t->offset + 1] == '|') {
                    140:                                t->offset += 2;
                    141:                                t->line_pos += 2;
                    142: 
                    143:                                tid = TK_OR;
                    144: 
                    145:                                buffer_copy_string_len(token, CONST_STR_LEN("(||)"));
                    146:                        } else {
                    147:                                log_error_write(srv, __FILE__, __LINE__, "sds",
                    148:                                                "pos:", t->line_pos,
                    149:                                                "missing second |");
                    150:                                return -1;
                    151:                        }
                    152: 
                    153:                        break;
                    154:                case '\t':
                    155:                case ' ':
                    156:                        t->offset++;
                    157:                        t->line_pos++;
                    158:                        break;
                    159: 
                    160:                case '\'':
                    161:                        /* search for the terminating " */
                    162:                        for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\'';  i++);
                    163: 
                    164:                        if (t->input[t->offset + i]) {
                    165:                                tid = TK_VALUE;
                    166: 
                    167:                                buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
                    168: 
                    169:                                t->offset += i + 1;
                    170:                                t->line_pos += i + 1;
                    171:                        } else {
                    172:                                /* ERROR */
                    173: 
                    174:                                log_error_write(srv, __FILE__, __LINE__, "sds",
                    175:                                                "pos:", t->line_pos,
                    176:                                                "missing closing quote");
                    177: 
                    178:                                return -1;
                    179:                        }
                    180: 
                    181:                        break;
                    182:                case '(':
                    183:                        t->offset++;
                    184:                        t->in_brace++;
                    185: 
                    186:                        tid = TK_LPARAN;
                    187: 
                    188:                        buffer_copy_string_len(token, CONST_STR_LEN("("));
                    189:                        break;
                    190:                case ')':
                    191:                        t->offset++;
                    192:                        t->in_brace--;
                    193: 
                    194:                        tid = TK_RPARAN;
                    195: 
                    196:                        buffer_copy_string_len(token, CONST_STR_LEN(")"));
                    197:                        break;
                    198:                case '$':
                    199:                        if (t->input[t->offset + 1] == '{') {
                    200:                                for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}';  i++);
                    201: 
                    202:                                if (t->input[t->offset + i] != '}') {
                    203:                                        log_error_write(srv, __FILE__, __LINE__, "sds",
                    204:                                                        "pos:", t->line_pos,
                    205:                                                        "missing closing quote");
                    206: 
                    207:                                        return -1;
                    208:                                }
                    209: 
                    210:                                buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
                    211:                        } else {
1.1.1.2 ! misho     212:                                for (i = 1; isalpha(t->input[t->offset + i]) ||
        !           213:                                            t->input[t->offset + i] == '_' ||
        !           214:                                            ((i > 1) && isdigit(t->input[t->offset + i]));  i++);
1.1       misho     215: 
                    216:                                buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
                    217:                        }
                    218: 
                    219:                        tid = TK_VALUE;
                    220: 
                    221:                        if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
1.1.1.2 ! misho     222:                                buffer_copy_buffer(token, ds->value);
1.1       misho     223:                        } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
1.1.1.2 ! misho     224:                                buffer_copy_buffer(token, ds->value);
1.1       misho     225:                        } else {
                    226:                                buffer_copy_string_len(token, CONST_STR_LEN(""));
                    227:                        }
                    228: 
                    229:                        t->offset += i;
                    230:                        t->line_pos += i;
                    231: 
                    232:                        break;
                    233:                default:
                    234:                        for (i = 0; isgraph(t->input[t->offset + i]);  i++) {
                    235:                                char d = t->input[t->offset + i];
                    236:                                switch(d) {
                    237:                                case ' ':
                    238:                                case '\t':
                    239:                                case ')':
                    240:                                case '(':
                    241:                                case '\'':
                    242:                                case '=':
                    243:                                case '!':
                    244:                                case '<':
                    245:                                case '>':
                    246:                                case '&':
                    247:                                case '|':
                    248:                                        break;
                    249:                                }
                    250:                        }
                    251: 
                    252:                        tid = TK_VALUE;
                    253: 
                    254:                        buffer_copy_string_len(token, t->input + t->offset, i);
                    255: 
                    256:                        t->offset += i;
                    257:                        t->line_pos += i;
                    258: 
                    259:                        break;
                    260:                }
                    261:        }
                    262: 
                    263:        if (tid) {
                    264:                *token_id = tid;
                    265: 
                    266:                return 1;
                    267:        } else if (t->offset < t->size) {
                    268:                log_error_write(srv, __FILE__, __LINE__, "sds",
                    269:                                "pos:", t->line_pos,
                    270:                                "foobar");
                    271:        }
                    272:        return 0;
                    273: }
                    274: 
                    275: int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr) {
                    276:        ssi_tokenizer_t t;
                    277:        void *pParser;
                    278:        int token_id;
                    279:        buffer *token;
                    280:        ssi_ctx_t context;
                    281:        int ret;
                    282: 
                    283:        t.input = expr;
                    284:        t.offset = 0;
                    285:        t.size = strlen(expr);
                    286:        t.line_pos = 1;
                    287: 
                    288:        t.in_key = 1;
                    289:        t.in_brace = 0;
                    290:        t.in_cond = 0;
                    291: 
                    292:        context.ok = 1;
                    293:        context.srv = srv;
                    294: 
                    295:        /* default context */
                    296: 
                    297:        pParser = ssiexprparserAlloc( malloc );
1.1.1.2 ! misho     298:        force_assert(pParser);
1.1       misho     299:        token = buffer_init();
                    300:        while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
                    301:                ssiexprparser(pParser, token_id, token, &context);
                    302: 
                    303:                token = buffer_init();
                    304:        }
                    305:        ssiexprparser(pParser, 0, token, &context);
                    306:        ssiexprparserFree(pParser, free );
                    307: 
                    308:        buffer_free(token);
                    309: 
                    310:        if (ret == -1) {
                    311:                log_error_write(srv, __FILE__, __LINE__, "s",
                    312:                                "expr parser failed");
                    313:                return -1;
                    314:        }
                    315: 
                    316:        if (context.ok == 0) {
                    317:                log_error_write(srv, __FILE__, __LINE__, "sds",
                    318:                                "pos:", t.line_pos,
                    319:                                "parser failed somehow near here");
                    320:                return -1;
                    321:        }
                    322: #if 0
                    323:        log_error_write(srv, __FILE__, __LINE__, "ssd",
                    324:                        "expr: ",
                    325:                        expr,
                    326:                        context.val.bo);
                    327: #endif
                    328:        return context.val.bo;
                    329: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>