W3C home > Mailing lists > Public > www-lib@w3.org > July to September 2003

A better wwwlib example (as a RE to how to return from callback function back to main( )?)

From: Akritidis Xristoforos <cakrit@hol.net>
Date: Fri, 29 Aug 2003 09:37:32 +0300
Message-ID: <AD28A1C5CFD29E448CE44D3E8ECD1974019529F9@mail.hol.net>
To: "Jerry G. Chiuan" <jerry@oridus.com>, <www-lib@w3.org>

I see that people keep coming across the same problems I encountered on
the fateful day I dug my teeth into wwwlib. It was a real nightmare and
confirmed my belief that a library without documentation is basically
unusable, unless you become an expert in it. 

I've become no expert, but I managed to write an api that does http POST
requests with any number of arguments, handles authentication and stores
the result body and headers in two separate strings. It's far from
perfect (see the hard-coded 'outputformat = "xml"' for example, but it
will get you where you're going fast. 

All you need to do is call www_init(), www_request with the options you
want, as many times as you like, and www_terminate() when you're done.
Just make sure you change my custom debug function to something else
(printf, HTprint, whatever...)

You may use this, modify it as you please...
If it becomes good enough, maybe we can put it in the distribution? 

Christopher

#include "WWWLib.h"
#include "WWWHTTP.h"
#include "WWWInit.h"
#include "HTUTree.h"
#include "HTNet.h"
#include "HTAABrow.h"

// variable length string that gets the entire response
HTChunk * result_chunk = NULL;

// Avoid printing progress messages
PUBLIC BOOL HTProgress (HTRequest * request, HTAlertOpcode op,
			int msgnum, const char * dfault, void * input,
			HTAlertPar * reply)
{
    char * msg = HTDialog_progressMessage(request, op, msgnum, dfault,
input);
    if (msg) {
	debug(D_DEBUG,"%s\n", msg);
	HT_FREE(msg);
    }
    if (reply) return YES;
    return YES;
}


// Declaration and constructor for authentication information.
typedef struct _MYBasic {		  /* Basic challenge and
credentials */
  char *	uid;
  char *	pw;
  BOOL	retry;			    /* Should we ask the user again? */
  BOOL	proxy;			    /* Proxy authentication */
} MYBasic;

PRIVATE MYBasic * MYBasic_new(char * username, char* password)
{
  MYBasic * me = NULL;
  if ((me = (MYBasic *) HT_CALLOC(1, sizeof(MYBasic))) == NULL)
    HT_OUTOFMEM("MYBasic_new");
  me->uid = strdup(username); 
  me->pw = strdup(password); 
  me->retry = NO; 
  me->proxy = NO; 
  return me;
}

PRIVATE int printer (const char * fmt, va_list pArgs)
{
  s_debug(D_DEBUG, fmt, pArgs);
  return 0;
}

PRIVATE int tracer (const char * fmt, va_list pArgs)
{
  s_debug(D_ANALYSIS, fmt, pArgs);
  return 0;
}

PRIVATE int terminate_handler (HTRequest * request, HTResponse *
response,
			       void * param, int status) 
{
  char statuscode[64];
  sprintf (statuscode,"%d",status);
  HTResponse_addHeader(response,"status",statuscode);
  HTEventList_stopLoop ();
  if (request && response && param && status) return HT_ERROR;
  return HT_ERROR;
}

void www_init(void) {
  /* Need our own trace and print functions */
  HTPrint_setCallback(printer);
  HTTrace_setCallback(tracer);

  /* Get trace messages */
  if (log_facilities & D_ANALYSIS) {
    HTSetTraceMessageMask("sop");
  }

  /* Add our own filter to update the history list */
  HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);

  /* Set the timeout for long we are going to wait for a response */
  HTHost_setEventTimeout(20000);

  /* Initialize libwww core */
  HTProfile_newNoCacheClient("TestApp", "1.0");

  HTAlert_setInteractive(NO);
}

