[BACK]Return to cgi.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/cgi.c between version 1.126 and 1.132

version 1.126, 2016/04/15 01:34:51 version 1.132, 2016/05/28 13:40:48
Line 21 
Line 21 
 #include <sys/time.h>  #include <sys/time.h>
   
 #include <ctype.h>  #include <ctype.h>
   #include <err.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <limits.h>  #include <limits.h>
Line 58  struct req {
Line 59  struct req {
         int               isquery; /* QUERY_STRING used, not PATH_INFO */          int               isquery; /* QUERY_STRING used, not PATH_INFO */
 };  };
   
 static  void             catman(const struct req *, const char *);  enum    focus {
 static  void             format(const struct req *, const char *);          FOCUS_NONE = 0,
           FOCUS_QUERY
   };
   
 static  void             html_print(const char *);  static  void             html_print(const char *);
 static  void             html_putchar(char);  static  void             html_putchar(char);
 static  int              http_decode(char *);  static  int              http_decode(char *);
 static  void             http_parse(struct req *, const char *);  static  void             parse_manpath_conf(struct req *);
 static  void             pathgen(struct req *);  static  void             parse_path_info(struct req *req, const char *path);
 static  void             path_parse(struct req *req, const char *path);  static  void             parse_query_string(struct req *, const char *);
 static  void             pg_error_badrequest(const char *);  static  void             pg_error_badrequest(const char *);
 static  void             pg_error_internal(void);  static  void             pg_error_internal(void);
 static  void             pg_index(const struct req *);  static  void             pg_index(const struct req *);
