]>
git.ipfire.org Git - thirdparty/cups.git/blob - cgi-bin/search.c
3d1a18df181cec0dcd5aefc9b79907f934b68db2
2 * Search routines for CUPS.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file. If this file is
11 * missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
18 #include "cgi-private.h"
23 * 'cgiCompileSearch()' - Compile a search string.
26 void * /* O - Search context */
27 cgiCompileSearch(const char *query
) /* I - Query string */
29 regex_t
*re
; /* Regular expression */
30 char *s
, /* Regular expression string */
31 *sptr
, /* Pointer into RE string */
32 *sword
; /* Pointer to start of word */
33 size_t slen
; /* Allocated size of RE string */
34 const char *qptr
, /* Pointer into query string */
35 *qend
; /* End of current word */
36 const char *prefix
; /* Prefix to add to next word */
37 int quoted
; /* Word is quoted */
38 size_t wlen
; /* Word length */
39 char *lword
; /* Last word in query */
42 DEBUG_printf(("cgiCompileSearch(query=\"%s\")\n", query
));
45 * Range check input...
52 * Allocate a regular expression storage structure...
55 if ((re
= (regex_t
*)calloc(1, sizeof(regex_t
))) == NULL
)
59 * Allocate a buffer to hold the regular expression string, starting
60 * at 1024 bytes or 3 times the length of the query string, whichever
61 * is greater. We'll expand the string as needed...
64 slen
= strlen(query
) * 3;
68 if ((s
= (char *)malloc(slen
)) == NULL
)
75 * Copy the query string to the regular expression, handling basic
87 * Skip leading whitespace...
90 while (isspace(*qptr
& 255))
97 * Find the end of the current word...
100 if (*qptr
== '\"' || *qptr
== '\'')
103 * Scan quoted string...
107 for (qend
= qptr
; *qend
&& *qend
!= quoted
; qend
++);
112 * No closing quote, error out!
127 * Scan whitespace-delimited string...
131 for (qend
= qptr
+ 1; *qend
&& !isspace(*qend
); qend
++);
134 wlen
= (size_t)(qend
- qptr
);
137 * Look for logic words: AND, OR
140 if (wlen
== 3 && !_cups_strncasecmp(qptr
, "AND", 3))
143 * Logical AND with the following text...
151 else if (wlen
== 2 && !_cups_strncasecmp(qptr
, "OR", 2))
154 * Logical OR with the following text...
165 * Add a search word, making sure we have enough room for the
166 * string + RE overhead...
169 wlen
= (size_t)(sptr
- s
) + 2 * 4 * wlen
+ 2 * strlen(prefix
) + 11;
171 wlen
+= strlen(lword
);
176 * Expand the RE string buffer...
179 char *temp
; /* Temporary string pointer */
183 temp
= (char *)realloc(s
, slen
);
195 sptr
= temp
+ (sptr
- s
);
200 * Add the prefix string...
203 memcpy(sptr
, prefix
, strlen(prefix
) + 1);
204 sptr
+= strlen(sptr
);
207 * Then quote the remaining word characters as needed for the
216 * Quote: ^ . [ $ ( ) | * + ? { \
219 if (strchr("^.[$()|*+?{\\", *qptr
))
228 * For "word1 AND word2", add reciprocal "word2 AND word1"...
231 if (!strcmp(prefix
, ".*") && lword
)
233 char *lword2
; /* New "last word" */
236 if ((lword2
= strdup(sword
)) == NULL
)
244 memcpy(sptr
, ".*|.*", 6);
247 memcpy(sptr
, lword2
, strlen(lword2
) + 1);
248 sptr
+= strlen(sptr
);
250 memcpy(sptr
, ".*", 3);
253 memcpy(sptr
, lword
, strlen(lword
) + 1);
254 sptr
+= strlen(sptr
);
264 lword
= strdup(sword
);
271 * Advance to the next string...
282 memcpy(sptr
, ".*", 3);
286 * No query data, return NULL...
296 * Compile the regular expression...
299 DEBUG_printf((" s=\"%s\"\n", s
));
301 if (regcomp(re
, s
, REG_EXTENDED
| REG_ICASE
))
310 * Free the RE string and return the new regular expression we compiled...
320 * 'cgiDoSearch()' - Do a search of some text.
323 int /* O - Number of matches */
324 cgiDoSearch(void *search
, /* I - Search context */
325 const char *text
) /* I - Text to search */
327 int i
; /* Looping var */
328 regmatch_t matches
[100]; /* RE matches */
335 if (!search
|| !text
)
342 if (!regexec((regex_t
*)search
, text
, sizeof(matches
) / sizeof(matches
[0]),
346 * Figure out the number of matches in the string...
349 for (i
= 0; i
< (int)(sizeof(matches
) / sizeof(matches
[0])); i
++)
350 if (matches
[i
].rm_so
< 0)
361 * 'cgiFreeSearch()' - Free a compiled search context.
365 cgiFreeSearch(void *search
) /* I - Search context */
367 regfree((regex_t
*)search
);