1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Online help index routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright © 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright © 1997-2007 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "cgi-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include <cups/dir.h>
17*5e7646d2SAndroid Build Coastguard Worker
18*5e7646d2SAndroid Build Coastguard Worker
19*5e7646d2SAndroid Build Coastguard Worker /*
20*5e7646d2SAndroid Build Coastguard Worker * List of common English words that should not be indexed...
21*5e7646d2SAndroid Build Coastguard Worker */
22*5e7646d2SAndroid Build Coastguard Worker
23*5e7646d2SAndroid Build Coastguard Worker static char help_common_words[][6] =
24*5e7646d2SAndroid Build Coastguard Worker {
25*5e7646d2SAndroid Build Coastguard Worker "about",
26*5e7646d2SAndroid Build Coastguard Worker "all",
27*5e7646d2SAndroid Build Coastguard Worker "an",
28*5e7646d2SAndroid Build Coastguard Worker "and",
29*5e7646d2SAndroid Build Coastguard Worker "are",
30*5e7646d2SAndroid Build Coastguard Worker "as",
31*5e7646d2SAndroid Build Coastguard Worker "at",
32*5e7646d2SAndroid Build Coastguard Worker "be",
33*5e7646d2SAndroid Build Coastguard Worker "been",
34*5e7646d2SAndroid Build Coastguard Worker "but",
35*5e7646d2SAndroid Build Coastguard Worker "by",
36*5e7646d2SAndroid Build Coastguard Worker "call",
37*5e7646d2SAndroid Build Coastguard Worker "can",
38*5e7646d2SAndroid Build Coastguard Worker "come",
39*5e7646d2SAndroid Build Coastguard Worker "could",
40*5e7646d2SAndroid Build Coastguard Worker "day",
41*5e7646d2SAndroid Build Coastguard Worker "did",
42*5e7646d2SAndroid Build Coastguard Worker "do",
43*5e7646d2SAndroid Build Coastguard Worker "down",
44*5e7646d2SAndroid Build Coastguard Worker "each",
45*5e7646d2SAndroid Build Coastguard Worker "find",
46*5e7646d2SAndroid Build Coastguard Worker "first",
47*5e7646d2SAndroid Build Coastguard Worker "for",
48*5e7646d2SAndroid Build Coastguard Worker "from",
49*5e7646d2SAndroid Build Coastguard Worker "go",
50*5e7646d2SAndroid Build Coastguard Worker "had",
51*5e7646d2SAndroid Build Coastguard Worker "has",
52*5e7646d2SAndroid Build Coastguard Worker "have",
53*5e7646d2SAndroid Build Coastguard Worker "he",
54*5e7646d2SAndroid Build Coastguard Worker "her",
55*5e7646d2SAndroid Build Coastguard Worker "him",
56*5e7646d2SAndroid Build Coastguard Worker "his",
57*5e7646d2SAndroid Build Coastguard Worker "hot",
58*5e7646d2SAndroid Build Coastguard Worker "how",
59*5e7646d2SAndroid Build Coastguard Worker "if",
60*5e7646d2SAndroid Build Coastguard Worker "in",
61*5e7646d2SAndroid Build Coastguard Worker "is",
62*5e7646d2SAndroid Build Coastguard Worker "it",
63*5e7646d2SAndroid Build Coastguard Worker "know",
64*5e7646d2SAndroid Build Coastguard Worker "like",
65*5e7646d2SAndroid Build Coastguard Worker "long",
66*5e7646d2SAndroid Build Coastguard Worker "look",
67*5e7646d2SAndroid Build Coastguard Worker "make",
68*5e7646d2SAndroid Build Coastguard Worker "many",
69*5e7646d2SAndroid Build Coastguard Worker "may",
70*5e7646d2SAndroid Build Coastguard Worker "more",
71*5e7646d2SAndroid Build Coastguard Worker "most",
72*5e7646d2SAndroid Build Coastguard Worker "my",
73*5e7646d2SAndroid Build Coastguard Worker "no",
74*5e7646d2SAndroid Build Coastguard Worker "now",
75*5e7646d2SAndroid Build Coastguard Worker "of",
76*5e7646d2SAndroid Build Coastguard Worker "on",
77*5e7646d2SAndroid Build Coastguard Worker "one",
78*5e7646d2SAndroid Build Coastguard Worker "or",
79*5e7646d2SAndroid Build Coastguard Worker "other",
80*5e7646d2SAndroid Build Coastguard Worker "out",
81*5e7646d2SAndroid Build Coastguard Worker "over",
82*5e7646d2SAndroid Build Coastguard Worker "said",
83*5e7646d2SAndroid Build Coastguard Worker "see",
84*5e7646d2SAndroid Build Coastguard Worker "she",
85*5e7646d2SAndroid Build Coastguard Worker "side",
86*5e7646d2SAndroid Build Coastguard Worker "so",
87*5e7646d2SAndroid Build Coastguard Worker "some",
88*5e7646d2SAndroid Build Coastguard Worker "sound",
89*5e7646d2SAndroid Build Coastguard Worker "than",
90*5e7646d2SAndroid Build Coastguard Worker "that",
91*5e7646d2SAndroid Build Coastguard Worker "the",
92*5e7646d2SAndroid Build Coastguard Worker "their",
93*5e7646d2SAndroid Build Coastguard Worker "them",
94*5e7646d2SAndroid Build Coastguard Worker "then",
95*5e7646d2SAndroid Build Coastguard Worker "there",
96*5e7646d2SAndroid Build Coastguard Worker "these",
97*5e7646d2SAndroid Build Coastguard Worker "they",
98*5e7646d2SAndroid Build Coastguard Worker "thing",
99*5e7646d2SAndroid Build Coastguard Worker "this",
100*5e7646d2SAndroid Build Coastguard Worker "time",
101*5e7646d2SAndroid Build Coastguard Worker "to",
102*5e7646d2SAndroid Build Coastguard Worker "two",
103*5e7646d2SAndroid Build Coastguard Worker "up",
104*5e7646d2SAndroid Build Coastguard Worker "use",
105*5e7646d2SAndroid Build Coastguard Worker "was",
106*5e7646d2SAndroid Build Coastguard Worker "water",
107*5e7646d2SAndroid Build Coastguard Worker "way",
108*5e7646d2SAndroid Build Coastguard Worker "we",
109*5e7646d2SAndroid Build Coastguard Worker "were",
110*5e7646d2SAndroid Build Coastguard Worker "what",
111*5e7646d2SAndroid Build Coastguard Worker "when",
112*5e7646d2SAndroid Build Coastguard Worker "which",
113*5e7646d2SAndroid Build Coastguard Worker "who",
114*5e7646d2SAndroid Build Coastguard Worker "will",
115*5e7646d2SAndroid Build Coastguard Worker "with",
116*5e7646d2SAndroid Build Coastguard Worker "word",
117*5e7646d2SAndroid Build Coastguard Worker "would",
118*5e7646d2SAndroid Build Coastguard Worker "write",
119*5e7646d2SAndroid Build Coastguard Worker "you",
120*5e7646d2SAndroid Build Coastguard Worker "your"
121*5e7646d2SAndroid Build Coastguard Worker };
122*5e7646d2SAndroid Build Coastguard Worker
123*5e7646d2SAndroid Build Coastguard Worker
124*5e7646d2SAndroid Build Coastguard Worker /*
125*5e7646d2SAndroid Build Coastguard Worker * Local functions...
126*5e7646d2SAndroid Build Coastguard Worker */
127*5e7646d2SAndroid Build Coastguard Worker
128*5e7646d2SAndroid Build Coastguard Worker static help_word_t *help_add_word(help_node_t *n, const char *text);
129*5e7646d2SAndroid Build Coastguard Worker static void help_delete_node(help_node_t *n);
130*5e7646d2SAndroid Build Coastguard Worker static void help_delete_word(help_word_t *w);
131*5e7646d2SAndroid Build Coastguard Worker static int help_load_directory(help_index_t *hi,
132*5e7646d2SAndroid Build Coastguard Worker const char *directory,
133*5e7646d2SAndroid Build Coastguard Worker const char *relative);
134*5e7646d2SAndroid Build Coastguard Worker static int help_load_file(help_index_t *hi,
135*5e7646d2SAndroid Build Coastguard Worker const char *filename,
136*5e7646d2SAndroid Build Coastguard Worker const char *relative,
137*5e7646d2SAndroid Build Coastguard Worker time_t mtime);
138*5e7646d2SAndroid Build Coastguard Worker static help_node_t *help_new_node(const char *filename, const char *anchor, const char *section, const char *text, time_t mtime, off_t offset, size_t length) _CUPS_NONNULL(1,3,4);
139*5e7646d2SAndroid Build Coastguard Worker static int help_sort_by_name(help_node_t *p1, help_node_t *p2);
140*5e7646d2SAndroid Build Coastguard Worker static int help_sort_by_score(help_node_t *p1, help_node_t *p2);
141*5e7646d2SAndroid Build Coastguard Worker static int help_sort_words(help_word_t *w1, help_word_t *w2);
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker
144*5e7646d2SAndroid Build Coastguard Worker /*
145*5e7646d2SAndroid Build Coastguard Worker * 'helpDeleteIndex()' - Delete an index, freeing all memory used.
146*5e7646d2SAndroid Build Coastguard Worker */
147*5e7646d2SAndroid Build Coastguard Worker
148*5e7646d2SAndroid Build Coastguard Worker void
helpDeleteIndex(help_index_t * hi)149*5e7646d2SAndroid Build Coastguard Worker helpDeleteIndex(help_index_t *hi) /* I - Help index */
150*5e7646d2SAndroid Build Coastguard Worker {
151*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
152*5e7646d2SAndroid Build Coastguard Worker
153*5e7646d2SAndroid Build Coastguard Worker
154*5e7646d2SAndroid Build Coastguard Worker if (!hi)
155*5e7646d2SAndroid Build Coastguard Worker return;
156*5e7646d2SAndroid Build Coastguard Worker
157*5e7646d2SAndroid Build Coastguard Worker for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
158*5e7646d2SAndroid Build Coastguard Worker node;
159*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayNext(hi->nodes))
160*5e7646d2SAndroid Build Coastguard Worker {
161*5e7646d2SAndroid Build Coastguard Worker if (!hi->search)
162*5e7646d2SAndroid Build Coastguard Worker help_delete_node(node);
163*5e7646d2SAndroid Build Coastguard Worker }
164*5e7646d2SAndroid Build Coastguard Worker
165*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(hi->nodes);
166*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(hi->sorted);
167*5e7646d2SAndroid Build Coastguard Worker
168*5e7646d2SAndroid Build Coastguard Worker free(hi);
169*5e7646d2SAndroid Build Coastguard Worker }
170*5e7646d2SAndroid Build Coastguard Worker
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker /*
173*5e7646d2SAndroid Build Coastguard Worker * 'helpFindNode()' - Find a node in an index.
174*5e7646d2SAndroid Build Coastguard Worker */
175*5e7646d2SAndroid Build Coastguard Worker
176*5e7646d2SAndroid Build Coastguard Worker help_node_t * /* O - Node pointer or NULL */
helpFindNode(help_index_t * hi,const char * filename,const char * anchor)177*5e7646d2SAndroid Build Coastguard Worker helpFindNode(help_index_t *hi, /* I - Index */
178*5e7646d2SAndroid Build Coastguard Worker const char *filename, /* I - Filename */
179*5e7646d2SAndroid Build Coastguard Worker const char *anchor) /* I - Anchor */
180*5e7646d2SAndroid Build Coastguard Worker {
181*5e7646d2SAndroid Build Coastguard Worker help_node_t key; /* Search key */
182*5e7646d2SAndroid Build Coastguard Worker
183*5e7646d2SAndroid Build Coastguard Worker
184*5e7646d2SAndroid Build Coastguard Worker /*
185*5e7646d2SAndroid Build Coastguard Worker * Range check input...
186*5e7646d2SAndroid Build Coastguard Worker */
187*5e7646d2SAndroid Build Coastguard Worker
188*5e7646d2SAndroid Build Coastguard Worker if (!hi || !filename)
189*5e7646d2SAndroid Build Coastguard Worker return (NULL);
190*5e7646d2SAndroid Build Coastguard Worker
191*5e7646d2SAndroid Build Coastguard Worker /*
192*5e7646d2SAndroid Build Coastguard Worker * Initialize the search key...
193*5e7646d2SAndroid Build Coastguard Worker */
194*5e7646d2SAndroid Build Coastguard Worker
195*5e7646d2SAndroid Build Coastguard Worker key.filename = (char *)filename;
196*5e7646d2SAndroid Build Coastguard Worker key.anchor = (char *)anchor;
197*5e7646d2SAndroid Build Coastguard Worker
198*5e7646d2SAndroid Build Coastguard Worker /*
199*5e7646d2SAndroid Build Coastguard Worker * Return any match...
200*5e7646d2SAndroid Build Coastguard Worker */
201*5e7646d2SAndroid Build Coastguard Worker
202*5e7646d2SAndroid Build Coastguard Worker return ((help_node_t *)cupsArrayFind(hi->nodes, &key));
203*5e7646d2SAndroid Build Coastguard Worker }
204*5e7646d2SAndroid Build Coastguard Worker
205*5e7646d2SAndroid Build Coastguard Worker
206*5e7646d2SAndroid Build Coastguard Worker /*
207*5e7646d2SAndroid Build Coastguard Worker * 'helpLoadIndex()' - Load a help index from disk.
208*5e7646d2SAndroid Build Coastguard Worker */
209*5e7646d2SAndroid Build Coastguard Worker
210*5e7646d2SAndroid Build Coastguard Worker help_index_t * /* O - Index pointer or NULL */
helpLoadIndex(const char * hifile,const char * directory)211*5e7646d2SAndroid Build Coastguard Worker helpLoadIndex(const char *hifile, /* I - Index filename */
212*5e7646d2SAndroid Build Coastguard Worker const char *directory) /* I - Directory that is indexed */
213*5e7646d2SAndroid Build Coastguard Worker {
214*5e7646d2SAndroid Build Coastguard Worker help_index_t *hi; /* Help index */
215*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Current file */
216*5e7646d2SAndroid Build Coastguard Worker char line[2048], /* Line from file */
217*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into line */
218*5e7646d2SAndroid Build Coastguard Worker *filename, /* Filename in line */
219*5e7646d2SAndroid Build Coastguard Worker *anchor, /* Anchor in line */
220*5e7646d2SAndroid Build Coastguard Worker *sectptr, /* Section pointer in line */
221*5e7646d2SAndroid Build Coastguard Worker section[1024], /* Section name */
222*5e7646d2SAndroid Build Coastguard Worker *text; /* Text in line */
223*5e7646d2SAndroid Build Coastguard Worker time_t mtime; /* Modification time */
224*5e7646d2SAndroid Build Coastguard Worker off_t offset; /* Offset into file */
225*5e7646d2SAndroid Build Coastguard Worker size_t length; /* Length in bytes */
226*5e7646d2SAndroid Build Coastguard Worker int update; /* Update? */
227*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
228*5e7646d2SAndroid Build Coastguard Worker help_word_t *word; /* Current word */
229*5e7646d2SAndroid Build Coastguard Worker
230*5e7646d2SAndroid Build Coastguard Worker
231*5e7646d2SAndroid Build Coastguard Worker /*
232*5e7646d2SAndroid Build Coastguard Worker * Create a new, empty index.
233*5e7646d2SAndroid Build Coastguard Worker */
234*5e7646d2SAndroid Build Coastguard Worker
235*5e7646d2SAndroid Build Coastguard Worker if ((hi = (help_index_t *)calloc(1, sizeof(help_index_t))) == NULL)
236*5e7646d2SAndroid Build Coastguard Worker return (NULL);
237*5e7646d2SAndroid Build Coastguard Worker
238*5e7646d2SAndroid Build Coastguard Worker hi->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
239*5e7646d2SAndroid Build Coastguard Worker hi->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
240*5e7646d2SAndroid Build Coastguard Worker
241*5e7646d2SAndroid Build Coastguard Worker if (!hi->nodes || !hi->sorted)
242*5e7646d2SAndroid Build Coastguard Worker {
243*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(hi->nodes);
244*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(hi->sorted);
245*5e7646d2SAndroid Build Coastguard Worker free(hi);
246*5e7646d2SAndroid Build Coastguard Worker return (NULL);
247*5e7646d2SAndroid Build Coastguard Worker }
248*5e7646d2SAndroid Build Coastguard Worker
249*5e7646d2SAndroid Build Coastguard Worker /*
250*5e7646d2SAndroid Build Coastguard Worker * Try loading the existing index file...
251*5e7646d2SAndroid Build Coastguard Worker */
252*5e7646d2SAndroid Build Coastguard Worker
253*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(hifile, "r")) != NULL)
254*5e7646d2SAndroid Build Coastguard Worker {
255*5e7646d2SAndroid Build Coastguard Worker /*
256*5e7646d2SAndroid Build Coastguard Worker * Lock the file and then read the first line...
257*5e7646d2SAndroid Build Coastguard Worker */
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker cupsFileLock(fp, 1);
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker if (cupsFileGets(fp, line, sizeof(line)) && !strcmp(line, "HELPV2"))
262*5e7646d2SAndroid Build Coastguard Worker {
263*5e7646d2SAndroid Build Coastguard Worker /*
264*5e7646d2SAndroid Build Coastguard Worker * Got a valid header line, now read the data lines...
265*5e7646d2SAndroid Build Coastguard Worker */
266*5e7646d2SAndroid Build Coastguard Worker
267*5e7646d2SAndroid Build Coastguard Worker node = NULL;
268*5e7646d2SAndroid Build Coastguard Worker
269*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, line, sizeof(line)))
270*5e7646d2SAndroid Build Coastguard Worker {
271*5e7646d2SAndroid Build Coastguard Worker /*
272*5e7646d2SAndroid Build Coastguard Worker * Each line looks like one of the following:
273*5e7646d2SAndroid Build Coastguard Worker *
274*5e7646d2SAndroid Build Coastguard Worker * filename mtime offset length "section" "text"
275*5e7646d2SAndroid Build Coastguard Worker * filename#anchor offset length "text"
276*5e7646d2SAndroid Build Coastguard Worker * SP count word
277*5e7646d2SAndroid Build Coastguard Worker */
278*5e7646d2SAndroid Build Coastguard Worker
279*5e7646d2SAndroid Build Coastguard Worker if (line[0] == ' ')
280*5e7646d2SAndroid Build Coastguard Worker {
281*5e7646d2SAndroid Build Coastguard Worker /*
282*5e7646d2SAndroid Build Coastguard Worker * Read a word in the current node...
283*5e7646d2SAndroid Build Coastguard Worker */
284*5e7646d2SAndroid Build Coastguard Worker
285*5e7646d2SAndroid Build Coastguard Worker if (!node || (ptr = strrchr(line, ' ')) == NULL)
286*5e7646d2SAndroid Build Coastguard Worker continue;
287*5e7646d2SAndroid Build Coastguard Worker
288*5e7646d2SAndroid Build Coastguard Worker if ((word = help_add_word(node, ptr + 1)) != NULL)
289*5e7646d2SAndroid Build Coastguard Worker word->count = atoi(line + 1);
290*5e7646d2SAndroid Build Coastguard Worker }
291*5e7646d2SAndroid Build Coastguard Worker else
292*5e7646d2SAndroid Build Coastguard Worker {
293*5e7646d2SAndroid Build Coastguard Worker /*
294*5e7646d2SAndroid Build Coastguard Worker * Add a node...
295*5e7646d2SAndroid Build Coastguard Worker */
296*5e7646d2SAndroid Build Coastguard Worker
297*5e7646d2SAndroid Build Coastguard Worker filename = line;
298*5e7646d2SAndroid Build Coastguard Worker
299*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(line, ' ')) == NULL)
300*5e7646d2SAndroid Build Coastguard Worker break;
301*5e7646d2SAndroid Build Coastguard Worker
302*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
303*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
304*5e7646d2SAndroid Build Coastguard Worker
305*5e7646d2SAndroid Build Coastguard Worker if ((anchor = strrchr(filename, '#')) != NULL)
306*5e7646d2SAndroid Build Coastguard Worker {
307*5e7646d2SAndroid Build Coastguard Worker *anchor++ = '\0';
308*5e7646d2SAndroid Build Coastguard Worker mtime = 0;
309*5e7646d2SAndroid Build Coastguard Worker }
310*5e7646d2SAndroid Build Coastguard Worker else
311*5e7646d2SAndroid Build Coastguard Worker mtime = strtol(ptr, &ptr, 10);
312*5e7646d2SAndroid Build Coastguard Worker
313*5e7646d2SAndroid Build Coastguard Worker offset = strtoll(ptr, &ptr, 10);
314*5e7646d2SAndroid Build Coastguard Worker length = (size_t)strtoll(ptr, &ptr, 10);
315*5e7646d2SAndroid Build Coastguard Worker
316*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
317*5e7646d2SAndroid Build Coastguard Worker ptr ++;
318*5e7646d2SAndroid Build Coastguard Worker
319*5e7646d2SAndroid Build Coastguard Worker if (!anchor)
320*5e7646d2SAndroid Build Coastguard Worker {
321*5e7646d2SAndroid Build Coastguard Worker /*
322*5e7646d2SAndroid Build Coastguard Worker * Get section...
323*5e7646d2SAndroid Build Coastguard Worker */
324*5e7646d2SAndroid Build Coastguard Worker
325*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
326*5e7646d2SAndroid Build Coastguard Worker break;
327*5e7646d2SAndroid Build Coastguard Worker
328*5e7646d2SAndroid Build Coastguard Worker ptr ++;
329*5e7646d2SAndroid Build Coastguard Worker sectptr = ptr;
330*5e7646d2SAndroid Build Coastguard Worker
331*5e7646d2SAndroid Build Coastguard Worker while (*ptr && *ptr != '\"')
332*5e7646d2SAndroid Build Coastguard Worker ptr ++;
333*5e7646d2SAndroid Build Coastguard Worker
334*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
335*5e7646d2SAndroid Build Coastguard Worker break;
336*5e7646d2SAndroid Build Coastguard Worker
337*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker strlcpy(section, sectptr, sizeof(section));
340*5e7646d2SAndroid Build Coastguard Worker
341*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
342*5e7646d2SAndroid Build Coastguard Worker ptr ++;
343*5e7646d2SAndroid Build Coastguard Worker }
344*5e7646d2SAndroid Build Coastguard Worker else
345*5e7646d2SAndroid Build Coastguard Worker section[0] = '\0';
346*5e7646d2SAndroid Build Coastguard Worker
347*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
348*5e7646d2SAndroid Build Coastguard Worker break;
349*5e7646d2SAndroid Build Coastguard Worker
350*5e7646d2SAndroid Build Coastguard Worker ptr ++;
351*5e7646d2SAndroid Build Coastguard Worker text = ptr;
352*5e7646d2SAndroid Build Coastguard Worker
353*5e7646d2SAndroid Build Coastguard Worker while (*ptr && *ptr != '\"')
354*5e7646d2SAndroid Build Coastguard Worker ptr ++;
355*5e7646d2SAndroid Build Coastguard Worker
356*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '\"')
357*5e7646d2SAndroid Build Coastguard Worker break;
358*5e7646d2SAndroid Build Coastguard Worker
359*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
360*5e7646d2SAndroid Build Coastguard Worker
361*5e7646d2SAndroid Build Coastguard Worker if ((node = help_new_node(filename, anchor, section, text,
362*5e7646d2SAndroid Build Coastguard Worker mtime, offset, length)) == NULL)
363*5e7646d2SAndroid Build Coastguard Worker break;
364*5e7646d2SAndroid Build Coastguard Worker
365*5e7646d2SAndroid Build Coastguard Worker node->score = -1;
366*5e7646d2SAndroid Build Coastguard Worker
367*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(hi->nodes, node);
368*5e7646d2SAndroid Build Coastguard Worker }
369*5e7646d2SAndroid Build Coastguard Worker }
370*5e7646d2SAndroid Build Coastguard Worker }
371*5e7646d2SAndroid Build Coastguard Worker
372*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
373*5e7646d2SAndroid Build Coastguard Worker }
374*5e7646d2SAndroid Build Coastguard Worker
375*5e7646d2SAndroid Build Coastguard Worker /*
376*5e7646d2SAndroid Build Coastguard Worker * Scan for new/updated files...
377*5e7646d2SAndroid Build Coastguard Worker */
378*5e7646d2SAndroid Build Coastguard Worker
379*5e7646d2SAndroid Build Coastguard Worker update = help_load_directory(hi, directory, NULL);
380*5e7646d2SAndroid Build Coastguard Worker
381*5e7646d2SAndroid Build Coastguard Worker /*
382*5e7646d2SAndroid Build Coastguard Worker * Remove any files that are no longer installed...
383*5e7646d2SAndroid Build Coastguard Worker */
384*5e7646d2SAndroid Build Coastguard Worker
385*5e7646d2SAndroid Build Coastguard Worker for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
386*5e7646d2SAndroid Build Coastguard Worker node;
387*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayNext(hi->nodes))
388*5e7646d2SAndroid Build Coastguard Worker if (node->score < 0)
389*5e7646d2SAndroid Build Coastguard Worker {
390*5e7646d2SAndroid Build Coastguard Worker /*
391*5e7646d2SAndroid Build Coastguard Worker * Delete this node...
392*5e7646d2SAndroid Build Coastguard Worker */
393*5e7646d2SAndroid Build Coastguard Worker
394*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(hi->nodes, node);
395*5e7646d2SAndroid Build Coastguard Worker help_delete_node(node);
396*5e7646d2SAndroid Build Coastguard Worker }
397*5e7646d2SAndroid Build Coastguard Worker
398*5e7646d2SAndroid Build Coastguard Worker /*
399*5e7646d2SAndroid Build Coastguard Worker * Add nodes to the sorted array...
400*5e7646d2SAndroid Build Coastguard Worker */
401*5e7646d2SAndroid Build Coastguard Worker
402*5e7646d2SAndroid Build Coastguard Worker for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
403*5e7646d2SAndroid Build Coastguard Worker node;
404*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayNext(hi->nodes))
405*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(hi->sorted, node);
406*5e7646d2SAndroid Build Coastguard Worker
407*5e7646d2SAndroid Build Coastguard Worker /*
408*5e7646d2SAndroid Build Coastguard Worker * Save the index if we updated it...
409*5e7646d2SAndroid Build Coastguard Worker */
410*5e7646d2SAndroid Build Coastguard Worker
411*5e7646d2SAndroid Build Coastguard Worker if (update)
412*5e7646d2SAndroid Build Coastguard Worker helpSaveIndex(hi, hifile);
413*5e7646d2SAndroid Build Coastguard Worker
414*5e7646d2SAndroid Build Coastguard Worker /*
415*5e7646d2SAndroid Build Coastguard Worker * Return the index...
416*5e7646d2SAndroid Build Coastguard Worker */
417*5e7646d2SAndroid Build Coastguard Worker
418*5e7646d2SAndroid Build Coastguard Worker return (hi);
419*5e7646d2SAndroid Build Coastguard Worker }
420*5e7646d2SAndroid Build Coastguard Worker
421*5e7646d2SAndroid Build Coastguard Worker
422*5e7646d2SAndroid Build Coastguard Worker /*
423*5e7646d2SAndroid Build Coastguard Worker * 'helpSaveIndex()' - Save a help index to disk.
424*5e7646d2SAndroid Build Coastguard Worker */
425*5e7646d2SAndroid Build Coastguard Worker
426*5e7646d2SAndroid Build Coastguard Worker int /* O - 0 on success, -1 on error */
helpSaveIndex(help_index_t * hi,const char * hifile)427*5e7646d2SAndroid Build Coastguard Worker helpSaveIndex(help_index_t *hi, /* I - Index */
428*5e7646d2SAndroid Build Coastguard Worker const char *hifile) /* I - Index filename */
429*5e7646d2SAndroid Build Coastguard Worker {
430*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* Index file */
431*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
432*5e7646d2SAndroid Build Coastguard Worker help_word_t *word; /* Current word */
433*5e7646d2SAndroid Build Coastguard Worker
434*5e7646d2SAndroid Build Coastguard Worker
435*5e7646d2SAndroid Build Coastguard Worker /*
436*5e7646d2SAndroid Build Coastguard Worker * Try creating a new index file...
437*5e7646d2SAndroid Build Coastguard Worker */
438*5e7646d2SAndroid Build Coastguard Worker
439*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(hifile, "w9")) == NULL)
440*5e7646d2SAndroid Build Coastguard Worker return (-1);
441*5e7646d2SAndroid Build Coastguard Worker
442*5e7646d2SAndroid Build Coastguard Worker /*
443*5e7646d2SAndroid Build Coastguard Worker * Lock the file while we write it...
444*5e7646d2SAndroid Build Coastguard Worker */
445*5e7646d2SAndroid Build Coastguard Worker
446*5e7646d2SAndroid Build Coastguard Worker cupsFileLock(fp, 1);
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker cupsFilePuts(fp, "HELPV2\n");
449*5e7646d2SAndroid Build Coastguard Worker
450*5e7646d2SAndroid Build Coastguard Worker for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
451*5e7646d2SAndroid Build Coastguard Worker node;
452*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayNext(hi->nodes))
453*5e7646d2SAndroid Build Coastguard Worker {
454*5e7646d2SAndroid Build Coastguard Worker /*
455*5e7646d2SAndroid Build Coastguard Worker * Write the current node with/without the anchor...
456*5e7646d2SAndroid Build Coastguard Worker */
457*5e7646d2SAndroid Build Coastguard Worker
458*5e7646d2SAndroid Build Coastguard Worker if (node->anchor)
459*5e7646d2SAndroid Build Coastguard Worker {
460*5e7646d2SAndroid Build Coastguard Worker if (cupsFilePrintf(fp, "%s#%s " CUPS_LLFMT " " CUPS_LLFMT " \"%s\"\n",
461*5e7646d2SAndroid Build Coastguard Worker node->filename, node->anchor,
462*5e7646d2SAndroid Build Coastguard Worker CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
463*5e7646d2SAndroid Build Coastguard Worker node->text) < 0)
464*5e7646d2SAndroid Build Coastguard Worker break;
465*5e7646d2SAndroid Build Coastguard Worker }
466*5e7646d2SAndroid Build Coastguard Worker else
467*5e7646d2SAndroid Build Coastguard Worker {
468*5e7646d2SAndroid Build Coastguard Worker if (cupsFilePrintf(fp, "%s %d " CUPS_LLFMT " " CUPS_LLFMT " \"%s\" \"%s\"\n",
469*5e7646d2SAndroid Build Coastguard Worker node->filename, (int)node->mtime,
470*5e7646d2SAndroid Build Coastguard Worker CUPS_LLCAST node->offset, CUPS_LLCAST node->length,
471*5e7646d2SAndroid Build Coastguard Worker node->section ? node->section : "", node->text) < 0)
472*5e7646d2SAndroid Build Coastguard Worker break;
473*5e7646d2SAndroid Build Coastguard Worker }
474*5e7646d2SAndroid Build Coastguard Worker
475*5e7646d2SAndroid Build Coastguard Worker /*
476*5e7646d2SAndroid Build Coastguard Worker * Then write the words associated with the node...
477*5e7646d2SAndroid Build Coastguard Worker */
478*5e7646d2SAndroid Build Coastguard Worker
479*5e7646d2SAndroid Build Coastguard Worker for (word = (help_word_t *)cupsArrayFirst(node->words);
480*5e7646d2SAndroid Build Coastguard Worker word;
481*5e7646d2SAndroid Build Coastguard Worker word = (help_word_t *)cupsArrayNext(node->words))
482*5e7646d2SAndroid Build Coastguard Worker if (cupsFilePrintf(fp, " %d %s\n", word->count, word->text) < 0)
483*5e7646d2SAndroid Build Coastguard Worker break;
484*5e7646d2SAndroid Build Coastguard Worker }
485*5e7646d2SAndroid Build Coastguard Worker
486*5e7646d2SAndroid Build Coastguard Worker cupsFileFlush(fp);
487*5e7646d2SAndroid Build Coastguard Worker
488*5e7646d2SAndroid Build Coastguard Worker if (cupsFileClose(fp) < 0)
489*5e7646d2SAndroid Build Coastguard Worker return (-1);
490*5e7646d2SAndroid Build Coastguard Worker else if (node)
491*5e7646d2SAndroid Build Coastguard Worker return (-1);
492*5e7646d2SAndroid Build Coastguard Worker else
493*5e7646d2SAndroid Build Coastguard Worker return (0);
494*5e7646d2SAndroid Build Coastguard Worker }
495*5e7646d2SAndroid Build Coastguard Worker
496*5e7646d2SAndroid Build Coastguard Worker
497*5e7646d2SAndroid Build Coastguard Worker /*
498*5e7646d2SAndroid Build Coastguard Worker * 'helpSearchIndex()' - Search an index.
499*5e7646d2SAndroid Build Coastguard Worker */
500*5e7646d2SAndroid Build Coastguard Worker
501*5e7646d2SAndroid Build Coastguard Worker help_index_t * /* O - Search index */
helpSearchIndex(help_index_t * hi,const char * query,const char * section,const char * filename)502*5e7646d2SAndroid Build Coastguard Worker helpSearchIndex(help_index_t *hi, /* I - Index */
503*5e7646d2SAndroid Build Coastguard Worker const char *query, /* I - Query string */
504*5e7646d2SAndroid Build Coastguard Worker const char *section, /* I - Limit search to this section */
505*5e7646d2SAndroid Build Coastguard Worker const char *filename) /* I - Limit search to this file */
506*5e7646d2SAndroid Build Coastguard Worker {
507*5e7646d2SAndroid Build Coastguard Worker help_index_t *search; /* Search index */
508*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
509*5e7646d2SAndroid Build Coastguard Worker help_word_t *word; /* Current word */
510*5e7646d2SAndroid Build Coastguard Worker void *sc; /* Search context */
511*5e7646d2SAndroid Build Coastguard Worker int matches; /* Number of matches */
512*5e7646d2SAndroid Build Coastguard Worker
513*5e7646d2SAndroid Build Coastguard Worker
514*5e7646d2SAndroid Build Coastguard Worker /*
515*5e7646d2SAndroid Build Coastguard Worker * Range check...
516*5e7646d2SAndroid Build Coastguard Worker */
517*5e7646d2SAndroid Build Coastguard Worker
518*5e7646d2SAndroid Build Coastguard Worker if (!hi || !query)
519*5e7646d2SAndroid Build Coastguard Worker return (NULL);
520*5e7646d2SAndroid Build Coastguard Worker
521*5e7646d2SAndroid Build Coastguard Worker /*
522*5e7646d2SAndroid Build Coastguard Worker * Reset the scores of all nodes to 0...
523*5e7646d2SAndroid Build Coastguard Worker */
524*5e7646d2SAndroid Build Coastguard Worker
525*5e7646d2SAndroid Build Coastguard Worker for (node = (help_node_t *)cupsArrayFirst(hi->nodes);
526*5e7646d2SAndroid Build Coastguard Worker node;
527*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayNext(hi->nodes))
528*5e7646d2SAndroid Build Coastguard Worker node->score = 0;
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker /*
531*5e7646d2SAndroid Build Coastguard Worker * Find the first node to search in...
532*5e7646d2SAndroid Build Coastguard Worker */
533*5e7646d2SAndroid Build Coastguard Worker
534*5e7646d2SAndroid Build Coastguard Worker if (filename)
535*5e7646d2SAndroid Build Coastguard Worker {
536*5e7646d2SAndroid Build Coastguard Worker node = helpFindNode(hi, filename, NULL);
537*5e7646d2SAndroid Build Coastguard Worker if (!node)
538*5e7646d2SAndroid Build Coastguard Worker return (NULL);
539*5e7646d2SAndroid Build Coastguard Worker }
540*5e7646d2SAndroid Build Coastguard Worker else
541*5e7646d2SAndroid Build Coastguard Worker node = (help_node_t *)cupsArrayFirst(hi->nodes);
542*5e7646d2SAndroid Build Coastguard Worker
543*5e7646d2SAndroid Build Coastguard Worker /*
544*5e7646d2SAndroid Build Coastguard Worker * Convert the query into a regular expression...
545*5e7646d2SAndroid Build Coastguard Worker */
546*5e7646d2SAndroid Build Coastguard Worker
547*5e7646d2SAndroid Build Coastguard Worker sc = cgiCompileSearch(query);
548*5e7646d2SAndroid Build Coastguard Worker if (!sc)
549*5e7646d2SAndroid Build Coastguard Worker return (NULL);
550*5e7646d2SAndroid Build Coastguard Worker
551*5e7646d2SAndroid Build Coastguard Worker /*
552*5e7646d2SAndroid Build Coastguard Worker * Allocate a search index...
553*5e7646d2SAndroid Build Coastguard Worker */
554*5e7646d2SAndroid Build Coastguard Worker
555*5e7646d2SAndroid Build Coastguard Worker search = calloc(1, sizeof(help_index_t));
556*5e7646d2SAndroid Build Coastguard Worker if (!search)
557*5e7646d2SAndroid Build Coastguard Worker {
558*5e7646d2SAndroid Build Coastguard Worker cgiFreeSearch(sc);
559*5e7646d2SAndroid Build Coastguard Worker return (NULL);
560*5e7646d2SAndroid Build Coastguard Worker }
561*5e7646d2SAndroid Build Coastguard Worker
562*5e7646d2SAndroid Build Coastguard Worker search->nodes = cupsArrayNew((cups_array_func_t)help_sort_by_name, NULL);
563*5e7646d2SAndroid Build Coastguard Worker search->sorted = cupsArrayNew((cups_array_func_t)help_sort_by_score, NULL);
564*5e7646d2SAndroid Build Coastguard Worker
565*5e7646d2SAndroid Build Coastguard Worker if (!search->nodes || !search->sorted)
566*5e7646d2SAndroid Build Coastguard Worker {
567*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(search->nodes);
568*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(search->sorted);
569*5e7646d2SAndroid Build Coastguard Worker free(search);
570*5e7646d2SAndroid Build Coastguard Worker cgiFreeSearch(sc);
571*5e7646d2SAndroid Build Coastguard Worker return (NULL);
572*5e7646d2SAndroid Build Coastguard Worker }
573*5e7646d2SAndroid Build Coastguard Worker
574*5e7646d2SAndroid Build Coastguard Worker search->search = 1;
575*5e7646d2SAndroid Build Coastguard Worker
576*5e7646d2SAndroid Build Coastguard Worker /*
577*5e7646d2SAndroid Build Coastguard Worker * Check each node in the index, adding matching nodes to the
578*5e7646d2SAndroid Build Coastguard Worker * search index...
579*5e7646d2SAndroid Build Coastguard Worker */
580*5e7646d2SAndroid Build Coastguard Worker
581*5e7646d2SAndroid Build Coastguard Worker for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
582*5e7646d2SAndroid Build Coastguard Worker if (node->section && section && strcmp(node->section, section))
583*5e7646d2SAndroid Build Coastguard Worker continue;
584*5e7646d2SAndroid Build Coastguard Worker else if (filename && strcmp(node->filename, filename))
585*5e7646d2SAndroid Build Coastguard Worker continue;
586*5e7646d2SAndroid Build Coastguard Worker else
587*5e7646d2SAndroid Build Coastguard Worker {
588*5e7646d2SAndroid Build Coastguard Worker matches = cgiDoSearch(sc, node->text);
589*5e7646d2SAndroid Build Coastguard Worker
590*5e7646d2SAndroid Build Coastguard Worker for (word = (help_word_t *)cupsArrayFirst(node->words);
591*5e7646d2SAndroid Build Coastguard Worker word;
592*5e7646d2SAndroid Build Coastguard Worker word = (help_word_t *)cupsArrayNext(node->words))
593*5e7646d2SAndroid Build Coastguard Worker if (cgiDoSearch(sc, word->text) > 0)
594*5e7646d2SAndroid Build Coastguard Worker matches += word->count;
595*5e7646d2SAndroid Build Coastguard Worker
596*5e7646d2SAndroid Build Coastguard Worker if (matches > 0)
597*5e7646d2SAndroid Build Coastguard Worker {
598*5e7646d2SAndroid Build Coastguard Worker /*
599*5e7646d2SAndroid Build Coastguard Worker * Found a match, add the node to the search index...
600*5e7646d2SAndroid Build Coastguard Worker */
601*5e7646d2SAndroid Build Coastguard Worker
602*5e7646d2SAndroid Build Coastguard Worker node->score = matches;
603*5e7646d2SAndroid Build Coastguard Worker
604*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(search->nodes, node);
605*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(search->sorted, node);
606*5e7646d2SAndroid Build Coastguard Worker }
607*5e7646d2SAndroid Build Coastguard Worker }
608*5e7646d2SAndroid Build Coastguard Worker
609*5e7646d2SAndroid Build Coastguard Worker /*
610*5e7646d2SAndroid Build Coastguard Worker * Free the search context...
611*5e7646d2SAndroid Build Coastguard Worker */
612*5e7646d2SAndroid Build Coastguard Worker
613*5e7646d2SAndroid Build Coastguard Worker cgiFreeSearch(sc);
614*5e7646d2SAndroid Build Coastguard Worker
615*5e7646d2SAndroid Build Coastguard Worker /*
616*5e7646d2SAndroid Build Coastguard Worker * Return the results...
617*5e7646d2SAndroid Build Coastguard Worker */
618*5e7646d2SAndroid Build Coastguard Worker
619*5e7646d2SAndroid Build Coastguard Worker return (search);
620*5e7646d2SAndroid Build Coastguard Worker }
621*5e7646d2SAndroid Build Coastguard Worker
622*5e7646d2SAndroid Build Coastguard Worker
623*5e7646d2SAndroid Build Coastguard Worker /*
624*5e7646d2SAndroid Build Coastguard Worker * 'help_add_word()' - Add a word to a node.
625*5e7646d2SAndroid Build Coastguard Worker */
626*5e7646d2SAndroid Build Coastguard Worker
627*5e7646d2SAndroid Build Coastguard Worker static help_word_t * /* O - New word */
help_add_word(help_node_t * n,const char * text)628*5e7646d2SAndroid Build Coastguard Worker help_add_word(help_node_t *n, /* I - Node */
629*5e7646d2SAndroid Build Coastguard Worker const char *text) /* I - Word text */
630*5e7646d2SAndroid Build Coastguard Worker {
631*5e7646d2SAndroid Build Coastguard Worker help_word_t *w, /* New word */
632*5e7646d2SAndroid Build Coastguard Worker key; /* Search key */
633*5e7646d2SAndroid Build Coastguard Worker
634*5e7646d2SAndroid Build Coastguard Worker
635*5e7646d2SAndroid Build Coastguard Worker /*
636*5e7646d2SAndroid Build Coastguard Worker * Create the words array as needed...
637*5e7646d2SAndroid Build Coastguard Worker */
638*5e7646d2SAndroid Build Coastguard Worker
639*5e7646d2SAndroid Build Coastguard Worker if (!n->words)
640*5e7646d2SAndroid Build Coastguard Worker n->words = cupsArrayNew((cups_array_func_t)help_sort_words, NULL);
641*5e7646d2SAndroid Build Coastguard Worker
642*5e7646d2SAndroid Build Coastguard Worker /*
643*5e7646d2SAndroid Build Coastguard Worker * See if the word is already added...
644*5e7646d2SAndroid Build Coastguard Worker */
645*5e7646d2SAndroid Build Coastguard Worker
646*5e7646d2SAndroid Build Coastguard Worker key.text = (char *)text;
647*5e7646d2SAndroid Build Coastguard Worker
648*5e7646d2SAndroid Build Coastguard Worker if ((w = (help_word_t *)cupsArrayFind(n->words, &key)) == NULL)
649*5e7646d2SAndroid Build Coastguard Worker {
650*5e7646d2SAndroid Build Coastguard Worker /*
651*5e7646d2SAndroid Build Coastguard Worker * Create a new word...
652*5e7646d2SAndroid Build Coastguard Worker */
653*5e7646d2SAndroid Build Coastguard Worker
654*5e7646d2SAndroid Build Coastguard Worker if ((w = calloc(1, sizeof(help_word_t))) == NULL)
655*5e7646d2SAndroid Build Coastguard Worker return (NULL);
656*5e7646d2SAndroid Build Coastguard Worker
657*5e7646d2SAndroid Build Coastguard Worker if ((w->text = strdup(text)) == NULL)
658*5e7646d2SAndroid Build Coastguard Worker {
659*5e7646d2SAndroid Build Coastguard Worker free(w);
660*5e7646d2SAndroid Build Coastguard Worker return (NULL);
661*5e7646d2SAndroid Build Coastguard Worker }
662*5e7646d2SAndroid Build Coastguard Worker
663*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(n->words, w);
664*5e7646d2SAndroid Build Coastguard Worker }
665*5e7646d2SAndroid Build Coastguard Worker
666*5e7646d2SAndroid Build Coastguard Worker /*
667*5e7646d2SAndroid Build Coastguard Worker * Bump the counter for this word and return it...
668*5e7646d2SAndroid Build Coastguard Worker */
669*5e7646d2SAndroid Build Coastguard Worker
670*5e7646d2SAndroid Build Coastguard Worker w->count ++;
671*5e7646d2SAndroid Build Coastguard Worker
672*5e7646d2SAndroid Build Coastguard Worker return (w);
673*5e7646d2SAndroid Build Coastguard Worker }
674*5e7646d2SAndroid Build Coastguard Worker
675*5e7646d2SAndroid Build Coastguard Worker
676*5e7646d2SAndroid Build Coastguard Worker /*
677*5e7646d2SAndroid Build Coastguard Worker * 'help_delete_node()' - Free all memory used by a node.
678*5e7646d2SAndroid Build Coastguard Worker */
679*5e7646d2SAndroid Build Coastguard Worker
680*5e7646d2SAndroid Build Coastguard Worker static void
help_delete_node(help_node_t * n)681*5e7646d2SAndroid Build Coastguard Worker help_delete_node(help_node_t *n) /* I - Node */
682*5e7646d2SAndroid Build Coastguard Worker {
683*5e7646d2SAndroid Build Coastguard Worker help_word_t *w; /* Current word */
684*5e7646d2SAndroid Build Coastguard Worker
685*5e7646d2SAndroid Build Coastguard Worker
686*5e7646d2SAndroid Build Coastguard Worker if (!n)
687*5e7646d2SAndroid Build Coastguard Worker return;
688*5e7646d2SAndroid Build Coastguard Worker
689*5e7646d2SAndroid Build Coastguard Worker if (n->filename)
690*5e7646d2SAndroid Build Coastguard Worker free(n->filename);
691*5e7646d2SAndroid Build Coastguard Worker
692*5e7646d2SAndroid Build Coastguard Worker if (n->anchor)
693*5e7646d2SAndroid Build Coastguard Worker free(n->anchor);
694*5e7646d2SAndroid Build Coastguard Worker
695*5e7646d2SAndroid Build Coastguard Worker if (n->section)
696*5e7646d2SAndroid Build Coastguard Worker free(n->section);
697*5e7646d2SAndroid Build Coastguard Worker
698*5e7646d2SAndroid Build Coastguard Worker if (n->text)
699*5e7646d2SAndroid Build Coastguard Worker free(n->text);
700*5e7646d2SAndroid Build Coastguard Worker
701*5e7646d2SAndroid Build Coastguard Worker for (w = (help_word_t *)cupsArrayFirst(n->words);
702*5e7646d2SAndroid Build Coastguard Worker w;
703*5e7646d2SAndroid Build Coastguard Worker w = (help_word_t *)cupsArrayNext(n->words))
704*5e7646d2SAndroid Build Coastguard Worker help_delete_word(w);
705*5e7646d2SAndroid Build Coastguard Worker
706*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(n->words);
707*5e7646d2SAndroid Build Coastguard Worker
708*5e7646d2SAndroid Build Coastguard Worker free(n);
709*5e7646d2SAndroid Build Coastguard Worker }
710*5e7646d2SAndroid Build Coastguard Worker
711*5e7646d2SAndroid Build Coastguard Worker
712*5e7646d2SAndroid Build Coastguard Worker /*
713*5e7646d2SAndroid Build Coastguard Worker * 'help_delete_word()' - Free all memory used by a word.
714*5e7646d2SAndroid Build Coastguard Worker */
715*5e7646d2SAndroid Build Coastguard Worker
716*5e7646d2SAndroid Build Coastguard Worker static void
help_delete_word(help_word_t * w)717*5e7646d2SAndroid Build Coastguard Worker help_delete_word(help_word_t *w) /* I - Word */
718*5e7646d2SAndroid Build Coastguard Worker {
719*5e7646d2SAndroid Build Coastguard Worker if (!w)
720*5e7646d2SAndroid Build Coastguard Worker return;
721*5e7646d2SAndroid Build Coastguard Worker
722*5e7646d2SAndroid Build Coastguard Worker if (w->text)
723*5e7646d2SAndroid Build Coastguard Worker free(w->text);
724*5e7646d2SAndroid Build Coastguard Worker
725*5e7646d2SAndroid Build Coastguard Worker free(w);
726*5e7646d2SAndroid Build Coastguard Worker }
727*5e7646d2SAndroid Build Coastguard Worker
728*5e7646d2SAndroid Build Coastguard Worker
729*5e7646d2SAndroid Build Coastguard Worker /*
730*5e7646d2SAndroid Build Coastguard Worker * 'help_load_directory()' - Load a directory of files into an index.
731*5e7646d2SAndroid Build Coastguard Worker */
732*5e7646d2SAndroid Build Coastguard Worker
733*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 = success, -1 = error, 1 = updated */
help_load_directory(help_index_t * hi,const char * directory,const char * relative)734*5e7646d2SAndroid Build Coastguard Worker help_load_directory(
735*5e7646d2SAndroid Build Coastguard Worker help_index_t *hi, /* I - Index */
736*5e7646d2SAndroid Build Coastguard Worker const char *directory, /* I - Directory */
737*5e7646d2SAndroid Build Coastguard Worker const char *relative) /* I - Relative path */
738*5e7646d2SAndroid Build Coastguard Worker {
739*5e7646d2SAndroid Build Coastguard Worker cups_dir_t *dir; /* Directory file */
740*5e7646d2SAndroid Build Coastguard Worker cups_dentry_t *dent; /* Directory entry */
741*5e7646d2SAndroid Build Coastguard Worker char *ext, /* Pointer to extension */
742*5e7646d2SAndroid Build Coastguard Worker filename[1024], /* Full filename */
743*5e7646d2SAndroid Build Coastguard Worker relname[1024]; /* Relative filename */
744*5e7646d2SAndroid Build Coastguard Worker int update; /* Updated? */
745*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
746*5e7646d2SAndroid Build Coastguard Worker
747*5e7646d2SAndroid Build Coastguard Worker
748*5e7646d2SAndroid Build Coastguard Worker /*
749*5e7646d2SAndroid Build Coastguard Worker * Open the directory and scan it...
750*5e7646d2SAndroid Build Coastguard Worker */
751*5e7646d2SAndroid Build Coastguard Worker
752*5e7646d2SAndroid Build Coastguard Worker if ((dir = cupsDirOpen(directory)) == NULL)
753*5e7646d2SAndroid Build Coastguard Worker return (0);
754*5e7646d2SAndroid Build Coastguard Worker
755*5e7646d2SAndroid Build Coastguard Worker update = 0;
756*5e7646d2SAndroid Build Coastguard Worker
757*5e7646d2SAndroid Build Coastguard Worker while ((dent = cupsDirRead(dir)) != NULL)
758*5e7646d2SAndroid Build Coastguard Worker {
759*5e7646d2SAndroid Build Coastguard Worker /*
760*5e7646d2SAndroid Build Coastguard Worker * Skip "." files...
761*5e7646d2SAndroid Build Coastguard Worker */
762*5e7646d2SAndroid Build Coastguard Worker
763*5e7646d2SAndroid Build Coastguard Worker if (dent->filename[0] == '.')
764*5e7646d2SAndroid Build Coastguard Worker continue;
765*5e7646d2SAndroid Build Coastguard Worker
766*5e7646d2SAndroid Build Coastguard Worker /*
767*5e7646d2SAndroid Build Coastguard Worker * Get absolute and relative filenames...
768*5e7646d2SAndroid Build Coastguard Worker */
769*5e7646d2SAndroid Build Coastguard Worker
770*5e7646d2SAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), "%s/%s", directory, dent->filename);
771*5e7646d2SAndroid Build Coastguard Worker if (relative)
772*5e7646d2SAndroid Build Coastguard Worker snprintf(relname, sizeof(relname), "%s/%s", relative, dent->filename);
773*5e7646d2SAndroid Build Coastguard Worker else
774*5e7646d2SAndroid Build Coastguard Worker strlcpy(relname, dent->filename, sizeof(relname));
775*5e7646d2SAndroid Build Coastguard Worker
776*5e7646d2SAndroid Build Coastguard Worker /*
777*5e7646d2SAndroid Build Coastguard Worker * Check if we have a HTML file...
778*5e7646d2SAndroid Build Coastguard Worker */
779*5e7646d2SAndroid Build Coastguard Worker
780*5e7646d2SAndroid Build Coastguard Worker if ((ext = strstr(dent->filename, ".html")) != NULL &&
781*5e7646d2SAndroid Build Coastguard Worker (!ext[5] || !strcmp(ext + 5, ".gz")))
782*5e7646d2SAndroid Build Coastguard Worker {
783*5e7646d2SAndroid Build Coastguard Worker /*
784*5e7646d2SAndroid Build Coastguard Worker * HTML file, see if we have already indexed the file...
785*5e7646d2SAndroid Build Coastguard Worker */
786*5e7646d2SAndroid Build Coastguard Worker
787*5e7646d2SAndroid Build Coastguard Worker if ((node = helpFindNode(hi, relname, NULL)) != NULL)
788*5e7646d2SAndroid Build Coastguard Worker {
789*5e7646d2SAndroid Build Coastguard Worker /*
790*5e7646d2SAndroid Build Coastguard Worker * File already indexed - check dates to confirm that the
791*5e7646d2SAndroid Build Coastguard Worker * index is up-to-date...
792*5e7646d2SAndroid Build Coastguard Worker */
793*5e7646d2SAndroid Build Coastguard Worker
794*5e7646d2SAndroid Build Coastguard Worker if (node->mtime == dent->fileinfo.st_mtime)
795*5e7646d2SAndroid Build Coastguard Worker {
796*5e7646d2SAndroid Build Coastguard Worker /*
797*5e7646d2SAndroid Build Coastguard Worker * Same modification time, so mark all of the nodes
798*5e7646d2SAndroid Build Coastguard Worker * for this file as up-to-date...
799*5e7646d2SAndroid Build Coastguard Worker */
800*5e7646d2SAndroid Build Coastguard Worker
801*5e7646d2SAndroid Build Coastguard Worker for (; node; node = (help_node_t *)cupsArrayNext(hi->nodes))
802*5e7646d2SAndroid Build Coastguard Worker if (!strcmp(node->filename, relname))
803*5e7646d2SAndroid Build Coastguard Worker node->score = 0;
804*5e7646d2SAndroid Build Coastguard Worker else
805*5e7646d2SAndroid Build Coastguard Worker break;
806*5e7646d2SAndroid Build Coastguard Worker
807*5e7646d2SAndroid Build Coastguard Worker continue;
808*5e7646d2SAndroid Build Coastguard Worker }
809*5e7646d2SAndroid Build Coastguard Worker }
810*5e7646d2SAndroid Build Coastguard Worker
811*5e7646d2SAndroid Build Coastguard Worker update = 1;
812*5e7646d2SAndroid Build Coastguard Worker
813*5e7646d2SAndroid Build Coastguard Worker help_load_file(hi, filename, relname, dent->fileinfo.st_mtime);
814*5e7646d2SAndroid Build Coastguard Worker }
815*5e7646d2SAndroid Build Coastguard Worker else if (S_ISDIR(dent->fileinfo.st_mode))
816*5e7646d2SAndroid Build Coastguard Worker {
817*5e7646d2SAndroid Build Coastguard Worker /*
818*5e7646d2SAndroid Build Coastguard Worker * Process sub-directory...
819*5e7646d2SAndroid Build Coastguard Worker */
820*5e7646d2SAndroid Build Coastguard Worker
821*5e7646d2SAndroid Build Coastguard Worker if (help_load_directory(hi, filename, relname) == 1)
822*5e7646d2SAndroid Build Coastguard Worker update = 1;
823*5e7646d2SAndroid Build Coastguard Worker }
824*5e7646d2SAndroid Build Coastguard Worker }
825*5e7646d2SAndroid Build Coastguard Worker
826*5e7646d2SAndroid Build Coastguard Worker cupsDirClose(dir);
827*5e7646d2SAndroid Build Coastguard Worker
828*5e7646d2SAndroid Build Coastguard Worker return (update);
829*5e7646d2SAndroid Build Coastguard Worker }
830*5e7646d2SAndroid Build Coastguard Worker
831*5e7646d2SAndroid Build Coastguard Worker
832*5e7646d2SAndroid Build Coastguard Worker /*
833*5e7646d2SAndroid Build Coastguard Worker * 'help_load_file()' - Load a HTML files into an index.
834*5e7646d2SAndroid Build Coastguard Worker */
835*5e7646d2SAndroid Build Coastguard Worker
836*5e7646d2SAndroid Build Coastguard Worker static int /* O - 0 = success, -1 = error */
help_load_file(help_index_t * hi,const char * filename,const char * relative,time_t mtime)837*5e7646d2SAndroid Build Coastguard Worker help_load_file(
838*5e7646d2SAndroid Build Coastguard Worker help_index_t *hi, /* I - Index */
839*5e7646d2SAndroid Build Coastguard Worker const char *filename, /* I - Filename */
840*5e7646d2SAndroid Build Coastguard Worker const char *relative, /* I - Relative path */
841*5e7646d2SAndroid Build Coastguard Worker time_t mtime) /* I - Modification time */
842*5e7646d2SAndroid Build Coastguard Worker {
843*5e7646d2SAndroid Build Coastguard Worker cups_file_t *fp; /* HTML file */
844*5e7646d2SAndroid Build Coastguard Worker help_node_t *node; /* Current node */
845*5e7646d2SAndroid Build Coastguard Worker char line[1024], /* Line from file */
846*5e7646d2SAndroid Build Coastguard Worker temp[1024], /* Temporary word */
847*5e7646d2SAndroid Build Coastguard Worker section[1024], /* Section */
848*5e7646d2SAndroid Build Coastguard Worker *ptr, /* Pointer into line */
849*5e7646d2SAndroid Build Coastguard Worker *anchor, /* Anchor name */
850*5e7646d2SAndroid Build Coastguard Worker *text; /* Text for anchor */
851*5e7646d2SAndroid Build Coastguard Worker off_t offset; /* File offset */
852*5e7646d2SAndroid Build Coastguard Worker char quote; /* Quote character */
853*5e7646d2SAndroid Build Coastguard Worker help_word_t *word; /* Current word */
854*5e7646d2SAndroid Build Coastguard Worker int wordlen; /* Length of word */
855*5e7646d2SAndroid Build Coastguard Worker
856*5e7646d2SAndroid Build Coastguard Worker
857*5e7646d2SAndroid Build Coastguard Worker if ((fp = cupsFileOpen(filename, "r")) == NULL)
858*5e7646d2SAndroid Build Coastguard Worker return (-1);
859*5e7646d2SAndroid Build Coastguard Worker
860*5e7646d2SAndroid Build Coastguard Worker node = NULL;
861*5e7646d2SAndroid Build Coastguard Worker offset = 0;
862*5e7646d2SAndroid Build Coastguard Worker
863*5e7646d2SAndroid Build Coastguard Worker strlcpy(section, "Other", sizeof(section));
864*5e7646d2SAndroid Build Coastguard Worker
865*5e7646d2SAndroid Build Coastguard Worker while (cupsFileGets(fp, line, sizeof(line)))
866*5e7646d2SAndroid Build Coastguard Worker {
867*5e7646d2SAndroid Build Coastguard Worker /*
868*5e7646d2SAndroid Build Coastguard Worker * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix...
869*5e7646d2SAndroid Build Coastguard Worker */
870*5e7646d2SAndroid Build Coastguard Worker
871*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strstr(line, "<!-- SECTION:")) != NULL)
872*5e7646d2SAndroid Build Coastguard Worker {
873*5e7646d2SAndroid Build Coastguard Worker /*
874*5e7646d2SAndroid Build Coastguard Worker * Got section line, copy it!
875*5e7646d2SAndroid Build Coastguard Worker */
876*5e7646d2SAndroid Build Coastguard Worker
877*5e7646d2SAndroid Build Coastguard Worker for (ptr += 13; isspace(*ptr & 255); ptr ++);
878*5e7646d2SAndroid Build Coastguard Worker
879*5e7646d2SAndroid Build Coastguard Worker strlcpy(section, ptr, sizeof(section));
880*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strstr(section, "-->")) != NULL)
881*5e7646d2SAndroid Build Coastguard Worker {
882*5e7646d2SAndroid Build Coastguard Worker /*
883*5e7646d2SAndroid Build Coastguard Worker * Strip comment stuff from end of line...
884*5e7646d2SAndroid Build Coastguard Worker */
885*5e7646d2SAndroid Build Coastguard Worker
886*5e7646d2SAndroid Build Coastguard Worker for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0');
887*5e7646d2SAndroid Build Coastguard Worker
888*5e7646d2SAndroid Build Coastguard Worker if (isspace(*ptr & 255))
889*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
890*5e7646d2SAndroid Build Coastguard Worker }
891*5e7646d2SAndroid Build Coastguard Worker continue;
892*5e7646d2SAndroid Build Coastguard Worker }
893*5e7646d2SAndroid Build Coastguard Worker
894*5e7646d2SAndroid Build Coastguard Worker for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;)
895*5e7646d2SAndroid Build Coastguard Worker {
896*5e7646d2SAndroid Build Coastguard Worker ptr ++;
897*5e7646d2SAndroid Build Coastguard Worker
898*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(ptr, "TITLE>", 6))
899*5e7646d2SAndroid Build Coastguard Worker {
900*5e7646d2SAndroid Build Coastguard Worker /*
901*5e7646d2SAndroid Build Coastguard Worker * Found the title...
902*5e7646d2SAndroid Build Coastguard Worker */
903*5e7646d2SAndroid Build Coastguard Worker
904*5e7646d2SAndroid Build Coastguard Worker anchor = NULL;
905*5e7646d2SAndroid Build Coastguard Worker ptr += 6;
906*5e7646d2SAndroid Build Coastguard Worker }
907*5e7646d2SAndroid Build Coastguard Worker else
908*5e7646d2SAndroid Build Coastguard Worker {
909*5e7646d2SAndroid Build Coastguard Worker char *idptr; /* Pointer to ID */
910*5e7646d2SAndroid Build Coastguard Worker
911*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strncasecmp(ptr, "A NAME=", 7))
912*5e7646d2SAndroid Build Coastguard Worker ptr += 7;
913*5e7646d2SAndroid Build Coastguard Worker else if ((idptr = strstr(ptr, " ID=")) != NULL)
914*5e7646d2SAndroid Build Coastguard Worker ptr = idptr + 4;
915*5e7646d2SAndroid Build Coastguard Worker else if ((idptr = strstr(ptr, " id=")) != NULL)
916*5e7646d2SAndroid Build Coastguard Worker ptr = idptr + 4;
917*5e7646d2SAndroid Build Coastguard Worker else
918*5e7646d2SAndroid Build Coastguard Worker continue;
919*5e7646d2SAndroid Build Coastguard Worker
920*5e7646d2SAndroid Build Coastguard Worker /*
921*5e7646d2SAndroid Build Coastguard Worker * Found an anchor...
922*5e7646d2SAndroid Build Coastguard Worker */
923*5e7646d2SAndroid Build Coastguard Worker
924*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\"' || *ptr == '\'')
925*5e7646d2SAndroid Build Coastguard Worker {
926*5e7646d2SAndroid Build Coastguard Worker /*
927*5e7646d2SAndroid Build Coastguard Worker * Get quoted anchor...
928*5e7646d2SAndroid Build Coastguard Worker */
929*5e7646d2SAndroid Build Coastguard Worker
930*5e7646d2SAndroid Build Coastguard Worker quote = *ptr;
931*5e7646d2SAndroid Build Coastguard Worker anchor = ptr + 1;
932*5e7646d2SAndroid Build Coastguard Worker if ((ptr = strchr(anchor, quote)) != NULL)
933*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
934*5e7646d2SAndroid Build Coastguard Worker else
935*5e7646d2SAndroid Build Coastguard Worker break;
936*5e7646d2SAndroid Build Coastguard Worker }
937*5e7646d2SAndroid Build Coastguard Worker else
938*5e7646d2SAndroid Build Coastguard Worker {
939*5e7646d2SAndroid Build Coastguard Worker /*
940*5e7646d2SAndroid Build Coastguard Worker * Get unquoted anchor...
941*5e7646d2SAndroid Build Coastguard Worker */
942*5e7646d2SAndroid Build Coastguard Worker
943*5e7646d2SAndroid Build Coastguard Worker anchor = ptr + 1;
944*5e7646d2SAndroid Build Coastguard Worker
945*5e7646d2SAndroid Build Coastguard Worker for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++);
946*5e7646d2SAndroid Build Coastguard Worker
947*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '>')
948*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
949*5e7646d2SAndroid Build Coastguard Worker else
950*5e7646d2SAndroid Build Coastguard Worker break;
951*5e7646d2SAndroid Build Coastguard Worker }
952*5e7646d2SAndroid Build Coastguard Worker
953*5e7646d2SAndroid Build Coastguard Worker /*
954*5e7646d2SAndroid Build Coastguard Worker * Got the anchor, now lets find the end...
955*5e7646d2SAndroid Build Coastguard Worker */
956*5e7646d2SAndroid Build Coastguard Worker
957*5e7646d2SAndroid Build Coastguard Worker while (*ptr && *ptr != '>')
958*5e7646d2SAndroid Build Coastguard Worker ptr ++;
959*5e7646d2SAndroid Build Coastguard Worker
960*5e7646d2SAndroid Build Coastguard Worker if (*ptr != '>')
961*5e7646d2SAndroid Build Coastguard Worker break;
962*5e7646d2SAndroid Build Coastguard Worker
963*5e7646d2SAndroid Build Coastguard Worker *ptr++ = '\0';
964*5e7646d2SAndroid Build Coastguard Worker }
965*5e7646d2SAndroid Build Coastguard Worker
966*5e7646d2SAndroid Build Coastguard Worker /*
967*5e7646d2SAndroid Build Coastguard Worker * Now collect text for the link...
968*5e7646d2SAndroid Build Coastguard Worker */
969*5e7646d2SAndroid Build Coastguard Worker
970*5e7646d2SAndroid Build Coastguard Worker text = ptr;
971*5e7646d2SAndroid Build Coastguard Worker while ((ptr = strchr(text, '<')) == NULL)
972*5e7646d2SAndroid Build Coastguard Worker {
973*5e7646d2SAndroid Build Coastguard Worker ptr = text + strlen(text);
974*5e7646d2SAndroid Build Coastguard Worker if (ptr >= (line + sizeof(line) - 2))
975*5e7646d2SAndroid Build Coastguard Worker break;
976*5e7646d2SAndroid Build Coastguard Worker
977*5e7646d2SAndroid Build Coastguard Worker *ptr++ = ' ';
978*5e7646d2SAndroid Build Coastguard Worker
979*5e7646d2SAndroid Build Coastguard Worker if (!cupsFileGets(fp, ptr, sizeof(line) - (size_t)(ptr - line) - 1))
980*5e7646d2SAndroid Build Coastguard Worker break;
981*5e7646d2SAndroid Build Coastguard Worker }
982*5e7646d2SAndroid Build Coastguard Worker
983*5e7646d2SAndroid Build Coastguard Worker *ptr = '\0';
984*5e7646d2SAndroid Build Coastguard Worker
985*5e7646d2SAndroid Build Coastguard Worker if (node)
986*5e7646d2SAndroid Build Coastguard Worker node->length = (size_t)(offset - node->offset);
987*5e7646d2SAndroid Build Coastguard Worker
988*5e7646d2SAndroid Build Coastguard Worker if (!*text)
989*5e7646d2SAndroid Build Coastguard Worker {
990*5e7646d2SAndroid Build Coastguard Worker node = NULL;
991*5e7646d2SAndroid Build Coastguard Worker break;
992*5e7646d2SAndroid Build Coastguard Worker }
993*5e7646d2SAndroid Build Coastguard Worker
994*5e7646d2SAndroid Build Coastguard Worker if ((node = helpFindNode(hi, relative, anchor)) != NULL)
995*5e7646d2SAndroid Build Coastguard Worker {
996*5e7646d2SAndroid Build Coastguard Worker /*
997*5e7646d2SAndroid Build Coastguard Worker * Node already in the index, so replace the text and other
998*5e7646d2SAndroid Build Coastguard Worker * data...
999*5e7646d2SAndroid Build Coastguard Worker */
1000*5e7646d2SAndroid Build Coastguard Worker
1001*5e7646d2SAndroid Build Coastguard Worker cupsArrayRemove(hi->nodes, node);
1002*5e7646d2SAndroid Build Coastguard Worker
1003*5e7646d2SAndroid Build Coastguard Worker if (node->section)
1004*5e7646d2SAndroid Build Coastguard Worker free(node->section);
1005*5e7646d2SAndroid Build Coastguard Worker
1006*5e7646d2SAndroid Build Coastguard Worker if (node->text)
1007*5e7646d2SAndroid Build Coastguard Worker free(node->text);
1008*5e7646d2SAndroid Build Coastguard Worker
1009*5e7646d2SAndroid Build Coastguard Worker if (node->words)
1010*5e7646d2SAndroid Build Coastguard Worker {
1011*5e7646d2SAndroid Build Coastguard Worker for (word = (help_word_t *)cupsArrayFirst(node->words);
1012*5e7646d2SAndroid Build Coastguard Worker word;
1013*5e7646d2SAndroid Build Coastguard Worker word = (help_word_t *)cupsArrayNext(node->words))
1014*5e7646d2SAndroid Build Coastguard Worker help_delete_word(word);
1015*5e7646d2SAndroid Build Coastguard Worker
1016*5e7646d2SAndroid Build Coastguard Worker cupsArrayDelete(node->words);
1017*5e7646d2SAndroid Build Coastguard Worker node->words = NULL;
1018*5e7646d2SAndroid Build Coastguard Worker }
1019*5e7646d2SAndroid Build Coastguard Worker
1020*5e7646d2SAndroid Build Coastguard Worker node->section = section[0] ? strdup(section) : NULL;
1021*5e7646d2SAndroid Build Coastguard Worker node->text = strdup(text);
1022*5e7646d2SAndroid Build Coastguard Worker node->mtime = mtime;
1023*5e7646d2SAndroid Build Coastguard Worker node->offset = offset;
1024*5e7646d2SAndroid Build Coastguard Worker node->score = 0;
1025*5e7646d2SAndroid Build Coastguard Worker }
1026*5e7646d2SAndroid Build Coastguard Worker else
1027*5e7646d2SAndroid Build Coastguard Worker {
1028*5e7646d2SAndroid Build Coastguard Worker /*
1029*5e7646d2SAndroid Build Coastguard Worker * New node...
1030*5e7646d2SAndroid Build Coastguard Worker */
1031*5e7646d2SAndroid Build Coastguard Worker
1032*5e7646d2SAndroid Build Coastguard Worker node = help_new_node(relative, anchor, section, text, mtime, offset, 0);
1033*5e7646d2SAndroid Build Coastguard Worker }
1034*5e7646d2SAndroid Build Coastguard Worker
1035*5e7646d2SAndroid Build Coastguard Worker /*
1036*5e7646d2SAndroid Build Coastguard Worker * Go through the text value and replace tabs and newlines with
1037*5e7646d2SAndroid Build Coastguard Worker * whitespace and eliminate extra whitespace...
1038*5e7646d2SAndroid Build Coastguard Worker */
1039*5e7646d2SAndroid Build Coastguard Worker
1040*5e7646d2SAndroid Build Coastguard Worker for (ptr = node->text, text = node->text; *ptr;)
1041*5e7646d2SAndroid Build Coastguard Worker if (isspace(*ptr & 255))
1042*5e7646d2SAndroid Build Coastguard Worker {
1043*5e7646d2SAndroid Build Coastguard Worker while (isspace(*ptr & 255))
1044*5e7646d2SAndroid Build Coastguard Worker ptr ++;
1045*5e7646d2SAndroid Build Coastguard Worker
1046*5e7646d2SAndroid Build Coastguard Worker *text++ = ' ';
1047*5e7646d2SAndroid Build Coastguard Worker }
1048*5e7646d2SAndroid Build Coastguard Worker else if (text != ptr)
1049*5e7646d2SAndroid Build Coastguard Worker *text++ = *ptr++;
1050*5e7646d2SAndroid Build Coastguard Worker else
1051*5e7646d2SAndroid Build Coastguard Worker {
1052*5e7646d2SAndroid Build Coastguard Worker text ++;
1053*5e7646d2SAndroid Build Coastguard Worker ptr ++;
1054*5e7646d2SAndroid Build Coastguard Worker }
1055*5e7646d2SAndroid Build Coastguard Worker
1056*5e7646d2SAndroid Build Coastguard Worker *text = '\0';
1057*5e7646d2SAndroid Build Coastguard Worker
1058*5e7646d2SAndroid Build Coastguard Worker /*
1059*5e7646d2SAndroid Build Coastguard Worker * (Re)add the node to the array...
1060*5e7646d2SAndroid Build Coastguard Worker */
1061*5e7646d2SAndroid Build Coastguard Worker
1062*5e7646d2SAndroid Build Coastguard Worker cupsArrayAdd(hi->nodes, node);
1063*5e7646d2SAndroid Build Coastguard Worker
1064*5e7646d2SAndroid Build Coastguard Worker if (!anchor)
1065*5e7646d2SAndroid Build Coastguard Worker node = NULL;
1066*5e7646d2SAndroid Build Coastguard Worker break;
1067*5e7646d2SAndroid Build Coastguard Worker }
1068*5e7646d2SAndroid Build Coastguard Worker
1069*5e7646d2SAndroid Build Coastguard Worker if (node)
1070*5e7646d2SAndroid Build Coastguard Worker {
1071*5e7646d2SAndroid Build Coastguard Worker /*
1072*5e7646d2SAndroid Build Coastguard Worker * Scan this line for words...
1073*5e7646d2SAndroid Build Coastguard Worker */
1074*5e7646d2SAndroid Build Coastguard Worker
1075*5e7646d2SAndroid Build Coastguard Worker for (ptr = line; *ptr; ptr ++)
1076*5e7646d2SAndroid Build Coastguard Worker {
1077*5e7646d2SAndroid Build Coastguard Worker /*
1078*5e7646d2SAndroid Build Coastguard Worker * Skip HTML stuff...
1079*5e7646d2SAndroid Build Coastguard Worker */
1080*5e7646d2SAndroid Build Coastguard Worker
1081*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '<')
1082*5e7646d2SAndroid Build Coastguard Worker {
1083*5e7646d2SAndroid Build Coastguard Worker if (!strncmp(ptr, "<!--", 4))
1084*5e7646d2SAndroid Build Coastguard Worker {
1085*5e7646d2SAndroid Build Coastguard Worker /*
1086*5e7646d2SAndroid Build Coastguard Worker * Skip HTML comment...
1087*5e7646d2SAndroid Build Coastguard Worker */
1088*5e7646d2SAndroid Build Coastguard Worker
1089*5e7646d2SAndroid Build Coastguard Worker if ((text = strstr(ptr + 4, "-->")) == NULL)
1090*5e7646d2SAndroid Build Coastguard Worker ptr += strlen(ptr) - 1;
1091*5e7646d2SAndroid Build Coastguard Worker else
1092*5e7646d2SAndroid Build Coastguard Worker ptr = text + 2;
1093*5e7646d2SAndroid Build Coastguard Worker }
1094*5e7646d2SAndroid Build Coastguard Worker else
1095*5e7646d2SAndroid Build Coastguard Worker {
1096*5e7646d2SAndroid Build Coastguard Worker /*
1097*5e7646d2SAndroid Build Coastguard Worker * Skip HTML element...
1098*5e7646d2SAndroid Build Coastguard Worker */
1099*5e7646d2SAndroid Build Coastguard Worker
1100*5e7646d2SAndroid Build Coastguard Worker for (ptr ++; *ptr && *ptr != '>'; ptr ++)
1101*5e7646d2SAndroid Build Coastguard Worker {
1102*5e7646d2SAndroid Build Coastguard Worker if (*ptr == '\"' || *ptr == '\'')
1103*5e7646d2SAndroid Build Coastguard Worker {
1104*5e7646d2SAndroid Build Coastguard Worker for (quote = *ptr++; *ptr && *ptr != quote; ptr ++);
1105*5e7646d2SAndroid Build Coastguard Worker
1106*5e7646d2SAndroid Build Coastguard Worker if (!*ptr)
1107*5e7646d2SAndroid Build Coastguard Worker ptr --;
1108*5e7646d2SAndroid Build Coastguard Worker }
1109*5e7646d2SAndroid Build Coastguard Worker }
1110*5e7646d2SAndroid Build Coastguard Worker
1111*5e7646d2SAndroid Build Coastguard Worker if (!*ptr)
1112*5e7646d2SAndroid Build Coastguard Worker ptr --;
1113*5e7646d2SAndroid Build Coastguard Worker }
1114*5e7646d2SAndroid Build Coastguard Worker
1115*5e7646d2SAndroid Build Coastguard Worker continue;
1116*5e7646d2SAndroid Build Coastguard Worker }
1117*5e7646d2SAndroid Build Coastguard Worker else if (*ptr == '&')
1118*5e7646d2SAndroid Build Coastguard Worker {
1119*5e7646d2SAndroid Build Coastguard Worker /*
1120*5e7646d2SAndroid Build Coastguard Worker * Skip HTML entity...
1121*5e7646d2SAndroid Build Coastguard Worker */
1122*5e7646d2SAndroid Build Coastguard Worker
1123*5e7646d2SAndroid Build Coastguard Worker for (ptr ++; *ptr && *ptr != ';'; ptr ++);
1124*5e7646d2SAndroid Build Coastguard Worker
1125*5e7646d2SAndroid Build Coastguard Worker if (!*ptr)
1126*5e7646d2SAndroid Build Coastguard Worker ptr --;
1127*5e7646d2SAndroid Build Coastguard Worker
1128*5e7646d2SAndroid Build Coastguard Worker continue;
1129*5e7646d2SAndroid Build Coastguard Worker }
1130*5e7646d2SAndroid Build Coastguard Worker else if (!isalnum(*ptr & 255))
1131*5e7646d2SAndroid Build Coastguard Worker continue;
1132*5e7646d2SAndroid Build Coastguard Worker
1133*5e7646d2SAndroid Build Coastguard Worker /*
1134*5e7646d2SAndroid Build Coastguard Worker * Found the start of a word, search until we find the end...
1135*5e7646d2SAndroid Build Coastguard Worker */
1136*5e7646d2SAndroid Build Coastguard Worker
1137*5e7646d2SAndroid Build Coastguard Worker for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++);
1138*5e7646d2SAndroid Build Coastguard Worker
1139*5e7646d2SAndroid Build Coastguard Worker wordlen = (int)(ptr - text);
1140*5e7646d2SAndroid Build Coastguard Worker
1141*5e7646d2SAndroid Build Coastguard Worker memcpy(temp, text, (size_t)wordlen);
1142*5e7646d2SAndroid Build Coastguard Worker temp[wordlen] = '\0';
1143*5e7646d2SAndroid Build Coastguard Worker
1144*5e7646d2SAndroid Build Coastguard Worker ptr --;
1145*5e7646d2SAndroid Build Coastguard Worker
1146*5e7646d2SAndroid Build Coastguard Worker if (wordlen > 1 && !bsearch(temp, help_common_words,
1147*5e7646d2SAndroid Build Coastguard Worker (sizeof(help_common_words) /
1148*5e7646d2SAndroid Build Coastguard Worker sizeof(help_common_words[0])),
1149*5e7646d2SAndroid Build Coastguard Worker sizeof(help_common_words[0]),
1150*5e7646d2SAndroid Build Coastguard Worker (int (*)(const void *, const void *))
1151*5e7646d2SAndroid Build Coastguard Worker _cups_strcasecmp))
1152*5e7646d2SAndroid Build Coastguard Worker help_add_word(node, temp);
1153*5e7646d2SAndroid Build Coastguard Worker }
1154*5e7646d2SAndroid Build Coastguard Worker }
1155*5e7646d2SAndroid Build Coastguard Worker
1156*5e7646d2SAndroid Build Coastguard Worker /*
1157*5e7646d2SAndroid Build Coastguard Worker * Get the offset of the next line...
1158*5e7646d2SAndroid Build Coastguard Worker */
1159*5e7646d2SAndroid Build Coastguard Worker
1160*5e7646d2SAndroid Build Coastguard Worker offset = cupsFileTell(fp);
1161*5e7646d2SAndroid Build Coastguard Worker }
1162*5e7646d2SAndroid Build Coastguard Worker
1163*5e7646d2SAndroid Build Coastguard Worker cupsFileClose(fp);
1164*5e7646d2SAndroid Build Coastguard Worker
1165*5e7646d2SAndroid Build Coastguard Worker if (node)
1166*5e7646d2SAndroid Build Coastguard Worker node->length = (size_t)(offset - node->offset);
1167*5e7646d2SAndroid Build Coastguard Worker
1168*5e7646d2SAndroid Build Coastguard Worker return (0);
1169*5e7646d2SAndroid Build Coastguard Worker }
1170*5e7646d2SAndroid Build Coastguard Worker
1171*5e7646d2SAndroid Build Coastguard Worker
1172*5e7646d2SAndroid Build Coastguard Worker /*
1173*5e7646d2SAndroid Build Coastguard Worker * 'help_new_node()' - Create a new node and add it to an index.
1174*5e7646d2SAndroid Build Coastguard Worker */
1175*5e7646d2SAndroid Build Coastguard Worker
1176*5e7646d2SAndroid Build Coastguard Worker static help_node_t * /* O - Node pointer or NULL on error */
help_new_node(const char * filename,const char * anchor,const char * section,const char * text,time_t mtime,off_t offset,size_t length)1177*5e7646d2SAndroid Build Coastguard Worker help_new_node(const char *filename, /* I - Filename */
1178*5e7646d2SAndroid Build Coastguard Worker const char *anchor, /* I - Anchor */
1179*5e7646d2SAndroid Build Coastguard Worker const char *section, /* I - Section */
1180*5e7646d2SAndroid Build Coastguard Worker const char *text, /* I - Text */
1181*5e7646d2SAndroid Build Coastguard Worker time_t mtime, /* I - Modification time */
1182*5e7646d2SAndroid Build Coastguard Worker off_t offset, /* I - Offset in file */
1183*5e7646d2SAndroid Build Coastguard Worker size_t length) /* I - Length in bytes */
1184*5e7646d2SAndroid Build Coastguard Worker {
1185*5e7646d2SAndroid Build Coastguard Worker help_node_t *n; /* Node */
1186*5e7646d2SAndroid Build Coastguard Worker
1187*5e7646d2SAndroid Build Coastguard Worker
1188*5e7646d2SAndroid Build Coastguard Worker n = (help_node_t *)calloc(1, sizeof(help_node_t));
1189*5e7646d2SAndroid Build Coastguard Worker if (!n)
1190*5e7646d2SAndroid Build Coastguard Worker return (NULL);
1191*5e7646d2SAndroid Build Coastguard Worker
1192*5e7646d2SAndroid Build Coastguard Worker n->filename = strdup(filename);
1193*5e7646d2SAndroid Build Coastguard Worker n->anchor = anchor ? strdup(anchor) : NULL;
1194*5e7646d2SAndroid Build Coastguard Worker n->section = (section && *section) ? strdup(section) : NULL;
1195*5e7646d2SAndroid Build Coastguard Worker n->text = strdup(text);
1196*5e7646d2SAndroid Build Coastguard Worker n->mtime = mtime;
1197*5e7646d2SAndroid Build Coastguard Worker n->offset = offset;
1198*5e7646d2SAndroid Build Coastguard Worker n->length = length;
1199*5e7646d2SAndroid Build Coastguard Worker
1200*5e7646d2SAndroid Build Coastguard Worker return (n);
1201*5e7646d2SAndroid Build Coastguard Worker }
1202*5e7646d2SAndroid Build Coastguard Worker
1203*5e7646d2SAndroid Build Coastguard Worker
1204*5e7646d2SAndroid Build Coastguard Worker /*
1205*5e7646d2SAndroid Build Coastguard Worker * 'help_sort_nodes_by_name()' - Sort nodes by section, filename, and anchor.
1206*5e7646d2SAndroid Build Coastguard Worker */
1207*5e7646d2SAndroid Build Coastguard Worker
1208*5e7646d2SAndroid Build Coastguard Worker static int /* O - Difference */
help_sort_by_name(help_node_t * n1,help_node_t * n2)1209*5e7646d2SAndroid Build Coastguard Worker help_sort_by_name(help_node_t *n1, /* I - First node */
1210*5e7646d2SAndroid Build Coastguard Worker help_node_t *n2) /* I - Second node */
1211*5e7646d2SAndroid Build Coastguard Worker {
1212*5e7646d2SAndroid Build Coastguard Worker int diff; /* Difference */
1213*5e7646d2SAndroid Build Coastguard Worker
1214*5e7646d2SAndroid Build Coastguard Worker
1215*5e7646d2SAndroid Build Coastguard Worker if ((diff = strcmp(n1->filename, n2->filename)) != 0)
1216*5e7646d2SAndroid Build Coastguard Worker return (diff);
1217*5e7646d2SAndroid Build Coastguard Worker
1218*5e7646d2SAndroid Build Coastguard Worker if (!n1->anchor && !n2->anchor)
1219*5e7646d2SAndroid Build Coastguard Worker return (0);
1220*5e7646d2SAndroid Build Coastguard Worker else if (!n1->anchor)
1221*5e7646d2SAndroid Build Coastguard Worker return (-1);
1222*5e7646d2SAndroid Build Coastguard Worker else if (!n2->anchor)
1223*5e7646d2SAndroid Build Coastguard Worker return (1);
1224*5e7646d2SAndroid Build Coastguard Worker else
1225*5e7646d2SAndroid Build Coastguard Worker return (strcmp(n1->anchor, n2->anchor));
1226*5e7646d2SAndroid Build Coastguard Worker }
1227*5e7646d2SAndroid Build Coastguard Worker
1228*5e7646d2SAndroid Build Coastguard Worker
1229*5e7646d2SAndroid Build Coastguard Worker /*
1230*5e7646d2SAndroid Build Coastguard Worker * 'help_sort_nodes_by_score()' - Sort nodes by score and text.
1231*5e7646d2SAndroid Build Coastguard Worker */
1232*5e7646d2SAndroid Build Coastguard Worker
1233*5e7646d2SAndroid Build Coastguard Worker static int /* O - Difference */
help_sort_by_score(help_node_t * n1,help_node_t * n2)1234*5e7646d2SAndroid Build Coastguard Worker help_sort_by_score(help_node_t *n1, /* I - First node */
1235*5e7646d2SAndroid Build Coastguard Worker help_node_t *n2) /* I - Second node */
1236*5e7646d2SAndroid Build Coastguard Worker {
1237*5e7646d2SAndroid Build Coastguard Worker int diff; /* Difference */
1238*5e7646d2SAndroid Build Coastguard Worker
1239*5e7646d2SAndroid Build Coastguard Worker
1240*5e7646d2SAndroid Build Coastguard Worker if (n1->score != n2->score)
1241*5e7646d2SAndroid Build Coastguard Worker return (n2->score - n1->score);
1242*5e7646d2SAndroid Build Coastguard Worker
1243*5e7646d2SAndroid Build Coastguard Worker if (n1->section && !n2->section)
1244*5e7646d2SAndroid Build Coastguard Worker return (1);
1245*5e7646d2SAndroid Build Coastguard Worker else if (!n1->section && n2->section)
1246*5e7646d2SAndroid Build Coastguard Worker return (-1);
1247*5e7646d2SAndroid Build Coastguard Worker else if (n1->section && n2->section &&
1248*5e7646d2SAndroid Build Coastguard Worker (diff = strcmp(n1->section, n2->section)) != 0)
1249*5e7646d2SAndroid Build Coastguard Worker return (diff);
1250*5e7646d2SAndroid Build Coastguard Worker
1251*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(n1->text, n2->text));
1252*5e7646d2SAndroid Build Coastguard Worker }
1253*5e7646d2SAndroid Build Coastguard Worker
1254*5e7646d2SAndroid Build Coastguard Worker
1255*5e7646d2SAndroid Build Coastguard Worker /*
1256*5e7646d2SAndroid Build Coastguard Worker * 'help_sort_words()' - Sort words alphabetically.
1257*5e7646d2SAndroid Build Coastguard Worker */
1258*5e7646d2SAndroid Build Coastguard Worker
1259*5e7646d2SAndroid Build Coastguard Worker static int /* O - Difference */
help_sort_words(help_word_t * w1,help_word_t * w2)1260*5e7646d2SAndroid Build Coastguard Worker help_sort_words(help_word_t *w1, /* I - Second word */
1261*5e7646d2SAndroid Build Coastguard Worker help_word_t *w2) /* I - Second word */
1262*5e7646d2SAndroid Build Coastguard Worker {
1263*5e7646d2SAndroid Build Coastguard Worker return (_cups_strcasecmp(w1->text, w2->text));
1264*5e7646d2SAndroid Build Coastguard Worker }
1265