void www_terminate(void) {
  /* Terminate the Library */
  HTProfile_delete();
}

int www_request (char* outputformat, char **HTMLheader, char **
HTMLresponse, char *url, char *username, char *password, ...) {
  // Everything requires a request stream
  HTRequest * request = HTRequest_new();
  // Structure holding authentication info
  MYBasic * basic;
  // Anchor holding the URL. Need it for POST requests
  HTAnchor * anchor = NULL;
  
  char * cwd = HTGetCurrentDirectoryURL();
  char * absolute_url;
  char * name_value=NULL;
  int RETURNVALUE=0;

  // Get arbitrary number of arguments for the cgi we will call
  // Put the arguments in an association list, to be used in PUT and GET
requests
  HTAssocList * formfields = NULL;

  va_list argsvar;
  va_start (argsvar, password);
  name_value=va_arg(argsvar,char *);
  if (name_value) {
    formfields = HTAssocList_new ();
    do {
      HTParseFormInput(formfields,name_value);
      debug(D_DEBUG,"argument '%s'", name_value);
      name_value=va_arg(argsvar,char *);
    } while (name_value);
  }
  va_end(argsvar);

  if (!url) return 1;

  debug(D_DEBUG,"www_request %s", url);

  // Escape illegal characters. Basically spaces and greek letters
  absolute_url = HTParse(url, cwd, PARSE_ALL);

  /* We want raw output including headers */
  if (strcmp(outputformat,"xml") == 0) {
    HTRequest_setOutputFormat(request, HTAtom_for("text/xml"));
  } else {
    HTRequest_setOutputFormat(request, WWW_SOURCE);
  }
  /* Close connection immediately */
  HTRequest_addConnection(request, "close", "");

  /* Automatic Authentication */
  if (username && password) {
    basic = MYBasic_new(username,password);
    HTBasic_generate (request, basic, 0);
  }

  debug(D_DEBUG,"absolute_url=%s",absolute_url);
  /* Get an anchor object for the URL */
  anchor = HTAnchor_findAddress(absolute_url);

  // Load the url
  if (formfields) {
    // Load with a POST
    result_chunk = HTPostFormAnchorToChunk(formfields, anchor, request);
  
    /* Clean up the form fields */
    HTAssocList_delete(formfields);

  } else {
    // Load with a GET
    result_chunk = HTLoadAnchorToChunk (anchor, request);
  }

  HT_FREE(absolute_url);
  HT_FREE(cwd);
  (*HTMLheader) = NULL;
  (*HTMLresponse) = NULL;

  if (result_chunk) {
    /* Go into the event loop... */
    HTEventList_loop(request);
    (*HTMLresponse) = HTChunk_toCString(result_chunk);
    debug(D_ANALYSIS, "Response : %s", *HTMLresponse);
    // Get headers and status code
    {
      HTResponse *response = HTRequest_response(request);
      if (response) {
	HTAssocList * headers = HTResponse_header(response);
	if (headers) {
	  HTAssoc * pres;
	  (*HTMLheader) = (char *) malloc (sizeof(char) * 1024);
	  (*HTMLheader)[0] = '\0';
	  while ((pres = (HTAssoc *) HTAssocList_nextObject(headers))) {
	    char * name = HTAssoc_name(pres);
	    char * value = HTAssoc_value(pres);
	    if (strcmp(name,"status") == 0) {
	      RETURNVALUE = atoi(value);
	    } else {
	      debug(D_DEBUG,"HEADER %s = %s", name, value);
	      sprintf(*HTMLheader,"%s%s = %s\n",*HTMLheader,name,value);
	    }
	  }
	}
      }
    }

  }

  /* Clean up the request */
  HTRequest_delete(request);
  return RETURNVALUE;
}
Received on Friday, 29 August 2003 02:37:51 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 23 April 2007 18:18:43 GMT