Line 76  static void   pg_searchres(const struct req *,
Line 80  static void   pg_searchres(const struct req *,
 static  void             pg_show(struct req *, const char *);  static  void             pg_show(struct req *, const char *);
 static  void             resp_begin_html(int, const char *);  static  void             resp_begin_html(int, const char *);
 static  void             resp_begin_http(int, const char *);  static  void             resp_begin_http(int, const char *);
   static  void             resp_catman(const struct req *, const char *);
 static  void             resp_copy(const char *);  static  void             resp_copy(const char *);
 static  void             resp_end_html(void);  static  void             resp_end_html(void);
 static  void             resp_searchform(const struct req *);  static  void             resp_format(const struct req *, const char *);
   static  void             resp_searchform(const struct req *, enum focus);
 static  void             resp_show(const struct req *, const char *);  static  void             resp_show(const struct req *, const char *);
 static  void             set_query_attr(char **, char **);  static  void             set_query_attr(char **, char **);
 static  int              validate_filename(const char *);  static  int              validate_filename(const char *);
Line 184  set_query_attr(char **attr, char **val)
Line 190  set_query_attr(char **attr, char **val)
  * and store the values into the query structure.   * and store the values into the query structure.
  */   */
 static void  static void
 http_parse(struct req *req, const char *qs)  parse_query_string(struct req *req, const char *qs)
 {  {
         char            *key, *val;          char            *key, *val;
         size_t           keysz, valsz;          size_t           keysz, valsz;
Line 366  resp_end_html(void)
Line 372  resp_end_html(void)
 }  }
   
 static void  static void
 resp_searchform(const struct req *req)  resp_searchform(const struct req *req, enum focus focus)
 {  {
         int              i;          int              i;
   
Line 379  resp_searchform(const struct req *req)
Line 385  resp_searchform(const struct req *req)
   
         /* Write query input box. */          /* Write query input box. */
   
         printf( "<table><tr><td>\n"          printf("<input type=\"text\" name=\"query\" value=\"");
                 "<input type=\"text\" name=\"query\" value=\"");          if (req->q.query != NULL)
         if (NULL != req->q.query)  
                 html_print(req->q.query);                  html_print(req->q.query);
         puts("\" size=\"40\">");          printf( "\" size=\"40\"");
           if (focus == FOCUS_QUERY)
                   printf(" autofocus");
           puts(">");
   
         /* Write submission and reset buttons. */          /* Write submission buttons. */
   
         printf( "<input type=\"submit\" value=\"Submit\">\n"          printf( "<button type=\"submit\" name=\"apropos\" value=\"0\">"
                 "<input type=\"reset\" value=\"Reset\">\n");                  "man</button>\n"
                   "<button type=\"submit\" name=\"apropos\" value=\"1\">"
                   "apropos</button>\n<br/>\n");
   
         /* Write show radio button */  
   
         printf( "</td><td>\n"  
                 "<input type=\"radio\" ");  
         if (req->q.equal)  
                 printf("checked=\"checked\" ");  
         printf( "name=\"apropos\" id=\"show\" value=\"0\">\n"  
                 "<label for=\"show\">Show named manual page</label>\n");  
   
         /* Write section selector. */          /* Write section selector. */
   
         puts(   "</td></tr><tr><td>\n"          puts("<select name=\"sec\">");
                 "<select name=\"sec\">");  
         for (i = 0; i < sec_MAX; i++) {          for (i = 0; i < sec_MAX; i++) {
                 printf("<option value=\"%s\"", sec_numbers[i]);                  printf("<option value=\"%s\"", sec_numbers[i]);
                 if (NULL != req->q.sec &&                  if (NULL != req->q.sec &&
Line 445  resp_searchform(const struct req *req)
Line 445  resp_searchform(const struct req *req)
                 puts("</select>");                  puts("</select>");
         }          }
   
         /* Write search radio button */          puts("</fieldset>\n"
   
         printf( "</td><td>\n"  
                 "<input type=\"radio\" ");  
         if (0 == req->q.equal)  
                 printf("checked=\"checked\" ");  
         printf( "name=\"apropos\" id=\"search\" value=\"1\">\n"  
                 "<label for=\"search\">Search with apropos query</label>\n");  
   
         puts("</td></tr></table>\n"  
              "</fieldset>\n"  
              "</form>\n"               "</form>\n"
              "</div>");               "</div>");
         puts("<!-- End search form. //-->");          puts("<!-- End search form. //-->");
Line 506  pg_index(const struct req *req)
Line 496  pg_index(const struct req *req)
 {  {
   
         resp_begin_html(200, NULL);          resp_begin_html(200, NULL);
         resp_searchform(req);          resp_searchform(req, FOCUS_QUERY);
         printf("<p>\n"          printf("<p>\n"
                "This web interface is documented in the\n"                 "This web interface is documented in the\n"
                "<a href=\"/%s%smandoc/man8/man.cgi.8\">man.cgi</a>\n"                 "<a href=\"/%s%smandoc/man8/man.cgi.8\">man.cgi</a>\n"
Line 523  static void
Line 513  static void
 pg_noresult(const struct req *req, const char *msg)  pg_noresult(const struct req *req, const char *msg)
 {  {
         resp_begin_html(200, NULL);          resp_begin_html(200, NULL);
         resp_searchform(req);          resp_searchform(req, FOCUS_QUERY);
         puts("<p>");          puts("<p>");
         puts(msg);          puts(msg);
         puts("</p>");          puts("</p>");
Line 564  pg_searchres(const struct req *req, struct manpage *r,
Line 554  pg_searchres(const struct req *req, struct manpage *r,
         for (i = 0; i < sz; i++) {          for (i = 0; i < sz; i++) {
                 if (validate_filename(r[i].file))                  if (validate_filename(r[i].file))
                         continue;                          continue;
                 fprintf(stderr, "invalid filename %s in %s database\n",                  warnx("invalid filename %s in %s database",
                     r[i].file, req->q.manpath);                      r[i].file, req->q.manpath);
                 pg_error_internal();                  pg_error_internal();
                 return;                  return;
Line 587  pg_searchres(const struct req *req, struct manpage *r,
Line 577  pg_searchres(const struct req *req, struct manpage *r,
         }          }
   
         resp_begin_html(200, NULL);          resp_begin_html(200, NULL);
         resp_searchform(req);          resp_searchform(req,
               req->q.equal || sz == 1 ? FOCUS_NONE : FOCUS_QUERY);
   
         if (sz > 1) {          if (sz > 1) {
                 puts("<div class=\"results\">");                  puts("<div class=\"results\">");
Line 660  pg_searchres(const struct req *req, struct manpage *r,
Line 651  pg_searchres(const struct req *req, struct manpage *r,
 }  }
   
 static void  static void
 catman(const struct req *req, const char *file)  resp_catman(const struct req *req, const char *file)
 {  {
         FILE            *f;          FILE            *f;
         char            *p;          char            *p;
Line 797  catman(const struct req *req, const char *file)
Line 788  catman(const struct req *req, const char *file)
 }  }
   
 static void  static void
 format(const struct req *req, const char *file)  resp_format(const struct req *req, const char *file)
 {  {
         struct manoutput conf;          struct manoutput conf;
         struct mparse   *mp;          struct mparse   *mp;
Line 824  format(const struct req *req, const char *file)
Line 815  format(const struct req *req, const char *file)
   
         mparse_result(mp, &man, NULL);          mparse_result(mp, &man, NULL);
         if (man == NULL) {          if (man == NULL) {
                 fprintf(stderr, "fatal mandoc error: %s/%s\n",                  warnx("fatal mandoc error: %s/%s", req->q.manpath, file);
                     req->q.manpath, file);  
                 pg_error_internal();                  pg_error_internal();
                 mparse_free(mp);                  mparse_free(mp);
                 mchars_free();                  mchars_free();
Line 856  resp_show(const struct req *req, const char *file)
Line 846  resp_show(const struct req *req, const char *file)
                 file += 2;                  file += 2;
   
         if ('c' == *file)          if ('c' == *file)
                 catman(req, file);                  resp_catman(req, file);
         else          else
                 format(req, file);                  resp_format(req, file);
 }  }
   
 static void  static void
Line 889  pg_show(struct req *req, const char *fullpath)
Line 879  pg_show(struct req *req, const char *fullpath)
          */           */
   
         if (chdir(manpath) == -1) {          if (chdir(manpath) == -1) {
                 fprintf(stderr, "chdir %s: %s\n",                  warn("chdir %s", manpath);
                     manpath, strerror(errno));  
                 pg_error_internal();                  pg_error_internal();
                 free(manpath);                  free(manpath);
                 return;                  return;
Line 909  pg_show(struct req *req, const char *fullpath)
Line 898  pg_show(struct req *req, const char *fullpath)
         }          }
   
         resp_begin_html(200, NULL);          resp_begin_html(200, NULL);
         resp_searchform(req);          resp_searchform(req, FOCUS_NONE);
         resp_show(req, file);          resp_show(req, file);
         resp_end_html();          resp_end_html();
 }  }
Line 931  pg_search(const struct req *req)
Line 920  pg_search(const struct req *req)
          * relative to the manpath root.           * relative to the manpath root.
          */           */
   
         if (-1 == (chdir(req->q.manpath))) {          if (chdir(req->q.manpath) == -1) {
                 fprintf(stderr, "chdir %s: %s\n",                  warn("chdir %s", req->q.manpath);
                     req->q.manpath, strerror(errno));  
                 pg_error_internal();                  pg_error_internal();
                 return;                  return;
         }          }
Line 1008  main(void)
Line 996  main(void)
         itimer.it_interval.tv_sec = 2;          itimer.it_interval.tv_sec = 2;
         itimer.it_interval.tv_usec = 0;          itimer.it_interval.tv_usec = 0;
         if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {          if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) {
                 fprintf(stderr, "setitimer: %s\n", strerror(errno));                  warn("setitimer");
                 pg_error_internal();                  pg_error_internal();
                 return EXIT_FAILURE;                  return EXIT_FAILURE;
         }          }
Line 1019  main(void)
Line 1007  main(void)
          * relative to the same position.           * relative to the same position.
          */           */
   
         if (-1 == chdir(MAN_DIR)) {          if (chdir(MAN_DIR) == -1) {
                 fprintf(stderr, "MAN_DIR: %s: %s\n",                  warn("MAN_DIR: %s", MAN_DIR);
                     MAN_DIR, strerror(errno));  
                 pg_error_internal();                  pg_error_internal();
                 return EXIT_FAILURE;                  return EXIT_FAILURE;
         }          }
   
         memset(&req, 0, sizeof(struct req));          memset(&req, 0, sizeof(struct req));
         req.q.equal = 1;          req.q.equal = 1;
         pathgen(&req);          parse_manpath_conf(&req);
   
         /* Parse the path info and the query string. */          /* Parse the path info and the query string. */
   
Line 1038  main(void)
Line 1025  main(void)
                 path++;                  path++;
   
         if (*path != '\0') {          if (*path != '\0') {
                 path_parse(&req, path);                  parse_path_info(&req, path);
                 if (access(path, F_OK) == -1)                  if (access(path, F_OK) == -1)
                         path = "";                          path = "";
         } else if ((querystring = getenv("QUERY_STRING")) != NULL)          } else if ((querystring = getenv("QUERY_STRING")) != NULL)
                 http_parse(&req, querystring);                  parse_query_string(&req, querystring);
   
         /* Validate parsed data and add defaults. */          /* Validate parsed data and add defaults. */
   
Line 1083  main(void)
Line 1070  main(void)
  * If PATH_INFO is not a file name, translate it to a query.   * If PATH_INFO is not a file name, translate it to a query.
  */   */
 static void  static void
 path_parse(struct req *req, const char *path)  parse_path_info(struct req *req, const char *path)
 {  {
         int      dir_done;          char    *dir;
   
         req->isquery = 0;          req->isquery = 0;
         req->q.equal = 1;          req->q.equal = 1;
Line 1115  path_parse(struct req *req, const char *path)
Line 1102  path_parse(struct req *req, const char *path)
         req->q.query = mandoc_strdup(req->q.query);          req->q.query = mandoc_strdup(req->q.query);
   
         /* Optional architecture. */          /* Optional architecture. */
         dir_done = 0;          dir = strrchr(req->q.manpath, '/');
         for (;;) {          if (dir != NULL && strncmp(dir + 1, "man", 3) != 0) {
                 if ((req->q.arch = strrchr(req->q.manpath, '/')) == NULL)                  *dir++ = '\0';
                         break;                  req->q.arch = mandoc_strdup(dir);
                 *req->q.arch++ = '\0';                  dir = strrchr(req->q.manpath, '/');
                 if (dir_done || strncmp(req->q.arch, "man", 3)) {          } else
                         req->q.arch = mandoc_strdup(req->q.arch);                  req->q.arch = NULL;
                         break;  
                 }  
   
                 /* Optional directory name. */          /* Optional directory name. */
                 req->q.arch += 3;          if (dir != NULL && strncmp(dir + 1, "man", 3) == 0) {
                 if (*req->q.arch != '\0') {                  *dir++ = '\0';
                         free(req->q.sec);                  free(req->q.sec);
                         req->q.sec = mandoc_strdup(req->q.arch);                  req->q.sec = mandoc_strdup(dir + 3);
                 }  
                 dir_done = 1;  
         }          }
 }  }
   
Line 1139  path_parse(struct req *req, const char *path)
Line 1122  path_parse(struct req *req, const char *path)
  * Scan for indexable paths.   * Scan for indexable paths.
  */   */
 static void  static void
 pathgen(struct req *req)  parse_manpath_conf(struct req *req)
 {  {
         FILE    *fp;          FILE    *fp;
         char    *dp;          char    *dp;
         size_t   dpsz;          size_t   dpsz;
         ssize_t  len;          ssize_t  len;
   
         if (NULL == (fp = fopen("manpath.conf", "r"))) {          if ((fp = fopen("manpath.conf", "r")) == NULL) {
                 fprintf(stderr, "%s/manpath.conf: %s\n",                  warn("%s/manpath.conf", MAN_DIR);
                         MAN_DIR, strerror(errno));  
                 pg_error_internal();                  pg_error_internal();
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
         }          }
Line 1162  pathgen(struct req *req)
Line 1144  pathgen(struct req *req)
                 req->p = mandoc_realloc(req->p,                  req->p = mandoc_realloc(req->p,
                     (req->psz + 1) * sizeof(char *));                      (req->psz + 1) * sizeof(char *));
                 if ( ! validate_urifrag(dp)) {                  if ( ! validate_urifrag(dp)) {
                         fprintf(stderr, "%s/manpath.conf contains "                          warnx("%s/manpath.conf contains "
                             "unsafe path \"%s\"\n", MAN_DIR, dp);                              "unsafe path \"%s\"", MAN_DIR, dp);
                         pg_error_internal();                          pg_error_internal();
                         exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
                 }                  }
                 if (NULL != strchr(dp, '/')) {                  if (strchr(dp, '/') != NULL) {
                         fprintf(stderr, "%s/manpath.conf contains "                          warnx("%s/manpath.conf contains "
                             "path with slash \"%s\"\n", MAN_DIR, dp);                              "path with slash \"%s\"", MAN_DIR, dp);
                         pg_error_internal();                          pg_error_internal();
                         exit(EXIT_FAILURE);                          exit(EXIT_FAILURE);
                 }                  }
Line 1179  pathgen(struct req *req)
Line 1161  pathgen(struct req *req)
         }          }
         free(dp);          free(dp);
   
         if ( req->p == NULL ) {          if (req->p == NULL) {
                 fprintf(stderr, "%s/manpath.conf is empty\n", MAN_DIR);                  warnx("%s/manpath.conf is empty", MAN_DIR);
                 pg_error_internal();                  pg_error_internal();
                 exit(EXIT_FAILURE);                  exit(EXIT_FAILURE);
         }          }

Legend:
Removed from v.1.126  
changed lines
  Added in v.1.132

CVSweb