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