varnish-cache/lib/libvarnishapi/vsl_query.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Martin Blix Grydeland <martin@varnish-software.com>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 */
30
31
#include "config.h"
32
33
#include <ctype.h>
34
#include <math.h>
35
#include <stdio.h>
36
37
#include "vdef.h"
38
#include "vas.h"
39
#include "miniobj.h"
40
41
#include "vbm.h"
42
#include "vnum.h"
43
#include "vqueue.h"
44
#include "vre.h"
45
#include "vsb.h"
46
47
#include "vapi/vsl.h"
48
49
#include "vsl_api.h"
50
#include "vxp.h"
51
52
struct vslq_query {
53
        unsigned                magic;
54
#define VSLQ_QUERY_MAGIC        0x122322A5
55
56
        struct vex              *vex;
57
};
58
59
#define VSLQ_TEST_NUMOP(TYPE, PRE_LHS, OP, PRE_RHS)             \
60
        do {                                                    \
61
                switch (TYPE) {                                 \
62
                case VEX_INT:                                   \
63
                        if (PRE_LHS##_int OP PRE_RHS##_int)     \
64
                                return (1);                     \
65
                        return (0);                             \
66
                case VEX_FLOAT:                                 \
67
                        if (PRE_LHS##_float OP PRE_RHS##_float) \
68
                                return (1);                     \
69
                        return (0);                             \
70
                default:                                        \
71
                        WRONG("Wrong RHS type");                \
72
                }                                               \
73
        } while(0)                                              \
74
75
static int
76 300
vslq_test_vxid(const struct vex *vex, const struct VSL_transaction *trans)
77
{
78
        const struct vex_rhs *rhs;
79
80 300
        AN(vex);
81 300
        AN(trans);
82
83 300
        rhs = vex->rhs;
84 300
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
85
86
        /* Prepare */
87 300
        switch (vex->tok) {
88
        case T_EQ:              /* == */
89
        case T_NEQ:             /* != */
90
        case '<':
91
        case '>':
92
        case T_LEQ:             /* <= */
93
        case T_GEQ:             /* >= */
94 300
                if (rhs->type != VEX_INT)
95 0
                        WRONG("Wrong RHS type for vxid");
96
                /* FALLTHROUGH */
97
        default:
98 300
                break;
99
        }
100
101
        /* Compare */
102 300
        switch (vex->tok) {
103
#define VXID_TEST_NUMOP(OP) return (trans->vxid OP rhs->val_int)
104 300
        case T_EQ:      VXID_TEST_NUMOP(==);
105 0
        case T_NEQ:     VXID_TEST_NUMOP(!=);
106 0
        case '<':       VXID_TEST_NUMOP(<);
107 0
        case '>':       VXID_TEST_NUMOP(>);
108 0
        case T_LEQ:     VXID_TEST_NUMOP(<=);
109 0
        case T_GEQ:     VXID_TEST_NUMOP(>=);
110
        #undef VXID_TEST_NUMOP
111 0
        default:        WRONG("Bad vxid expression token");
112
        }
113
114
        NEEDLESS(return (0));
115
}
116
117
static int
118 125
vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
119
{
120
        const struct vex_rhs *rhs;
121 125
        long long lhs_int = 0;
122 125
        double lhs_float = 0.;
123
        const char *b, *e, *q;
124
        char *p;
125
        int i;
126
127 125
        AN(vex);
128 125
        AN(rec);
129
130 125
        b = VSL_CDATA(rec->ptr);
131 125
        e = b + VSL_LEN(rec->ptr) - 1;
132
133
        /* Prefix */
134 125
        if (vex->lhs->prefix != NULL) {
135 9
                if (strncasecmp(b, vex->lhs->prefix, vex->lhs->prefixlen))
136 8
                        return (0);
137 1
                if (b[vex->lhs->prefixlen] != ':')
138 0
                        return (0);
139 1
                b += vex->lhs->prefixlen + 1;
140
                /* Skip ws */
141 3
                while (*b && isspace(*b))
142 1
                        b++;
143
        }
144
145
        /* Field */
146 117
        if (vex->lhs->field > 0) {
147 36
                for (e = b, i = 0; *e && i < vex->lhs->field; i++) {
148 24
                        b = e;
149
                        /* Skip ws */
150 60
                        while (*b && isspace(*b))
151 12
                                b++;
152 24
                        e = b;
153
                        /* Skip non-ws */
154 170
                        while (*e && !isspace(*e))
155 122
                                e++;
156
                }
157 12
                assert(b <= e);
158 12
                if (*b == '\0' || i < vex->lhs->field)
159
                        /* Missing field - no match */
160 0
                        return (0);
161
        }
162
163 117
        if (vex->tok == T_TRUE)
164
                /* Always true */
165 64
                return (1);
166
167 53
        rhs = vex->rhs;
168 53
        CHECK_OBJ_NOTNULL(rhs, VEX_RHS_MAGIC);
169
170
        /* Prepare */
171 53
        switch (vex->tok) {
172
        case T_EQ:              /* == */
173
        case T_NEQ:             /* != */
174
        case '<':
175
        case '>':
176
        case T_LEQ:             /* <= */
177
        case T_GEQ:             /* >= */
178
                /* Numerical comparison */
179 32
                if (*b == '\0')
180
                        /* Empty string doesn't match */
181 0
                        return (0);
182 32
                switch (rhs->type) {
183
                case VEX_INT:
184 20
                        lhs_int = strtoll(b, &p, 0);
185 20
                        if (*p != '\0' && !isspace(*p))
186 3
                                return (0); /* Can't parse - no match */
187 17
                        break;
188
                case VEX_FLOAT:
189 12
                        lhs_float = VNUMpfx(b, &q);
190 12
                        if (isnan(lhs_float))
191 1
                                return (0);
192 11
                        if (q != NULL && q > b && !isspace(q[-1]))
193 0
                                return (0);
194 11
                        break;
195
                default:
196 0
                        WRONG("Wrong RHS type");
197
                }
198 28
                break;
199
        default:
200 21
                break;
201
        }
202
203
        /* Compare */
204 49
        switch (vex->tok) {
205
        case T_EQ:              /* == */
206 18
                VSLQ_TEST_NUMOP(rhs->type, lhs, ==, rhs->val);
207
        case T_NEQ:             /* != */
208 2
                VSLQ_TEST_NUMOP(rhs->type, lhs, !=, rhs->val);
209
        case '<':               /* < */
210 2
                VSLQ_TEST_NUMOP(rhs->type, lhs, <, rhs->val);
211
        case '>':
212 2
                VSLQ_TEST_NUMOP(rhs->type, lhs, >, rhs->val);
213
        case T_LEQ:             /* <= */
214 2
                VSLQ_TEST_NUMOP(rhs->type, lhs, <=, rhs->val);
215
        case T_GEQ:             /* >= */
216 2
                VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
217
        case T_SEQ:             /* eq */
218 3
                assert(rhs->type == VEX_STRING);
219 3
                if (e - b != rhs->val_stringlen)
220 1
                        return (0);
221 2
                if (vex->options & VEX_OPT_CASELESS) {
222 0
                        if (strncasecmp(b, rhs->val_string, e - b))
223 0
                                return (0);
224
                } else {
225 2
                        if (strncmp(b, rhs->val_string, e - b))
226 0
                                return (0);
227
                }
228 2
                return (1);
229
        case T_SNEQ:            /* ne */
230 1
                assert(rhs->type == VEX_STRING);
231 1
                if (e - b != rhs->val_stringlen)
232 0
                        return (1);
233 1
                if (vex->options & VEX_OPT_CASELESS) {
234 0
                        if (strncasecmp(b, rhs->val_string, e - b))
235 0
                                return (1);
236
                } else {
237 1
                        if (strncmp(b, rhs->val_string, e - b))
238 1
                                return (1);
239
                }
240 0
                return (0);
241
        case '~':               /* ~ */
242 16
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
243 16
                i = VRE_exec(rhs->val_regex, b, e - b, 0, 0, NULL, 0, NULL);
244 16
                if (i != VRE_ERROR_NOMATCH)
245 11
                        return (1);
246 5
                return (0);
247
        case T_NOMATCH:         /* !~ */
248 1
                assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
249 1
                i = VRE_exec(rhs->val_regex, b, e - b, 0, 0, NULL, 0, NULL);
250 1
                if (i == VRE_ERROR_NOMATCH)
251 1
                        return (1);
252 0
                return (0);
253
        default:
254 0
                WRONG("Bad expression token");
255
        }
256
        NEEDLESS(return (0));
257
}
258
259
static int
260 622
vslq_test(const struct vex *vex, struct VSL_transaction * const ptrans[])
261
{
262
        struct VSL_transaction *t;
263
        int i;
264
265 622
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
266 622
        CHECK_OBJ_NOTNULL(vex->lhs, VEX_LHS_MAGIC);
267 622
        AN(vex->lhs->tags);
268 622
        assert(vex->lhs->vxid <= 1);
269
270 622
        if (vex->lhs->vxid) {
271 300
                AZ(vex->lhs->taglist);
272 571
                for (t = ptrans[0]; t != NULL; t = *++ptrans)
273 300
                        if (vslq_test_vxid(vex, t))
274 29
                                return (1);
275 271
                return (0);
276
        }
277
278 322
        AN(vex->lhs->taglist);
279
280 545
        for (t = ptrans[0]; t != NULL; t = *++ptrans) {
281 322
                if (vex->lhs->level >= 0) {
282 3
                        if (vex->lhs->level_pm < 0) {
283
                                /* OK if less than or equal */
284 1
                                if (t->level > vex->lhs->level)
285 0
                                        continue;
286 2
                        } else if (vex->lhs->level_pm > 0) {
287
                                /* OK if greater than or equal */
288 1
                                if (t->level < vex->lhs->level)
289 0
                                        continue;
290
                        } else {
291
                                /* OK if equal */
292 1
                                if (t->level != vex->lhs->level)
293 0
                                        continue;
294
                        }
295
                }
296
297 322
                AZ(VSL_ResetCursor(t->c));
298
                while (1) {
299 8605
                        i = VSL_Next(t->c);
300 8605
                        if (i < 0)
301 0
                                return (i);
302 8605
                        if (i == 0)
303 223
                                break;
304 8382
                        assert(i == 1);
305 8382
                        AN(t->c->rec.ptr);
306
307 8382
                        if (!vbit_test(vex->lhs->tags, VSL_TAG(t->c->rec.ptr)))
308 8257
                                continue;
309
310 125
                        i = vslq_test_rec(vex, &t->c->rec);
311 125
                        if (i)
312 99
                                return (i);
313 8283
                }
314
        }
315
316 223
        return (0);
317
}
318
319
static int
320 635
vslq_exec(const struct vex *vex, struct VSL_transaction * const ptrans[])
321
{
322
        int r;
323
324 635
        CHECK_OBJ_NOTNULL(vex, VEX_MAGIC);
325
326 635
        switch (vex->tok) {
327
        case T_OR:
328 7
                AN(vex->a);
329 7
                AN(vex->b);
330 7
                r = vslq_exec(vex->a, ptrans);
331 7
                if (r != 0)
332 2
                        return (r);
333 5
                return (vslq_exec(vex->b, ptrans));
334
        case T_AND:
335 5
                AN(vex->a);
336 5
                AN(vex->b);
337 5
                r = vslq_exec(vex->a, ptrans);
338 5
                if (r <= 0)
339 3
                        return (r);
340 2
                return (vslq_exec(vex->b, ptrans));
341
        case T_NOT:
342 1
                AN(vex->a);
343 1
                AZ(vex->b);
344 1
                r = vslq_exec(vex->a, ptrans);
345 1
                if (r < 0)
346 0
                        return (r);
347 1
                return (!r);
348
        default:
349 622
                return (vslq_test(vex, ptrans));
350
        }
351
        NEEDLESS(return 0);
352
}
353
354
struct vslq_query *
355 63
vslq_newquery(struct VSL_data *vsl, enum VSL_grouping_e grouping,
356
    const char *querystring)
357
{
358
        struct vsb *vsb;
359
        struct vex *vex;
360 63
        struct vslq_query *query = NULL;
361
362
        (void)grouping;
363 63
        AN(querystring);
364
365 63
        vsb = VSB_new_auto();
366 63
        AN(vsb);
367 63
        vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
368 63
        AZ(VSB_finish(vsb));
369 63
        if (vex == NULL)
370 9
                vsl_diag(vsl, "%s", VSB_data(vsb));
371
        else {
372 54
                ALLOC_OBJ(query, VSLQ_QUERY_MAGIC);
373 54
                XXXAN(query);
374 54
                query->vex = vex;
375
        }
376 63
        VSB_destroy(&vsb);
377 63
        return (query);
378
}
379
380
void
381 54
vslq_deletequery(struct vslq_query **pquery)
382
{
383
        struct vslq_query *query;
384
385 54
        TAKE_OBJ_NOTNULL(query, pquery, VSLQ_QUERY_MAGIC);
386
387 54
        AN(query->vex);
388 54
        vex_Free(&query->vex);
389 54
        AZ(query->vex);
390
391 54
        FREE_OBJ(query);
392 54
}
393
394
int
395 615
vslq_runquery(const struct vslq_query *query,
396
    struct VSL_transaction * const ptrans[])
397
{
398
        struct VSL_transaction *t;
399
        int r;
400
401 615
        CHECK_OBJ_NOTNULL(query, VSLQ_QUERY_MAGIC);
402
403 615
        r = vslq_exec(query->vex, ptrans);
404 1230
        for (t = ptrans[0]; t != NULL; t = *++ptrans)
405 615
                AZ(VSL_ResetCursor(t->c));
406 615
        return (r);
407
}