/*
 * $Header: /home/gene/library/website/docsrc/httpxtran/src/RCS/httpxtran.c,v 395.1 2008/04/20 17:25:51 gene Exp $
 *
 * Copyright (c) 2005 Gene Michael Stover.  All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL GENE MICHAEL STOVER BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * Except as contained in this notice, the name of Gene Michael Stover
 * shall not be used in advertising or otherwise to promote the sale, use
 * or other dealings in this Software without prior written authorization
 * from Gene Michael Stover.
 */
/*
 * HTTP Transaction.  Send some data & save the reply.
 */

#include "this.h"

/*
 */
enum { ACTION_HELP, ACTION_RUN };
static int S_action = ACTION_RUN;
static char *S_progname = NULL;
static char *S_url = NULL;
static FILE *S_src = NULL;
static FILE *S_dst = stdout;
static BOOL S_isSaveHeaders = FALSE;
static struct XHTTP_Proxy S_proxy;

/*
 */
static int
S_Init ()
{
  int rc = 0;

  srand (time (NULL) + getpid ());
  return rc;
}

/*
 */
static int
S_CommandLine (int argc, char *argv[])
{
  int rc = 0;
  int c;

  S_progname = argv[0];
  while (rc == 0 && (c = getopt (argc, argv, "ghi:l:m:o:p:sx:")) != -1) {
    switch (c) {
    case 'g':
      DEBUG_Enable (TRUE);
      break;

    case 'h':
      S_action = ACTION_HELP;
      break;

    case 'i':
      if (S_src != NULL) {
	fclose (S_src);
      }
      if (strcmp (optarg, "-") == 0) {
	S_src = stdin;                  /* special case for stdin */
      } else {
	S_src = fopen (optarg, "rb");
	if (S_src == NULL) {
	  LOG_Fopen (optarg, "rb", __FILE__, __LINE__);
	  rc = 1558;
	}
      }
      break;

    case 'l':
      S_proxy.login = optarg;
      break;

    case 'm':
      fprintf (stderr, "\n%s:%d: Methods are not implemented yet.", __FILE__,
	       __LINE__);
      fprintf (stderr, "  Using WinINET.");
      break;

    case 'o':
      fclose (S_dst);
      S_dst = fopen (optarg, "wb");
      if (S_dst == NULL) {
	LOG_Fopen (optarg, "wb", __FILE__, __LINE__);
	rc = 1206;
      }
      break;

    case 'p':
      S_proxy.hostname = optarg;
      break;

    case 's':
      S_isSaveHeaders = TRUE;
      break;

    case 'x':
      S_proxy.password = optarg;
      break;

    default:
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " Ignoring unexpected command line");
      fprintf (stderr, " option, \"%c\".", c);
    }
  }
  if (S_action == ACTION_RUN) {
    if (optind < argc) {
      S_url = argv[optind++];
      if (optind < argc) {
	fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
	fprintf (stderr, " Ignoring extra arguments on the command");
	fprintf (stderr, " line.");
      }
    } else {
      fprintf (stderr, "\n%s:%d:", __FILE__, __LINE__);
      fprintf (stderr, " Missing URL from the command line.");
      rc = 1517;
    }
  } else {
    assert (S_action == ACTION_HELP);
    /*
     * Action is Help, so we don't check the positional arguments.
     */
  }
  return rc;
}

/*
 */
