• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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