1 /*
2  * Online help CGI for CUPS.
3  *
4  * Copyright 2007-2011 by Apple Inc.
5  * Copyright 1997-2006 by Easy Software Products.
6  *
7  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
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 */
main(int argc,char * argv[])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 */
27   help_node_t	*n;			/* Current help node */
28   int		i;			/* Looping var */
29   const char	*query;			/* Search query */
30   const char	*cache_dir;		/* CUPS_CACHEDIR environment variable */
31   const char	*docroot;		/* CUPS_DOCROOT environment variable */
32   const char	*helpfile,		/* Current help file */
33 		*helptitle = NULL;	/* Current help title */
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 */
41   int		printable;		/* Show printable version? */
42 
43 
44  /*
45   * Get any form variables...
46   */
47 
48   cgiInitialize();
49 
50   printable = cgiGetVariable("PRINTABLE") != NULL;
51 
52  /*
53   * Set the web interface section...
54   */
55 
56   cgiSetVariable("SECTION", "help");
57   cgiSetVariable("REFRESH_PAGE", "");
58 
59  /*
60   * Load the help index...
61   */
62 
63   if ((cache_dir = getenv("CUPS_CACHEDIR")) == NULL)
64     cache_dir = CUPS_CACHEDIR;
65 
66   snprintf(filename, sizeof(filename), "%s/help.index", cache_dir);
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 
81     cgiStartHTML(cgiText(_("Online Help")));
82     cgiSetVariable("ERROR", cgiText(_("Unable to load help index.")));
83     cgiCopyTemplateLang("error.tmpl");
84     cgiEndHTML();
85 
86     return (1);
87   }
88 
89   fprintf(stderr, "DEBUG: %d nodes in help index...\n",
90           cupsArrayCount(hi->nodes));
91 
92  /*
93   * See if we are viewing a file...
94   */
95 
96   for (i = 0; i < argc; i ++)
97     fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
98 
99   if ((helpfile = getenv("PATH_INFO")) != NULL)
100   {
101     helpfile ++;
102 
103     if (!*helpfile)
104       helpfile = NULL;
105   }
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 
122       cgiStartHTML(cgiText(_("Online Help")));
123       cgiSetVariable("ERROR", cgiText(_("Unable to access help file.")));
124       cgiCopyTemplateLang("error.tmpl");
125       cgiEndHTML();
126 
127       return (1);
128     }
129 
130     if ((n = helpFindNode(hi, helpfile, NULL)) == NULL)
131     {
132       cgiStartHTML(cgiText(_("Online Help")));
133       cgiSetVariable("ERROR", cgiText(_("Help file not in index.")));
134       cgiCopyTemplateLang("error.tmpl");
135       cgiEndHTML();
136 
137       return (1);
138     }
139 
140    /*
141     * Save the page title and help file...
142     */
143 
144     helptitle = n->text;
145     topic     = n->section;
146 
147    /*
148     * Send a standard page header...
149     */
150 
151     if (printable)
152       puts("Content-Type: text/html;charset=utf-8\n");
153     else
154       cgiStartHTML(n->text);
155   }
156   else
157   {
158    /*
159     * Send a standard page header...
160     */
161 
162     cgiStartHTML(cgiText(_("Online Help")));
163 
164     topic = cgiGetVariable("TOPIC");
165   }
166 
167  /*
168   * Do a search as needed...
169   */
170 
171   if (cgiGetVariable("CLEAR"))
172     cgiSetVariable("QUERY", "");
173 
174   query = cgiGetVariable("QUERY");
175   si    = helpSearchIndex(hi, query, topic, helpfile);
176 
177   cgiClearVariables();
178   if (query)
179     cgiSetVariable("QUERY", query);
180   if (topic)
181     cgiSetVariable("TOPIC", topic);
182   if (helpfile)
183     cgiSetVariable("HELPFILE", helpfile);
184   if (helptitle)
185     cgiSetVariable("HELPTITLE", helptitle);
186 
187   fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n",
188           query ? query : "(null)", topic ? topic : "(null)");
189 
190   if (si)
191   {
192     help_node_t	*nn;			/* Parent node */
193 
194 
195     fprintf(stderr,
196             "DEBUG: si=%p, si->sorted=%p, cupsArrayCount(si->sorted)=%d\n", si,
197             si->sorted, cupsArrayCount(si->sorted));
198 
199     for (i = 0, n = (help_node_t *)cupsArrayFirst(si->sorted);
200          n;
201 	 i ++, n = (help_node_t *)cupsArrayNext(si->sorted))
202     {
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);
208       else
209         snprintf(line, sizeof(line), "/help/%s?QUERY=%s", n->filename,
210 	         query ? query : "");
211 
212       cgiSetArray("QTEXT", i, n->text);
213       cgiSetArray("QLINK", i, line);
214 
215       if (!helpfile && n->anchor)
216       {
217         nn = helpFindNode(hi, n->filename, NULL);
218 
219         snprintf(line, sizeof(line), "/help/%s?QUERY=%s", nn->filename,
220 	         query ? query : "");
221 
222         cgiSetArray("QPTEXT", i, nn->text);
223 	cgiSetArray("QPLINK", i, line);
224       }
225       else
226       {
227         cgiSetArray("QPTEXT", i, "");
228 	cgiSetArray("QPLINK", i, "");
229       }
230 
231       fprintf(stderr, "DEBUG: [%d] = \"%s\" @ \"%s\"\n", i, n->text, line);
232     }
233 
234     helpDeleteIndex(si);
235   }
236 
237  /*
238   * OK, now list the bookmarks within the index...
239   */
240 
241   for (i = 0, section = NULL, n = (help_node_t *)cupsArrayFirst(hi->sorted);
242        n;
243        n = (help_node_t *)cupsArrayNext(hi->sorted))
244   {
245     if (n->anchor)
246       continue;
247 
248    /*
249     * Add a section link as needed...
250     */
251 
252     if (n->section &&
253         (!section || strcmp(n->section, section)))
254     {
255      /*
256       * Add a link for this node...
257       */
258 
259       snprintf(line, sizeof(line), "/help/?TOPIC=%s&QUERY=%s",
260                cgiFormEncode(topic_data, n->section, sizeof(topic_data)),
261 	       query ? query : "");
262       cgiSetArray("BMLINK", i, line);
263       cgiSetArray("BMTEXT", i, n->section);
264       cgiSetArray("BMINDENT", i, "0");
265 
266       i ++;
267       section = n->section;
268     }
269 
270     if (!topic || !n->section || strcmp(n->section, topic))
271       continue;
272 
273    /*
274     * Add a link for this node...
275     */
276 
277     snprintf(line, sizeof(line), "/help/%s?TOPIC=%s&QUERY=%s", n->filename,
278              cgiFormEncode(topic_data, n->section, sizeof(topic_data)),
279 	     query ? query : "");
280     cgiSetArray("BMLINK", i, line);
281     cgiSetArray("BMTEXT", i, n->text);
282     cgiSetArray("BMINDENT", i, "1");
283 
284     i ++;
285 
286     if (helpfile && !strcmp(helpfile, n->filename))
287     {
288       help_node_t	*nn;		/* Pointer to sub-node */
289 
290 
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))
297 	{
298 	 /*
299 	  * Add a link for this node...
300 	  */
301 
302 	  snprintf(line, sizeof(line), "#%s", nn->anchor);
303 	  cgiSetArray("BMLINK", i, line);
304 	  cgiSetArray("BMTEXT", i, nn->text);
305 	  cgiSetArray("BMINDENT", i, "2");
306 
307 	  i ++;
308 	}
309 
310       cupsArrayRestore(hi->sorted);
311     }
312   }
313 
314  /*
315   * Show the search and bookmark content...
316   */
317 
318   if (!helpfile || !printable)
319     cgiCopyTemplateLang("help-header.tmpl");
320   else
321     cgiCopyTemplateLang("help-printable.tmpl");
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? */
332       char	*lineptr;		/* Pointer into line */
333 
334       inbody = 0;
335 
336       while (cupsFileGets(fp, line, sizeof(line)))
337       {
338         for (lineptr = line; *lineptr && isspace(*lineptr & 255); lineptr ++);
339 
340         if (inbody)
341 	{
342 	  if (!_cups_strncasecmp(lineptr, "</BODY>", 7))
343 	    break;
344 
345 	  printf("%s\n", line);
346         }
347 	else if (!_cups_strncasecmp(lineptr, "<BODY", 5))
348 	  inbody = 1;
349       }
350 
351       cupsFileClose(fp);
352     }
353     else
354     {
355       perror(filename);
356       cgiSetVariable("ERROR", cgiText(_("Unable to open help file.")));
357       cgiCopyTemplateLang("error.tmpl");
358     }
359   }
360 
361  /*
362   * Send a standard trailer...
363   */
364 
365   if (!printable)
366   {
367     cgiCopyTemplateLang("help-trailer.tmpl");
368     cgiEndHTML();
369   }
370   else
371     puts("</BODY>\n</HTML>");
372 
373  /*
374   * Delete the index...
375   */
376 
377   helpDeleteIndex(hi);
378 
379  /*
380   * Return with no errors...
381   */
382 
383   return (0);
384 }
385