#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <microhttpd.h>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define PORT 8888

#define PAGE							\
  "<html><head><title>libmicrohttpd demo</title></head>"	\
  "<body>Access granted</body></html>"

#define DENIED							\
  "<html><head><title>libmicrohttpd demo</title></head>"	\
  "<body>Access denied</body></html>"

#define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"

static int
ahc_echo (void *cls,
          struct MHD_Connection *connection,
          const char *url,
          const char *method,
          const char *version,
          const char *upload_data, size_t *upload_data_size, void **ptr)
{
  struct MHD_Response *response;
  char *username;
  const char *password = "testpass";
  const char *realm = "test@example.com";
  int ret;

  fprintf(stderr, "%s %s %s\n", method, url, version);
  username = MHD_digest_auth_get_username(connection);
  if (username == NULL)
    {
      response = MHD_create_response_from_buffer(strlen (DENIED),
					         DENIED,
					         MHD_RESPMEM_PERSISTENT);
      ret = MHD_queue_auth_fail_response(connection, realm,
					 OPAQUE,
					 response,
					 MHD_NO);
      MHD_destroy_response(response);
      return ret;
    }
  ret = MHD_digest_auth_check(connection, realm,
			      username,
			      password,
			      300);
  free(username);
  if ( (ret == MHD_INVALID_NONCE) ||
       (ret == MHD_NO) )
    {
      response = MHD_create_response_from_buffer(strlen (DENIED),
					         DENIED,
					         MHD_RESPMEM_PERSISTENT);
      if (NULL == response)
	return MHD_NO;
      ret = MHD_queue_auth_fail_response(connection, realm,
					 OPAQUE,
					 response,
					 (ret == MHD_INVALID_NONCE)?
					 MHD_YES : MHD_NO);
      MHD_destroy_response(response);
      return ret;
    }
  response = MHD_create_response_from_buffer (strlen(PAGE), PAGE,
 					      MHD_RESPMEM_PERSISTENT);
  ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
  MHD_destroy_response(response);
  return ret;
}

int main ()
{
  struct MHD_Daemon *daemon;

  daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
                             &ahc_echo, NULL, MHD_OPTION_END);
  if (NULL == daemon) return 1;
  getchar ();

  MHD_stop_daemon (daemon);
  return 0;
}
