/*
 * Dpi for "Hello World".
 *
 * This server is an example. Play with it and modify to your taste.
 *
 * Copyright 2003 Jorge Arellano Cid <jcid@dillo.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 */

#include <glib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/*---------------------------------------------------------------------------*/

/*
 * Task: given a tag and an attribute name, return its value.
 *       (character stuffing is removed here)
 * Return value: the attribute value, or NULL if not present or malformed.
 * (copied from bookmarks.c)
 */          
char *Get_attr_value(char *tag, int tagsize, char *attrname)
{            
   char *p, *q, *ltag, quote, *start, *val = NULL;

   ltag = g_strndup(tag, tagsize);
   if ((p = strstr(ltag, attrname)) &&
       (p = strchr(p, '=')) &&
       (p = strpbrk(p, "'\"")) ) {
      quote = *p;                 
      start = ++p;
      while ((q = strchr(p, quote)) && q[1] == quote)
         p = q + 2;
      if (q) {
         val = g_strndup(start, q - start);
         for (p = q = val; (*q = *p); ++p, ++q)
            if ((*p == '"' || *p == '\'') && p[1] == p[0])
               ++p;
      }
   }         
   g_free(ltag);

   return val;
}


/*
 * Send the stream with coarse buffering (fastest)
 */
gint send_stream_4(FILE *in_stream, gchar *url)
{
   gchar buf[4096];
   size_t n;

   while ((n = fread (buf, 1, 4096, in_stream)) > 0)
      fwrite(buf, 1, n, stdout);

   return 0;
}

/*
 * Escape unsafe characters as html entities.
 * Return value: NULL if there's no need to escape, New string otherwise.
 * (borrowed from Dillo's file.c)
 */
static gchar *Html_escape(const gchar *str)
{
   static const char *unsafe_chars = "&<>\"'";
   static const char *unsafe_rep[] =
     { "&amp;", "&lt;", "&gt;", "&quot;", "&#39;" };

   gchar *p;
   GString *gstr;
   gint i;

   if ((p = strpbrk(str, unsafe_chars))) {
      gstr = g_string_sized_new(64);

      for (i = 0; str[i]; ++i) {
         if ((p = strchr(unsafe_chars, str[i])))
            g_string_append(gstr, unsafe_rep[p - unsafe_chars]);
         else
            g_string_append_c(gstr, str[i]);
      }
      p = gstr->str;
      g_string_free(gstr, FALSE);
   }
   return p;
}


/*
 *
 */
int main(void)
{
   FILE *F_stdin, *in_stream;
   gchar *dpip_tag = NULL, *cmd = NULL, *url = NULL, *child_cmd = NULL;
   gchar *esc_tag;
   gint i, rd_len, ret;
   gchar buf[4096];

   g_printerr("hello.dpi:: starting...\n");

   /* Read the dpi command from STDIN.
    * (the buffer has a fixed size, but is enough for this example!)
    */
   F_stdin = fdopen (STDIN_FILENO, "r");
   rd_len = read(STDIN_FILENO, buf, 4096);
   dpip_tag = g_strndup(buf, rd_len);
   fclose(F_stdin);
   g_printerr("[%s]\n", dpip_tag);

   cmd = Get_attr_value(dpip_tag, strlen(dpip_tag), "cmd");
   url = Get_attr_value(dpip_tag, strlen(dpip_tag), "url");

   /* Start sending our answer */
   printf("<dpi cmd='start_send_page' url='%s'>", url);
   printf("Content-type: text/html\n\n");
   printf("<html>\n"
          "<head><title>Simple dpi test page (hello.dpi)</title></head>\n"
          "<body><hr><h1>Hello world!</h1><hr>\n"
          "<br><br>\n");

   /* Show the dpip tag we received */
   esc_tag = Html_escape(dpip_tag);
   printf("<h3>dpip tag received:</h3>\n");
   printf("<pre>\n%s</pre>\n", esc_tag);
   printf("<br><small>(<b>dpip:</b> dpi protocol)</small><br><br><br>\n");
   g_free(esc_tag);


   /* No something more interesting,
    * fork a command and show its feedback */
   if (cmd && url) {
      child_cmd = g_strdup("date -R");
      g_printerr("[%s]\n", child_cmd);

      /* Fork, exec command, get its output and answer */
      if ((in_stream = popen(child_cmd, "r")) == NULL) {
         perror("popen");
         return EXIT_FAILURE;
      }
   
      printf("<h3>date:</h3>\n");
      printf("<pre>\n");
      /* Read/Write */
      i = send_stream_4(in_stream, url);
      printf("</pre>\n");
   
      if ((ret = pclose(in_stream)) != 0)
         g_printerr("popen: [%d]\n", ret);

      g_free(child_cmd);
   }

   printf("</body></html>\n");

   g_free(cmd);
   g_free(url);
   g_free(dpip_tag);
   return 0;
}

