]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
503b54c9 | 2 | * Online help CGI for CUPS. |
ef416fc2 | 3 | * |
503b54c9 MS |
4 | * Copyright 2007-2011 by Apple Inc. |
5 | * Copyright 1997-2006 by Easy Software Products. | |
ef416fc2 | 6 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 8 | */ |
9 | ||
10 | /* | |
11 | * Include necessary headers... | |
12 | */ | |
13 | ||
14 | #include "cgi-private.h" | |
15 | ||
16 | ||
17 | /* | |
18 | * 'main()' - Main entry for CGI. | |
19 | */ | |
20 | ||
21 | int /* O - Exit status */ | |
22 | main(int argc, /* I - Number of command-line arguments */ | |
23 | char *argv[]) /* I - Command-line arguments */ | |
24 | { | |
25 | help_index_t *hi, /* Help index */ | |
26 | *si; /* Search index */ | |
ecdc0628 | 27 | help_node_t *n; /* Current help node */ |
28 | int i; /* Looping var */ | |
ef416fc2 | 29 | const char *query; /* Search query */ |
ecdc0628 | 30 | const char *cache_dir; /* CUPS_CACHEDIR environment variable */ |
ef416fc2 | 31 | const char *docroot; /* CUPS_DOCROOT environment variable */ |
82cc1f9a MS |
32 | const char *helpfile, /* Current help file */ |
33 | *helptitle = NULL; /* Current help title */ | |
ef416fc2 | 34 | const char *topic; /* Current topic */ |
35 | char topic_data[1024]; /* Topic form data */ | |
36 | const char *section; /* Current section */ | |
37 | char filename[1024], /* Filename */ | |
38 | directory[1024]; /* Directory */ | |
39 | cups_file_t *fp; /* Help file */ | |
40 | char line[1024]; /* Line from file */ | |
4744bd90 | 41 | int printable; /* Show printable version? */ |
ef416fc2 | 42 | |
43 | ||
44 | /* | |
45 | * Get any form variables... | |
46 | */ | |
47 | ||
48 | cgiInitialize(); | |
49 | ||
4744bd90 | 50 | printable = cgiGetVariable("PRINTABLE") != NULL; |
51 | ||
ef416fc2 | 52 | /* |
53 | * Set the web interface section... | |
54 | */ | |
55 | ||
56 | cgiSetVariable("SECTION", "help"); | |
ef55b745 | 57 | cgiSetVariable("REFRESH_PAGE", ""); |
ef416fc2 | 58 | |
59 | /* | |
60 | * Load the help index... | |
61 | */ | |
62 | ||
ecdc0628 | 63 | if ((cache_dir = getenv("CUPS_CACHEDIR")) == NULL) |
64 | cache_dir = CUPS_CACHEDIR; | |
ef416fc2 | 65 | |
ecdc0628 | 66 | snprintf(filename, sizeof(filename), "%s/help.index", cache_dir); |
ef416fc2 | 67 | |
68 | if ((docroot = getenv("CUPS_DOCROOT")) == NULL) | |
69 | docroot = CUPS_DOCROOT; | |
70 | ||
71 | snprintf(directory, sizeof(directory), "%s/help", docroot); | |
72 | ||
73 | fprintf(stderr, "DEBUG: helpLoadIndex(filename=\"%s\", directory=\"%s\")\n", | |
74 | filename, directory); | |
75 | ||
76 | hi = helpLoadIndex(filename, directory); | |
77 | if (!hi) | |
78 | { | |
79 | perror(filename); | |
80 | ||
2e4ff8af | 81 | cgiStartHTML(cgiText(_("Online Help"))); |
82cc1f9a | 82 | cgiSetVariable("ERROR", cgiText(_("Unable to load help index."))); |
ef416fc2 | 83 | cgiCopyTemplateLang("error.tmpl"); |
84 | cgiEndHTML(); | |
85 | ||
86 | return (1); | |
87 | } | |
88 | ||
ecdc0628 | 89 | fprintf(stderr, "DEBUG: %d nodes in help index...\n", |
90 | cupsArrayCount(hi->nodes)); | |
ef416fc2 | 91 | |
92 | /* | |
93 | * See if we are viewing a file... | |
94 | */ | |
95 | ||
96 | for (i = 0; i < argc; i ++) | |
ef55b745 | 97 | fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); |
ef416fc2 | 98 | |
99 | if ((helpfile = getenv("PATH_INFO")) != NULL) | |
b423cd4c | 100 | { |
ef416fc2 | 101 | helpfile ++; |
b423cd4c | 102 | |
103 | if (!*helpfile) | |
104 | helpfile = NULL; | |
105 | } | |
ef416fc2 | 106 | |
107 | if (helpfile) | |
108 | { | |
109 | /* | |
110 | * Verify that the help file exists and is part of the index... | |
111 | */ | |
112 | ||
113 | snprintf(filename, sizeof(filename), "%s/help/%s", docroot, helpfile); | |
114 | ||
115 | fprintf(stderr, "DEBUG: helpfile=\"%s\", filename=\"%s\"\n", | |
116 | helpfile, filename); | |
117 | ||
118 | if (access(filename, R_OK)) | |
119 | { | |
120 | perror(filename); | |
121 | ||
2e4ff8af | 122 | cgiStartHTML(cgiText(_("Online Help"))); |
82cc1f9a | 123 | cgiSetVariable("ERROR", cgiText(_("Unable to access help file."))); |
ef416fc2 | 124 | cgiCopyTemplateLang("error.tmpl"); |
125 | cgiEndHTML(); | |
126 | ||
127 | return (1); | |
128 | } | |
129 | ||
130 | if ((n = helpFindNode(hi, helpfile, NULL)) == NULL) | |
131 | { | |
2e4ff8af | 132 | cgiStartHTML(cgiText(_("Online Help"))); |
82cc1f9a | 133 | cgiSetVariable("ERROR", cgiText(_("Help file not in index."))); |
ef416fc2 | 134 | cgiCopyTemplateLang("error.tmpl"); |
135 | cgiEndHTML(); | |
136 | ||
137 | return (1); | |
138 | } | |
139 | ||
140 | /* | |
82cc1f9a | 141 | * Save the page title and help file... |
ef416fc2 | 142 | */ |
143 | ||
82cc1f9a MS |
144 | helptitle = n->text; |
145 | topic = n->section; | |
ef416fc2 | 146 | |
147 | /* | |
148 | * Send a standard page header... | |
149 | */ | |
150 | ||
4744bd90 | 151 | if (printable) |
152 | puts("Content-Type: text/html;charset=utf-8\n"); | |
153 | else | |
154 | cgiStartHTML(n->text); | |
ef416fc2 | 155 | } |
156 | else | |
157 | { | |
158 | /* | |
159 | * Send a standard page header... | |
160 | */ | |
161 | ||
2e4ff8af | 162 | cgiStartHTML(cgiText(_("Online Help"))); |
82cc1f9a MS |
163 | |
164 | topic = cgiGetVariable("TOPIC"); | |
ef416fc2 | 165 | } |
166 | ||
167 | /* | |
168 | * Do a search as needed... | |
169 | */ | |
170 | ||
2e4ff8af MS |
171 | if (cgiGetVariable("CLEAR")) |
172 | cgiSetVariable("QUERY", ""); | |
173 | ||
ef416fc2 | 174 | query = cgiGetVariable("QUERY"); |
ef416fc2 | 175 | si = helpSearchIndex(hi, query, topic, helpfile); |
176 | ||
ef55b745 MS |
177 | cgiClearVariables(); |
178 | if (query) | |
179 | cgiSetVariable("QUERY", query); | |
180 | if (topic) | |
181 | cgiSetVariable("TOPIC", topic); | |
82cc1f9a MS |
182 | if (helpfile) |
183 | cgiSetVariable("HELPFILE", helpfile); | |
184 | if (helptitle) | |
185 | cgiSetVariable("HELPTITLE", helptitle); | |
ef55b745 | 186 | |
f301802f | 187 | fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n", |
188 | query ? query : "(null)", topic ? topic : "(null)"); | |
b423cd4c | 189 | |
ef416fc2 | 190 | if (si) |
191 | { | |
ecdc0628 | 192 | help_node_t *nn; /* Parent node */ |
ef416fc2 | 193 | |
194 | ||
ecdc0628 | 195 | fprintf(stderr, |
196 | "DEBUG: si=%p, si->sorted=%p, cupsArrayCount(si->sorted)=%d\n", si, | |
197 | si->sorted, cupsArrayCount(si->sorted)); | |
ef416fc2 | 198 | |
b423cd4c | 199 | for (i = 0, n = (help_node_t *)cupsArrayFirst(si->sorted); |
ecdc0628 | 200 | n; |
b423cd4c | 201 | i ++, n = (help_node_t *)cupsArrayNext(si->sorted)) |
ef416fc2 | 202 | { |
ecdc0628 | 203 | if (helpfile && n->anchor) |
204 | snprintf(line, sizeof(line), "#%s", n->anchor); | |
205 | else if (n->anchor) | |
206 | snprintf(line, sizeof(line), "/help/%s?QUERY=%s#%s", n->filename, | |
207 | query ? query : "", n->anchor); | |
ef416fc2 | 208 | else |
ecdc0628 | 209 | snprintf(line, sizeof(line), "/help/%s?QUERY=%s", n->filename, |
ef416fc2 | 210 | query ? query : ""); |
211 | ||
ecdc0628 | 212 | cgiSetArray("QTEXT", i, n->text); |
ef416fc2 | 213 | cgiSetArray("QLINK", i, line); |
214 | ||
ecdc0628 | 215 | if (!helpfile && n->anchor) |
ef416fc2 | 216 | { |
ecdc0628 | 217 | nn = helpFindNode(hi, n->filename, NULL); |
ef416fc2 | 218 | |
ecdc0628 | 219 | snprintf(line, sizeof(line), "/help/%s?QUERY=%s", nn->filename, |
ef416fc2 | 220 | query ? query : ""); |
221 | ||
ecdc0628 | 222 | cgiSetArray("QPTEXT", i, nn->text); |
ef416fc2 | 223 | cgiSetArray("QPLINK", i, line); |
224 | } | |
225 | else | |
226 | { | |
227 | cgiSetArray("QPTEXT", i, ""); | |
228 | cgiSetArray("QPLINK", i, ""); | |
229 | } | |
230 | ||
ecdc0628 | 231 | fprintf(stderr, "DEBUG: [%d] = \"%s\" @ \"%s\"\n", i, n->text, line); |
ef416fc2 | 232 | } |
233 | ||
234 | helpDeleteIndex(si); | |
235 | } | |
236 | ||
237 | /* | |
238 | * OK, now list the bookmarks within the index... | |
239 | */ | |
240 | ||
ecdc0628 | 241 | for (i = 0, section = NULL, n = (help_node_t *)cupsArrayFirst(hi->sorted); |
242 | n; | |
243 | n = (help_node_t *)cupsArrayNext(hi->sorted)) | |
ef416fc2 | 244 | { |
ecdc0628 | 245 | if (n->anchor) |
ef416fc2 | 246 | continue; |
247 | ||
248 | /* | |
249 | * Add a section link as needed... | |
250 | */ | |
251 | ||
ecdc0628 | 252 | if (n->section && |
253 | (!section || strcmp(n->section, section))) | |
ef416fc2 | 254 | { |
255 | /* | |
256 | * Add a link for this node... | |
257 | */ | |
258 | ||
259 | snprintf(line, sizeof(line), "/help/?TOPIC=%s&QUERY=%s", | |
ecdc0628 | 260 | cgiFormEncode(topic_data, n->section, sizeof(topic_data)), |
ef416fc2 | 261 | query ? query : ""); |
ecdc0628 | 262 | cgiSetArray("BMLINK", i, line); |
263 | cgiSetArray("BMTEXT", i, n->section); | |
264 | cgiSetArray("BMINDENT", i, "0"); | |
ef416fc2 | 265 | |
ecdc0628 | 266 | i ++; |
267 | section = n->section; | |
ef416fc2 | 268 | } |
269 | ||
7f500d89 | 270 | if (!topic || !n->section || strcmp(n->section, topic)) |
ef416fc2 | 271 | continue; |
272 | ||
273 | /* | |
274 | * Add a link for this node... | |
275 | */ | |
276 | ||
ecdc0628 | 277 | snprintf(line, sizeof(line), "/help/%s?TOPIC=%s&QUERY=%s", n->filename, |
278 | cgiFormEncode(topic_data, n->section, sizeof(topic_data)), | |
ef416fc2 | 279 | query ? query : ""); |
ecdc0628 | 280 | cgiSetArray("BMLINK", i, line); |
281 | cgiSetArray("BMTEXT", i, n->text); | |
282 | cgiSetArray("BMINDENT", i, "1"); | |
ef416fc2 | 283 | |
ecdc0628 | 284 | i ++; |
ef416fc2 | 285 | |
ecdc0628 | 286 | if (helpfile && !strcmp(helpfile, n->filename)) |
ef416fc2 | 287 | { |
ecdc0628 | 288 | help_node_t *nn; /* Pointer to sub-node */ |
ef416fc2 | 289 | |
290 | ||
ecdc0628 | 291 | cupsArraySave(hi->sorted); |
292 | ||
293 | for (nn = (help_node_t *)cupsArrayFirst(hi->sorted); | |
294 | nn; | |
295 | nn = (help_node_t *)cupsArrayNext(hi->sorted)) | |
296 | if (nn->anchor && !strcmp(helpfile, nn->filename)) | |
ef416fc2 | 297 | { |
298 | /* | |
299 | * Add a link for this node... | |
300 | */ | |
301 | ||
ecdc0628 | 302 | snprintf(line, sizeof(line), "#%s", nn->anchor); |
303 | cgiSetArray("BMLINK", i, line); | |
304 | cgiSetArray("BMTEXT", i, nn->text); | |
305 | cgiSetArray("BMINDENT", i, "2"); | |
ef416fc2 | 306 | |
ecdc0628 | 307 | i ++; |
ef416fc2 | 308 | } |
ecdc0628 | 309 | |
310 | cupsArrayRestore(hi->sorted); | |
ef416fc2 | 311 | } |
312 | } | |
313 | ||
314 | /* | |
315 | * Show the search and bookmark content... | |
316 | */ | |
317 | ||
4744bd90 | 318 | if (!helpfile || !printable) |
319 | cgiCopyTemplateLang("help-header.tmpl"); | |
320 | else | |
321 | cgiCopyTemplateLang("help-printable.tmpl"); | |
ef416fc2 | 322 | |
323 | /* | |
324 | * If we are viewing a file, copy it in now... | |
325 | */ | |
326 | ||
327 | if (helpfile) | |
328 | { | |
329 | if ((fp = cupsFileOpen(filename, "r")) != NULL) | |
330 | { | |
331 | int inbody; /* Are we inside the body? */ | |
5e1c3dff | 332 | char *lineptr; /* Pointer into line */ |
ef416fc2 | 333 | |
334 | inbody = 0; | |
335 | ||
336 | while (cupsFileGets(fp, line, sizeof(line))) | |
337 | { | |
5e1c3dff MS |
338 | for (lineptr = line; *lineptr && isspace(*lineptr & 255); lineptr ++); |
339 | ||
ef416fc2 | 340 | if (inbody) |
341 | { | |
5e1c3dff | 342 | if (!_cups_strncasecmp(lineptr, "</BODY>", 7)) |
ef416fc2 | 343 | break; |
344 | ||
345 | printf("%s\n", line); | |
346 | } | |
5e1c3dff | 347 | else if (!_cups_strncasecmp(lineptr, "<BODY", 5)) |
ef416fc2 | 348 | inbody = 1; |
349 | } | |
350 | ||
351 | cupsFileClose(fp); | |
352 | } | |
353 | else | |
354 | { | |
355 | perror(filename); | |
82cc1f9a | 356 | cgiSetVariable("ERROR", cgiText(_("Unable to open help file."))); |
ef416fc2 | 357 | cgiCopyTemplateLang("error.tmpl"); |
358 | } | |
359 | } | |
360 | ||
361 | /* | |
362 | * Send a standard trailer... | |
363 | */ | |
364 | ||
4744bd90 | 365 | if (!printable) |
b19ccc9e MS |
366 | { |
367 | cgiCopyTemplateLang("help-trailer.tmpl"); | |
4744bd90 | 368 | cgiEndHTML(); |
b19ccc9e | 369 | } |
4744bd90 | 370 | else |
371 | puts("</BODY>\n</HTML>"); | |
ef416fc2 | 372 | |
373 | /* | |
374 | * Delete the index... | |
375 | */ | |
376 | ||
377 | helpDeleteIndex(hi); | |
378 | ||
379 | /* | |
380 | * Return with no errors... | |
381 | */ | |
382 | ||
383 | return (0); | |
384 | } |