1 /*
2 * $Id: output.c,v 1.80.4.39 2008-07-19 17:56:42 opengl2772 Exp $
3 *
4 * Copyright (C) 1997-1999 Satoru Takabayashi All rights reserved.
5 * Copyright (C) 2000-2008 Namazu Project All rights reserved.
6 * This is free software with ABSOLUTELY NO WARRANTY.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 * 02111-1307, USA
22 *
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29 #ifdef HAVE_SUPPORT_H
30 # include "support.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <stdarg.h>
37
38 #ifdef HAVE_ERRNO_H
39 # include <errno.h>
40 #endif
41
42 #ifdef HAVE_STRING_H
43 # include <string.h>
44 #else
45 # include <strings.h>
46 #endif
47
48 #include "namazu.h"
49 #include "libnamazu.h"
50 #include "codeconv.h"
51 #include "output.h"
52 #include "util.h"
53 #include "field.h"
54 #include "search.h"
55 #include "result.h"
56 #include "i18n.h"
57 #include "message.h"
58 #include "form.h"
59 #include "var.h"
60 #include "idxname.h"
61 #include "query.h"
62 #include "system.h"
63 #include "charset.h"
64
65 static int htmlmode = 0;
66 static int cgimode = 0;
67 static int quietmode = 0;
68
69 static int countmode = 0; /* like grep -c */
70 static int listmode = 0; /* like grep -l */
71
72 static int allresult = 0; /* print all results */
73 static int pageindex = 0; /* print "Page: [1][2][3][4][5][6][7][8]" */
74 static int formprint = 0; /* print "<form> ... </form>" at cgimode */
75 static int refprint = 0; /* print "References: [ foo: 123 ]" */
76
77 static int maxresult = 20; /* max number of search results */
78 static int listwhence = 0; /* number which beginning of search results */
79
80 static char template_suffix[BUFSIZE] = "normal"; /* suffix of NMZ.result.* */
81
82 /*
83 * They are used for emphasizing keywords in html results.
84 */
85 static char emphasis_start_tag[BUFSIZE] = "<strong class=\"keyword\">";
86 static char emphasis_end_tag[BUFSIZE] = "</strong>";
87 static char contenttype[BUFSIZE] = "text/html";
88
89 /*
90 * Extern variables.
91 */
92
93 extern NMZ_HANDLE handle_charset;
94
95 /*
96 *
97 * Private functions
98 *
99 */
100
101 static void emprint( char *s, int entity_encode );
102 static void unhtml_buffer( char *ostr );
103 static void fputs_without_html_tag ( const char *str, FILE *fp );
104 static char *load_nmz_result(const char *basedir);
105 static void print_hitnum_each ( struct nmz_hitnumlist *hn );
106 static int is_allresult ( void );
107 static int is_pageindex ( void );
108 static int is_countmode ( void );
109 static int is_listmode ( void );
110 static int is_quietmode ( void );
111 static int is_refprint ( void );
112 static int is_cgimode ( void );
113 static enum nmz_stat print_hlist ( NmzResult hlist );
114 static enum nmz_stat print_listing ( NmzResult hlist );
115 static void print_query ( const char * qs, int w );
116 static void print_page_index ( int n );
117 static void print_current_range ( int listmax );
118 static void print_hitnum_all_idx ( void );
119 static void print_hitnum ( int n );
120 static void print_msgfile ( const char *fname );
121 static void print_range ( NmzResult hlist );
122 static void print_errmsg(int errid);
123
124 /*
125 * Print s to stdout with processing for emphasizing keyword
126 * and entity encoding.
127 */
128 static void
emprint(char * s,int entity_encode)129 emprint(char *s, int entity_encode)
130 {
131 int i;
132 int nestedtags = 0;
133 for (i = 0; i < BUFSIZE * 16 && *s; s++) {
134 if (*s == EM_START_MARK) {
135 nestedtags++;
136 fputs(emphasis_start_tag, stdout);
137 continue;
138 } else if (*s == EM_END_MARK) {
139 if (nestedtags > 0) nestedtags--;
140 fputs(emphasis_end_tag, stdout);
141 continue;
142 }
143 if (entity_encode) {
144 /* < > & " are converted to entities like < */
145 if (*s == '<') {
146 fputs("<", stdout);
147 } else if (*s == '>') {
148 fputs(">", stdout);
149 } else if (*s == '&') {
150 fputs("&", stdout);
151 } else if (*s == '"') {
152 fputs(""", stdout);
153 } else if (*s == '\'') {
154 fputs("'", stdout);
155 } else if (*s == '(') {
156 fputs("(", stdout);
157 } else if (*s == ')') {
158 fputs(")", stdout);
159 } else {
160 fputc(*s, stdout);
161 }
162 } else {
163 fputc(*s, stdout);
164 }
165 }
166 for (; nestedtags > 0; nestedtags--) {
167 fputs(emphasis_end_tag, stdout);
168 }
169 }
170
171 /*
172 * Output string without HTML elements
173 */
174 static void
unhtml_buffer(char * ostr)175 unhtml_buffer(char *ostr) {
176 int f;
177 size_t i;
178 char buf[BUFSIZE] = "", *str;
179 size_t len;
180 len = strlen(ostr) + 1;
181 str = ostr;
182 for (f = 0, i = 0; i < BUFSIZE && *str; str++) {
183
184 /* Iso-2022-jp handling */
185 if ((strncmp(str, "\033$", 2) == 0)
186 && (*(str + 2) == 'B' || *(str + 2) == '@'))
187 {
188 char *p;
189
190 strncpy(buf + i, str, 3);
191 i += 3;
192 str += 3;
193 p = strstr(str, "\033(");
194 if (p == NULL) { /* non-terminating jis x 0208 */
195 strcpy(buf + i, str);
196 return;
197 }
198 if (*(p + 2) == 'J' || *(p + 2) == 'B' || *(p + 2) == 'H') {
199 size_t len = p - str + 3;
200 strncpy(buf + i, str, len);
201 i += len;
202 str += len;
203 } else { /* unknown charset designation */
204 strcpy(buf + i, str);
205 return;
206 }
207 }
208
209 if (strncasecmp(str, "<br>", 4) == 0 && *(str + 4) != '\n') {
210 buf[i++] = '\n';
211 str += 3;
212 continue;
213 } else if (strncasecmp(str, "<br />", 6) == 0 && *(str + 6) != '\n') {
214 buf[i++] = '\n';
215 str += 5;
216 continue;
217 }
218 if (*str == '<') {
219 f = 1;
220 continue;
221 }
222 if (*str == '>') {
223 f = 0;
224 continue;
225 }
226 if (f == 0) {
227 if (strncmp(str, "<", strlen("<")) == 0) {
228 buf[i++] = '<';
229 str += 3;
230 } else if (strncmp(str, ">", strlen(">")) == 0) {
231 buf[i++] = '>';
232 str += 3;
233 } else if (strncmp(str, "&", strlen("&")) == 0) {
234 buf[i++] = '&';
235 str += 4;
236 } else if (strncmp(str, """, strlen(""")) == 0) {
237 buf[i++] = '"';
238 str += 5;
239 } else {
240 buf[i++] = *str;
241 }
242 }
243 }
244 buf[i] = '\0';
245 strncpy(ostr, buf, len);
246 ostr[len - 1] = '\0';
247 }
248
249 static void
fputs_without_html_tag(const char * str,FILE * fp)250 fputs_without_html_tag(const char *str, FILE *fp)
251 {
252 char buf[BUFSIZE] = "";
253 strncpy(buf, str, BUFSIZE - 1);
254 unhtml_buffer(buf);
255 fputs(buf, fp);
256 }
257
258 static void
print_hitnum_each(struct nmz_hitnumlist * hn)259 print_hitnum_each (struct nmz_hitnumlist *hn)
260 {
261 struct nmz_hitnumlist *hnptr = hn;
262
263 if (hn->phrase != NULL) { /* it has phrases */
264 hnptr = hn->phrase;
265 if (is_refprint() && !is_countmode() && !is_listmode() &&
266 !is_quietmode())
267 {
268 printf(" { ");
269 }
270 }
271
272 if (is_refprint() && !is_countmode() &&
273 !is_listmode() && !is_quietmode())
274 {
275 do {
276 char *converted = nmz_query_external(hnptr->word);
277 if (converted == NULL) {
278 die("print_hitnum_each");
279 }
280
281 printf(" [ ");
282 html_print(converted);
283 free(converted);
284
285 if (hnptr->stat == SUCCESS) {
286 printf(": %d", hnptr->hitnum);
287 } else {
288 char *errmsg = nmz_strerror(hnptr->stat);
289 printf(" (%s) ", errmsg);
290 }
291 printf(" ] ");
292 hnptr = hnptr->next;
293 } while (hn->phrase && hnptr != NULL);
294 }
295
296 if (is_refprint() && !is_countmode() && !is_listmode() &&
297 !is_quietmode() && hn->phrase != NULL) /* it has phrases */
298 {
299 printf(" :: %d } ", hn->hitnum);
300 }
301 }
302
303 static int
is_allresult(void)304 is_allresult(void)
305 {
306 return allresult;
307 }
308
309 static int
is_pageindex(void)310 is_pageindex(void)
311 {
312 return pageindex;
313 }
314
315 static int
is_countmode(void)316 is_countmode(void)
317 {
318 return countmode;
319 }
320
321 static int
is_listmode(void)322 is_listmode(void)
323 {
324 return listmode;
325 }
326
327 static int
is_quietmode(void)328 is_quietmode(void)
329 {
330 return quietmode;
331 }
332
333 static int
is_refprint(void)334 is_refprint(void)
335 {
336 return refprint;
337 }
338
339 static int
is_cgimode(void)340 is_cgimode(void)
341 {
342 return cgimode;
343
344 }
345
346 static char*
load_nmz_result(const char * basedir)347 load_nmz_result(const char *basedir)
348 {
349 char fname[BUFSIZE] = "", lang_suffix[BUFSIZE] = "", *buf;
350 char templatesuffix[BUFSIZE] = "";
351
352 nmz_pathcat(basedir, NMZ.result);
353 strncpy(fname, NMZ.result, BUFSIZE - 1);
354 strncat(fname, ".", BUFSIZE - strlen(fname) - 1);
355 nmz_delete_since_path_delimitation(templatesuffix, get_templatesuffix(), BUFSIZE);
356 strncat(fname, templatesuffix, BUFSIZE - strlen(fname) - 1); /* usually "normal" */
357
358 if (nmz_choose_msgfile_suffix(fname, lang_suffix) != SUCCESS) {
359 nmz_warn_printf("%s: %s", fname, strerror(errno));
360 return NULL;
361 }
362 strncat(fname, lang_suffix, BUFSIZE - strlen(fname) - 1);
363
364 /* buf is allocated in nmz_readfile. */
365 buf = nmz_readfile(fname);
366 if (buf == NULL) { /* failed */
367 return NULL;
368 }
369
370 return buf;
371 }
372
373 /*
374 * Display one searched document according to NMZ.result.* file.
375 * e.g.,
376 *
377 * <dt>1. <strong><a href="/foo/gunzip.1.gz">GZIP(1)</a></strong> (score: xx)
378 * <dd><strong>Author</strong>: <em>(unknown)</em>
379 * <dd><strong>Date</strong>: <em>Thu, 09 Apr 1998 12:59:59</em>
380 * <dd>gzip, gunzip, zcat - compress or expand files:: Gzip
381 * reduces the size of the named files using Lempel-Ziv
382 * coding (LZ77). Whenever possible, each file is replaced
383 * by one with the extension .gz, while
384 * <dd><a href="/foo/gunzip.1.gz">/foo/gunzip.1.gz</a> (5,410 bytes)<br><br>
385 */
386 static enum nmz_stat
print_hlist(NmzResult hlist)387 print_hlist(NmzResult hlist)
388 {
389 int i;
390 char *the_template = NULL; /* User-specified template. */
391 char *template_caches[INDEX_MAX]; /* For caching each NMZ.result */
392
393 if (hlist.num <= 0 || get_maxresult() == 0) {
394 return SUCCESS; /* No document searched but success. */
395 }
396
397 /*
398 * Clear pointers for caching NMZ.result.
399 */
400 for (i = 0; i < nmz_get_idxnum(); i++) {
401 template_caches[i] = NULL;
402 }
403
404 /*
405 * Check whether user-specified templatedir is set or not.
406 */
407 {
408 char templdir[BUFSIZE];
409 strcpy(templdir, get_templatedir());
410 if (*templdir != '\0') { /* user-specified one is set. */
411 the_template = load_nmz_result(templdir);
412 if (the_template == NULL) {
413 return ERR_CANNOT_OPEN_RESULT_FORMAT_FILE;
414 }
415 }
416 }
417
418 for (i = get_listwhence(); i < hlist.num; i++) {
419 /*
420 * Prepare large memory for replace_field() for safety.
421 * FIXME: static memory allocation may cause buffer overflow.
422 */
423 char result[BUFSIZE * 128] = "";
424 int counter;
425 char *template = the_template;
426
427 counter = i + 1;
428
429 if (!is_allresult() && (i >= get_listwhence() + get_maxresult()))
430 break;
431
432 if (is_listmode()) {
433 template = "${uri}";
434 } else {
435 int idxid = hlist.data[i].idxid;
436 /*
437 * If user-specified templatedir is not set. and
438 */
439 if (template == NULL) {
440 /*
441 * If NMZ.result is not cached, load NMZ.result and cache it in
442 * template_caches[].
443 */
444 if (template_caches[idxid] == NULL) {
445 char *basedir = nmz_get_idxname(idxid);
446 template_caches[idxid] = load_nmz_result(basedir);
447 if (template_caches[idxid] == NULL) {
448 return ERR_CANNOT_OPEN_RESULT_FORMAT_FILE;
449 }
450 }
451 template = template_caches[idxid];
452 }
453 }
454
455 if (is_htmlmode() || is_listmode()) {
456 compose_result(hlist.data[i], counter, template, result);
457 } else {
458 char tmpbuf[BUFSIZE] = "";
459 strncpy(tmpbuf, template, BUFSIZE -1);
460 tmpbuf[BUFSIZE - 1] = 0;
461 unhtml_buffer(tmpbuf);
462 compose_result(hlist.data[i], counter, tmpbuf, result);
463 }
464 {
465 char *converted = nmz_codeconv_external(result);
466 if (converted == NULL) {
467 die(nmz_get_dyingmsg());
468 }
469 if (is_htmlmode() || is_listmode()) {
470 html_print(converted);
471 } else {
472 puts(converted+1); /* remove '\t' in the head of buffer */
473 }
474 free(converted);
475 printf("\n");
476 }
477 }
478
479 /* Free user-specified template. */
480 if (the_template != NULL) {
481 free(the_template);
482 }
483
484 /* Free all template_caches[] */
485 for (i = 0; i < nmz_get_idxnum(); i++) {
486 if (template_caches[i] != NULL) {
487 free(template_caches[i]);
488 }
489 }
490
491 return SUCCESS;
492 }
493
494 static enum nmz_stat
print_listing(NmzResult hlist)495 print_listing(NmzResult hlist)
496 {
497 enum nmz_stat ret;
498
499 if (is_htmlmode()) {
500 printf("<dl>\n");
501 }
502
503 ret = print_hlist(hlist);
504 if (ret != SUCCESS) {
505 return ret;
506 }
507
508 if (is_htmlmode()) {
509 printf("</dl>\n");
510 }
511 return SUCCESS;
512 }
513
514 /*
515 * For page_index().
516 */
517 static void
print_query(const char * qs,int w)518 print_query(const char * qs, int w)
519 {
520 int foo = 0;
521 while (*qs) {
522 if (strncmp(qs, "whence=", strlen("whence=")) == 0) {
523 foo = 1;
524 printf("whence=%d", w);
525 for (qs += strlen("whence="); nmz_isdigit((unsigned char)*qs); qs++);
526 } else {
527 /* '"' is converted to entities """ */
528 putc_entitize(*qs);
529 qs++;
530 }
531 }
532 if (foo == 0) {
533 printf("&whence=%d", w);
534 }
535 }
536
537 /*
538 * Display page index.
539 */
540 static void
print_page_index(int n)541 print_page_index(int n)
542 {
543 int i, max, whence;
544 char *qs; /* QUERY_STRING */
545 char *sn; /* SCRIPT_NAME */
546 char *dn; /* DOCUMENT_URI */
547
548 qs = nmz_getenv("QUERY_STRING");
549 sn = nmz_getenv("SCRIPT_NAME");
550 dn = nmz_getenv("DOCUMENT_URI");
551
552 if(dn == NULL || *dn == '\0') {
553 dn = sn;
554 } else {
555 /* Delete characters after '?' for Lotus Domino Server R5.06a */
556 char *s;
557 for (s = dn; *s; s++)
558 if (*s == '?') {*s = 0; break;}
559 }
560
561 html_print(_(" <strong>Page:</strong> "));
562
563 max = get_maxresult();
564 whence = get_listwhence();
565 for (i = 0; i < PAGE_MAX; i++) {
566 if (i * max >= n)
567 break;
568 if (is_htmlmode()) {
569 if (i * max != whence) {
570 printf("<a href=\"");
571 fputs(dn, stdout);
572 fputc('?', stdout);
573 print_query(qs, i * max);
574 printf("\">");
575 } else {
576 printf("<strong>");
577 }
578 }
579 printf("[%d]", i + 1);
580 if (is_htmlmode()) {
581 if (i * max != whence) {
582 printf("</a> ");
583 } else
584 printf("</strong> ");
585 }
586 if (is_allresult()) {
587 break;
588 }
589 }
590 }
591
592 /*
593 * Output current range
594 */
595 static void
print_current_range(int listmax)596 print_current_range(int listmax)
597 {
598 int max, whence;
599
600 max = get_maxresult();
601 whence = get_listwhence();
602
603 if (is_htmlmode()) {
604 printf("<strong>");
605 }
606 printf(_("Current List: %d"), whence + 1);
607
608 printf(" - ");
609 if (!is_allresult() && ((whence + max) < listmax)) {
610 printf("%d", whence + max);
611 } else {
612 printf("%d", listmax);
613 }
614 if (is_htmlmode()) {
615 printf("</strong><br>\n");
616 } else {
617 fputc('\n', stdout);
618 }
619 }
620
621 static void
print_hitnum_all_idx(void)622 print_hitnum_all_idx(void)
623 {
624 int idxid;
625 for (idxid = 0; idxid < nmz_get_idxnum(); idxid ++) {
626 struct nmz_hitnumlist *hnlist = nmz_get_idx_hitnumlist(idxid);
627
628 if (is_refprint() && !is_countmode() &&
629 !is_listmode() && !is_quietmode())
630 {
631 if (nmz_get_idxnum() > 1) {
632 if (is_htmlmode()) {
633 char *idxname = nmz_get_idxname(idxid);
634 if (is_cgimode()) {
635 /* For hiding a full pathname of an index */
636 idxname = nmz_get_idxname(idxid)
637 + strlen(nmz_get_defaultidx()) + 1;
638 }
639 printf("<li><strong>");
640 puts_entitize(idxname);
641 printf("</strong>: ");
642 } else {
643 printf("(%s)", nmz_get_idxname(idxid));
644 }
645 }
646 }
647
648 while (hnlist != NULL) {
649 print_hitnum_each(hnlist);
650 hnlist = hnlist->next;
651 }
652
653 if (is_refprint() && !is_countmode() && !is_listmode() &&
654 !is_quietmode()) {
655 if (nmz_get_idxnum() > 1 && nmz_get_querytokennum() > 1) {
656 printf(_(" [ TOTAL: %d ]"), nmz_get_idx_totalhitnum(idxid));
657 }
658 if (nmz_get_idxnum() > 1) {
659 if (is_htmlmode()) {
660 printf("</li>");
661 }
662 }
663 printf("\n");
664 }
665 }
666 }
667
668 static void
print_hitnum(int n)669 print_hitnum(int n)
670 {
671 html_print(_(" <p><strong> Total "));
672 if (is_htmlmode()) {
673 printf("<!-- HIT -->%d<!-- HIT -->", n);
674 }
675 else {
676 printf("%d", n);
677 }
678 html_print(_(" documents matching your query.</strong></p>\n\n"));
679 }
680
681 /*
682 * Output contents of a message file such as NMZ.tips or NMZ.body.
683 */
684 static void
print_msgfile(const char * fname)685 print_msgfile(const char *fname) {
686 char suffix[BUFSIZE] = "", tmpfname[BUFSIZE] = "";
687
688 if (nmz_choose_msgfile_suffix(fname, suffix) == SUCCESS) {
689 char *buf;
690
691 strncpy(tmpfname, fname, BUFSIZE - 1);
692 strncat(tmpfname, suffix, BUFSIZE - strlen(tmpfname) - 1);
693
694 buf = nmz_readfile(tmpfname); /* buf is allocated in nmz_readfile. */
695 if (buf == NULL) {
696 die(nmz_get_dyingmsg());
697 }
698 /* In case of suffix isn't equal to lang, we need code conversion */
699 if (strcmp(suffix, nmz_get_lang()) != 0) {
700 /* new is allocated in nmz_codeconv_external. */
701 char *new = nmz_codeconv_external(buf);
702 free(buf); /* Then we should free buf's memory */
703 buf = new;
704 }
705
706 fputs(buf, stdout);
707 free(buf);
708 } else {
709 nmz_warn_printf("%s: %s", fname, strerror(errno));
710 }
711 }
712
713 static void
print_range(NmzResult hlist)714 print_range(NmzResult hlist)
715 {
716 if (is_htmlmode()) {
717 printf("<div class=\"namazu-result-footer\">\n");
718 }
719 print_current_range(hlist.num);
720 if (is_pageindex()) {
721 print_page_index(hlist.num);
722 }
723 if (is_htmlmode()) {
724 printf("</div>\n"); /* class="namazu-result-footer" */
725 } else {
726 printf("\n");
727 }
728 }
729
730 /*
731 * Print the error message specified by errid while outputing the results.
732 */
733 static void
print_errmsg(int errid)734 print_errmsg(int errid)
735 {
736 char *errmsg = nmz_strerror(errid);
737 char buf[BUFSIZE] = "";
738 snprintf(buf, BUFSIZE - 1, _(" <h2>Error!</h2>\n<p>%s</p>\n"), errmsg);
739 html_print(buf);
740 }
741
742 /*
743 *
744 * Public functions
745 *
746 */
747 enum nmz_stat
print_result(NmzResult hlist,const char * query,const char * subquery)748 print_result(NmzResult hlist, const char *query, const char *subquery)
749 {
750 if (is_htmlmode()) {
751 if (is_cgimode()) {
752 printf("%s %s" CRLF CRLF, MSG_MIME_HEADER, get_contenttype());
753 }
754 print_headfoot(NMZ.head, query, subquery);
755 }
756
757 if (hlist.stat != SUCCESS) {
758 print_errmsg(hlist.stat);
759 return FAILURE;
760 }
761
762 if (!is_countmode() && !is_listmode() && !is_quietmode()) {
763 if (is_htmlmode()) {
764 fputs("<div class=\"namazu-result-header\">\n", stdout);
765 }
766 }
767
768 /* Result1: <h2>Results:</h2>, References: */
769 if (is_refprint() && !is_countmode() &&
770 !is_listmode() && !is_quietmode())
771 {
772 html_print(_(" <h2>Results:</h2>\n"));
773
774 if (is_htmlmode()) {
775 fputs("<p>\n", stdout);
776 } else {
777 fputc('\n', stdout);
778 }
779 printf(_("References: "));
780 if (nmz_get_idxnum() > 1 && is_htmlmode()) {
781 fputs("</p>\n", stdout);
782 }
783
784 if (nmz_get_idxnum() > 1) {
785 printf("\n");
786 if (is_htmlmode())
787 printf("<ul>\n");
788 }
789 }
790
791 print_hitnum_all_idx(); /* print hit numbers for all index. */
792
793 if (is_refprint() && !is_countmode() &&
794 !is_listmode() && !is_quietmode()) {
795 if (nmz_get_idxnum() > 1 && is_htmlmode()) {
796 printf("</ul>\n");
797 }
798 if (nmz_get_idxnum() == 1 && is_htmlmode()) {
799 printf("\n</p>\n");
800 } else {
801 fputc('\n', stdout);
802 }
803 }
804
805 if (hlist.num > 0) {
806 if (!is_countmode() && !is_listmode() && !is_quietmode()) {
807 print_hitnum(hlist.num); /* <!-- HIT -->%d<!-- HIT --> */
808 if (is_htmlmode()) {
809 fputs("</div>\n", stdout); /* class="namazu-result-header" */
810 }
811 }
812 if (is_countmode()) {
813 printf("%d\n", hlist.num);
814 } else {
815 enum nmz_stat ret = print_listing(hlist);
816
817 if (ret != SUCCESS) { /* summary listing */
818 print_errmsg(ret);
819 return ret;
820 }
821 }
822 if (!is_countmode() && !is_listmode() && !is_quietmode()) {
823 print_range(hlist);
824 }
825 } else {
826 if (is_countmode()) {
827 printf("0\n");
828 } else if (!is_listmode() && !is_quietmode()) {
829 html_print(_(" <p>No document matching your query.</p>\n"));
830 if (is_htmlmode()) {
831 fputs("</div>\n", stdout); /* class="namazu-result-header" */
832 print_msgfile(NMZ.tips);
833 }
834 }
835 }
836
837 if (is_htmlmode()) {
838 print_headfoot(NMZ.foot, query, subquery);
839 }
840
841 return SUCCESS;
842 }
843
844 /*
845 * Print default page: NMZ.{head,body,foot}
846 */
847 void
print_default_page(void)848 print_default_page (void) {
849 if (is_htmlmode()) {
850 if (is_cgimode()) {
851 printf("%s %s" CRLF CRLF, MSG_MIME_HEADER, get_contenttype());
852 }
853 print_headfoot(NMZ.head, "", "");
854 print_msgfile(NMZ.body);
855 print_headfoot(NMZ.foot, "", "");
856 }
857 }
858
859 /*
860 * output string as non-html (replace special characters by entities)
861 */
862 void
puts_entitize(const char * str)863 puts_entitize(const char *str)
864 {
865 const char *p = str;
866 for (; *p != 0; p++) {
867 putc_entitize(*p);
868 }
869 }
870
871 void
putc_entitize(int c)872 putc_entitize(int c)
873 {
874 if (c == '<') {
875 fputs("<", stdout);
876 } else if (c == '>') {
877 fputs(">", stdout);
878 } else if (c == '&') {
879 fputs("&", stdout);
880 } else if (c == '"') {
881 fputs(""", stdout);
882 } else if (c == '\'') {
883 /* not support ' for HTML 4.01 */
884 /* fputs("'", stdout); */
885 fputs("'", stdout);
886 } else if (c == '(') {
887 fputs("(", stdout);
888 } else if (c == ')') {
889 fputs(")", stdout);
890 } else {
891 fputc(c, stdout);
892 }
893 }
894
895 void
set_emphasis_tags(const char * start_tag,const char * end_tag)896 set_emphasis_tags(const char *start_tag, const char *end_tag)
897 {
898 strncpy(emphasis_start_tag, start_tag, BUFSIZE - 1);
899 strncpy(emphasis_end_tag, end_tag, BUFSIZE - 1);
900 }
901
902 char *
get_emphasis_tag_start(void)903 get_emphasis_tag_start(void)
904 {
905 return emphasis_start_tag;
906 }
907
908 char *
get_emphasis_tag_end(void)909 get_emphasis_tag_end(void)
910 {
911 return emphasis_end_tag;
912 }
913
914 void
set_contenttype(const char * str)915 set_contenttype(const char *str)
916 {
917 strncpy(contenttype, str, BUFSIZE - 1);
918 }
919
920 char *
get_contenttype(void)921 get_contenttype(void)
922 {
923 static char buff[BUFSIZE];
924 char *p;
925 int is_charset = 0;
926
927
928 buff[0] = '\0';
929 p = strtok(contenttype, " \t\n\r;");
930 while(p) {
931 if (!strncasecmp(p, "charset=", strlen("charset="))) {
932 is_charset = 1;
933 break;
934 }
935 p = strtok(NULL, " \t\n\r;");
936 }
937
938 if (!is_charset) {
939 char *charset = "ISO-8859-1";
940 int cont = 1;
941 char suffix[BUFSIZE] = "";
942 char *lang;
943
944 buff[0] = '\0';
945 if (nmz_choose_msgfile_suffix(NMZ.head, suffix) == SUCCESS) {
946 if (suffix[0] == '.') {
947 strncpy(buff, suffix + 1, BUFSIZE - 1);
948 } else {
949 buff[0] = '\0';
950 }
951 }
952 lang = nmz_get_lang();
953 if (!strncasecmp(lang, "ja", 2)) {
954 if (!strcasecmp(lang, "ja_JP.SJIS")) {
955 /* Shift_JIS */
956 strncpy(buff, "ja_JP.SJIS", BUFSIZE - 1);
957 } else if (!strcasecmp(lang, "ja_JP.ISO-2022-JP")) {
958 /* ISO-2022-JP */
959 strncpy(buff, "ja_JP.ISO-2022-JP", BUFSIZE - 1);
960 } else {
961 /* EUC-JP */
962 strncpy(buff, "ja", BUFSIZE - 1);
963 }
964 }
965
966 while(cont == 1) {
967 int i;
968 char *value;
969 cont = 0;
970
971 if ((value = nmz_find_first_strlist(handle_charset, buff))) {
972 charset = value;
973 break;
974 }
975
976 for(i = (int)strlen(buff) - 1; i >= 0; i--) {
977 if (buff[i] == '.' || buff[i] == '_' || buff[i] == '@') {
978 buff[i] = '\0';
979 cont = 1;
980 break;
981 }
982 }
983 }
984
985 sprintf(buff, "%s; charset=%s", contenttype, charset);
986 return(buff);
987 }
988
989 return(contenttype);
990 }
991
992 void
set_htmlmode(int mode)993 set_htmlmode(int mode)
994 {
995 htmlmode = mode;
996 }
997
998 int
is_htmlmode(void)999 is_htmlmode(void)
1000 {
1001 return htmlmode;
1002 }
1003
1004 void
set_cgimode(int mode)1005 set_cgimode(int mode)
1006 {
1007 cgimode = mode;
1008 }
1009
1010 void
set_quietmode(int mode)1011 set_quietmode(int mode)
1012 {
1013 quietmode = mode;
1014 }
1015
1016 void
set_countmode(int mode)1017 set_countmode(int mode)
1018 {
1019 countmode = mode;
1020 }
1021
1022 void
set_listmode(int mode)1023 set_listmode(int mode)
1024 {
1025 listmode = mode;
1026 }
1027
1028 void
set_allresult(int mode)1029 set_allresult(int mode)
1030 {
1031 allresult = mode;
1032 }
1033
1034 void
set_pageindex(int mode)1035 set_pageindex(int mode)
1036 {
1037 pageindex = mode;
1038 }
1039
1040 void
set_formprint(int mode)1041 set_formprint(int mode)
1042 {
1043 formprint = mode;
1044 }
1045
1046 int
is_formprint(void)1047 is_formprint(void)
1048 {
1049 return formprint;
1050 }
1051
1052 void
set_refprint(int mode)1053 set_refprint(int mode)
1054 {
1055 refprint = mode;
1056 }
1057
1058 void
set_maxresult(int num)1059 set_maxresult(int num)
1060 {
1061 maxresult = num;
1062 }
1063
1064 int
get_maxresult(void)1065 get_maxresult(void)
1066 {
1067 return maxresult;
1068 }
1069
1070 void
set_listwhence(int num)1071 set_listwhence(int num)
1072 {
1073 listwhence = num;
1074 }
1075
1076 int
get_listwhence(void)1077 get_listwhence(void)
1078 {
1079 return listwhence;
1080 }
1081
1082
1083 void
set_templatesuffix(const char * tmpl)1084 set_templatesuffix(const char *tmpl)
1085 {
1086 int i = 0;
1087 char *p;
1088
1089 strncpy(template_suffix, tmpl, BUFSIZE - 1);
1090 template_suffix[BUFSIZE - 1] = '\0';
1091
1092 /*
1093 * result : [A-Za-z][A-Za-z0-9_\-]*
1094 * (ex. normal, short)
1095 */
1096 p = template_suffix;
1097 while(*p) {
1098 if (!((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
1099 (((*p >= '0' && *p <= '9') || *p == '_' || *p == '-')&& i != 0))) {
1100 *p = '\0';
1101 break;
1102 }
1103 p++;
1104 i++;
1105 }
1106
1107 if (template_suffix[0] == '\0') {
1108 strncpy(template_suffix, "normal", BUFSIZE - 1);
1109 template_suffix[BUFSIZE - 1] = '\0';
1110 }
1111 }
1112
1113 char *
get_templatesuffix(void)1114 get_templatesuffix(void)
1115 {
1116 return template_suffix;
1117 }
1118
1119
1120 /*
1121 * Namazu version fputs, it works with considereation of html mode.
1122 */
1123 void
html_print(const char * str)1124 html_print(const char *str)
1125 {
1126 char buf[BUFSIZE * 16] = "";
1127 int is_nmz_html = 0;
1128
1129 if ((int)*str == (int)'\t') { /* Namazu's HTML message */
1130 is_nmz_html = 1;
1131 }
1132
1133 strcpy(buf, str + is_nmz_html);
1134 if (is_htmlmode()) {
1135 /*
1136 * If str is Namazu's HTML message, it will be printed with emprint.
1137 * If not, it will be printed with entity conversion
1138 */
1139 emprint(buf, ! is_nmz_html);
1140 } else {
1141 /*
1142 * If str is Namazu's HTML message, it will be printed without
1143 * HTML tag, if not, it will be printed as is
1144 */
1145 if (is_nmz_html) {
1146 fputs_without_html_tag(buf, stdout);
1147 }
1148 else {
1149 fputs(buf, stdout);
1150 }
1151 }
1152 }
1153
1154
1155 /*
1156 * Print the error message and die.
1157 */
1158 void
die(const char * fmt,...)1159 die(const char *fmt, ...)
1160 {
1161 va_list args;
1162
1163 fflush(stdout);
1164 fflush(stderr);
1165
1166 if (is_htmlmode()) {
1167 static char msg[BUFSIZE] = "";
1168
1169 va_start(args, fmt);
1170 vsnprintf(msg, BUFSIZE - 1, fmt, args);
1171 va_end(args);
1172
1173 if (is_cgimode()) {
1174 printf("%s %s; %s" CRLF CRLF, MSG_MIME_HEADER,
1175 "text/html", _("charset=ISO-8859-1"));
1176 }
1177 printf("<html><body>\n");
1178 printf(_("<h2>Error</h2>\n<p>"));
1179 puts_entitize(msg);
1180 printf(_("</p>"));
1181 printf("\n</body></html>\n");
1182 } else {
1183 fprintf(stderr, "%s: ", PACKAGE);
1184 va_start(args, fmt);
1185 vfprintf(stderr, fmt, args);
1186 va_end(args);
1187 if (fmt[strlen(fmt) - 1] != '\n') {
1188 fprintf(stderr, "\n");
1189 }
1190 }
1191
1192 exit_nmz(EXIT_FAILURE);
1193 }
1194
1195