RE: HTTP Authentication with libwww + POST + XML + arguments + headers

Hi,

Thank you so much for this helpful bit of code.  I now see how the 
authentication is supposed to work and I have gotten it to work 
successfully.

Thanks again,

Erik.

On Fri, 19 Sep 2003, Akritidis Xristoforos wrote:

> 
>  
> > As I see from the mailing list postings, this issue is covered
> frequently.
> > I'm still having trouble!  I got a great deal of help from Josh Watts'
> > posting back in 2001, but my application still isn't working.
> 
> I believe I sent some code on this, not long ago. I have been using the
> code that follows as a generic http request library. The only things I
> haven't implemented that I might are saving the ftp results (I only
> check if it the file is there) and ssl. Look for 'basic' authentication
> below and you'll be ok. All you need to use the library is define your
> own debug function.
> 
> Changed the subject to add some keywords.
> 
> /* wwwapi.h */
> 
> #ifdef __cplusplus
> extern "C" {
> #endif
> 
> extern void www_init (void);
> extern void www_terminate (void);
> extern int www_request (char* outputformat, char **HTMLheader, char **
> HTMLresponse, char *url, char *username, char *password, ...);
> 
> #ifdef __cplusplus
> }
> #endif
> 
> 
> #include "wwwapi.h"
> #include "WWWHTTP.h"
> #include "WWWInit.h"
> #include "HTUTree.h"
> #include "HTNet.h"
> #include "HTAABrow.h"
> 
> 
> /*
> ** Local context structure used in the HTNet object.
> */
> typedef enum _HTFTPState {
>     FTP_SUCCESS	= -2,
>     FTP_ERROR = -1,
>     FTP_BEGIN = 0,
>     FTP_NEED_CCON,				       /* Control
> connection */
>     FTP_NEED_LOGIN,
>     FTP_NEED_DCON,					  /* Data
> connection */
>     FTP_NEED_DATA,
>     FTP_NEED_SERVER				   /* For directory
> listings */
> } HTFTPState;
> 
> typedef struct _ftp_ctrl {
>     HTChunk *		cmd;
>     int			repcode;
>     char *		reply;
>     char *		uid;
>     char *		passwd;
>     char *		account;
>     HTFTPState     	state;			  /* State of the
> connection */
>     int 		substate;		  /* For hierarchical
> states */
>     BOOL		sent;			    /* Read or write
> command */
>     BOOL		cwd;					 /* Done
> cwd */
>     BOOL		reset;			 	  /* Expect
> greeting */
>     FTPServerType	server;		         	   /* Type of
> server */
>     HTNet *		cnet;			       /* Control
> connection */
>     HTNet *		dnet;			   	  /* Data
> connection */
>     BOOL		alreadyLoggedIn;
> } ftp_ctrl;
> 
> // 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) return status;
>   return status;
> }
> 
> 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();
>   // Anchor holding the URL. Need it for POST requests
>   HTAnchor * anchor = NULL;
>   // Structure holding authentication info
>   MYBasic * basic;
>   /* ftp Automatic Authentication */
>   HTNet * cnet; 
>   ftp_ctrl * ctrl; 
> 
>   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;
> 
>   // Set the username and password for ftp requests
>   if (strcmp("ftp",outputformat) == 0) {
>     cnet = HTRequest_net(request);
>     ctrl = (ftp_ctrl *) HTNet_context(cnet);
>     if (ctrl) {
>       StrAllocCopy(ctrl->uid, username);
>       StrAllocCopy(ctrl->passwd, password);
>     }
>   }
> 
>   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 Wednesday, 24 September 2003 16:19:40 UTC