static void
S_Help ()
{
  printf ("\n%s performs transactions over HTTP.  It can send a payload &",
	  S_progname);
  printf ("\nsave the reply to a destination file.  This functionality can");
  printf ("\nbe used to download individual files from HTTP servers, to");
  printf ("\nupload files to servers, or to execute remote procedure calls");
  printf ("\n(if you prepare the payload & extra headers carefully).");
  printf ("\n");
  printf ("\nUsage:");
  printf ("\n    %s -h", S_progname);
  printf ("\n    %s", S_progname);
  printf (" [-g]");
  printf (" [-m METHOD]");
  printf (" [-i PAYLOAD]");
  printf (" [-o OUTPUT]");
  printf (" [-s]");
  printf (" [-p PROXY]");
  printf (" [-l LOGIN]");
  printf (" [-x PASSWORD]");
  printf (" URL");
  printf ("\n");
  printf ("\nwhere...");
  printf ("\n    URL identifies the remote resource.  This is required.");
  printf ("\n");
  printf ("\n    -h  (Help) print these instructions");
  printf ("\n");
  printf ("\n    -g Enable debugging output.  Default is disabled debugging");
  printf ("\n       output.");
  printf ("\n");
  printf ("\n    -m METHOD tells which networking & HTTP library to use.");
  printf ("\n        Permitted values are \"wininet\" or \"winhttp\".  (It");
  printf ("\n        is case-insensitive.)  Default is \"wininet\".");
  printf ("\n");
  printf ("\n    -i PAYLOAD identifies a file which contains the payload to");
  printf ("\n        send to the server.  If you don't specify this, it");
  printf ("\n        doesn't send any payload, which would be appropriate if");
  printf ("\n        you are just retrieving a file.  A special case is");
  printf ("\n        \"-\", which means to use stdin.");
  printf ("\n");
  printf ("\n    -o OUTPUT identifies a file in which to save the reply.  If");
  printf ("\n        you don't specify this, the reply goes to Standard");
  printf ("\n        Output (STDOUT).");
  printf ("\n");
  printf ("\n    -s Save the reply headers & write them to the OUTPUT.");
  printf ("\n");
  printf ("\n    -p PROXY specifies the HTTP proxy to use.  If you don't");
  printf ("\n        use this option, %s uses the global, default",
	  S_progname);
  printf ("\n        proxy settings.");
  printf ("\n");
  printf ("\n    -l LOGIN is the user name to supply to the proxy.  Without");
  printf ("\n        it, does not supply any user name to the proxy.");
  printf ("\n");
  printf ("\n    -x PASSWORD is the password for the proxy.  Without it,");
  printf ("\n        does not supply any password to the proxy.");
  printf ("\n");
  printf ("\n%s, %s", __DATE__, __TIME__);
  printf ("\n");
}

/*
 */
static int
S_Run ()
{
  int rc = 0;

  assert (S_dst != NULL);
  assert (S_url != NULL);
  if (WINET_Transact (S_url, S_src, S_dst) == 0) {
    /* good */
  } else {
    DEBUG_Print (__FILE__, __LINE__, "WINET_Xtran failed");
    rc = 11;
  }
  return rc;
}

/*
 */
static int
S_Dispatch ()
{
  int rc = 0;

  switch (S_action) {
  case ACTION_HELP:
    S_Help ();
    break;

  case ACTION_RUN:
    rc = S_Run ();
    break;

  default:
    DEBUG_Print (__FILE__, __LINE__,
		 "Unexpected action, %d.  This should never happen!",
		 S_action);
    rc = 12;
  }
  return rc;
}

/*
 */
static void
S_Uninit ()
{
  if (S_src != NULL) {
    fclose (S_src); S_src = NULL;
  }
  if (S_dst != NULL) {
    fclose (S_dst); S_dst = NULL;
  }
}

int
main (int argc, char *argv[])
{
  int rc = 0;

  if (S_Init () == 0) {
    if (S_CommandLine (argc, argv) == 0) {
      if (S_Dispatch () == 0) {
	/* good */
      } else {
	DEBUG_Print (__FILE__, __LINE__, "S_Dispatch failed");
	rc = 1507;
      }
    } else {
      DEBUG_Print (__FILE__, __LINE__, "S_CommandLine failed");
      rc = 1507;
    }
    S_Uninit ();
  } else {
    DEBUG_Print (__FILE__, __LINE__, "S_Init failed");
    rc = 1506;
  }
  return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

/* --- end of file --- */
