int optionsURL_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { if (argc == 2) { char *url = argv[1]; if (url) { HTRequest *req = HTRequest_new(); BOOL work; HTChunk *chunk = HTChunk_new(0x2000); HTStream *stream = HTStreamToChunk(req, &chunk, 0); HTRequest_setOutputFormat(req, DEFAULT_FORMAT); HTRequest_setOutputStream(req, stream); HTRequest_setPreemptive(req, YES); work = HTOptionsAbsolute(url, req); Tcl_AppendResult(interp, work ? "YES" : "NO", HTChunkData(chunk), NULL); HT_FREE(url); HTRequest_kill(req); HT_FREE(stream); HTChunkFree(chunk); return TCL_OK; } Tcl_AppendResult(interp, bad_vars, NULL); return TCL_ERROR; } else { Tcl_AppendResult(interp, err_string, argv[0], " url", NULL); return TCL_ERROR; } }
int main (int argc, char ** argv) { HTRequest * request = NULL; HTAnchor * anchor = NULL; char * uri = NULL; /* Create a new premptive client */ HTProfile_newNoCacheClient("UpgradeApp", "1.0"); /* Need our own trace and print functions */ HTPrint_setCallback(printer); HTTrace_setCallback(tracer); /* Set trace messages and alert messages*/ #if 0 HTSetTraceMessageMask("sop"); #endif /* Add our own AFTER filter to terminate the app */ HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* Don't ask - don't tell */ HTAlert_setInteractive(NO); /* Setup a timeout on the request for 15 secs */ HTHost_setEventTimeout(15000); /* Handle command line args */ if (argc >= 2) uri = argv[1]; if (uri && *uri) { /* Create a request */ request = HTRequest_new(); /* Get an anchor object for the URI */ anchor = HTAnchor_findAddress(uri); /* Get the source stream asis */ HTRequest_setOutputFormat(request, WWW_SOURCE); /* Get the source stream asis */ HTRequest_setOutputStream(request, HTFWriter_new(request, stdout, YES)); /* Issue the GET */ if (HTLoadAnchor(anchor, request)) { /* Go into the event loop... */ HTEventList_newLoop(); } } else { HTPrint("Type the URI to get (to test for upgrade).\n"); HTPrint("If an 101 Switching Protocols status is recieved\n"); HTPrint("then print everything following to stdout.\n\n"); HTPrint("\t%s <uri>\n", argv[0]); } return 0; }
int postURL_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { if (argc == 3) { char *url = argv[1]; char *dest = argv[2]; if (url && dest) { HTParentAnchor *source = (HTParentAnchor *) HTAnchor_findAddress(url); HTRequest *req = HTRequest_new(); HTChunk *chunk = HTChunk_new(0x2000); HTStream *stream = HTStreamToChunk(req, &chunk, 0); BOOL work; HTRequest_setOutputFormat(req, DEFAULT_FORMAT); HTRequest_setOutputStream(req, stream); HTRequest_setPreemptive(req, YES); work = HTPostAbsolute (source, dest, req); Tcl_AppendResult(interp, work ? "YES" : "NO", HTChunkData(chunk), NULL); HT_FREE(url); HTRequest_kill(req); HTAnchor_delete(source); HT_FREE(stream); HTChunkFree(chunk); return TCL_OK; } Tcl_AppendResult(interp, bad_vars, NULL); return TCL_ERROR; } else { Tcl_AppendResult(interp, err_string, argv[0], " url destination", NULL); return TCL_ERROR; } }
int main (int argc, char ** argv) { char * uri = NULL; char * cwd = HTGetCurrentDirectoryURL(); /* Create a new premptive client */ HTProfile_newHTMLNoCacheClient ("ShowRDFTriples", "1.0"); /* Need our own trace and print functions */ HTPrint_setCallback(printer); HTTrace_setCallback(tracer); /* Set trace messages */ #if 0 HTSetTraceMessageMask("sopx"); #endif /* Add our own termination filter */ HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* Setup a timeout on the request for 15 secs */ HTHost_setEventTimeout(15000); /* Set up our RDF To Triple conveter stream */ HTFormat_addConversion("text/rdf", "*/*", HTRDFToTriples, 1.0, 0.0, 0.0); /* Handle command line args */ if (argc >= 2) uri = HTParse(argv[1], cwd, PARSE_ALL); HT_FREE(cwd); if (uri) { HTRequest * request = HTRequest_new(); HTAnchor * anchor = HTAnchor_findAddress(uri); BOOL status = NO; /* Set the output stream to stdout */ HTRequest_setOutputStream(request, HTFWriter_new(request, stdout, NO)); /* Start the GET request */ status = HTLoadAnchor(anchor, request); /* Go into the event loop... */ if (status == YES) HTEventList_loop(request); } else { HTPrint("Type the URI to parse\n"); HTPrint("\t%s <uri>\n", argv[0]); HTPrint("For example:\n"); HTPrint("\t%s http://www.yoursite.com/your.rdf\n", argv[0]); } return 0; }
PRIVATE HTRequest * create_request (void) { HTRequest * me = HTRequest_new(); /* set output and debug streans */ HTRequest_setOutputStream(me, HTFWriter_new(me, stdout, YES)); HTRequest_setDebugStream(me, HTFWriter_new(me, stderr, YES)); HTRequest_setOutputFormat(me,HTAtom_for("text/xml")); HTRequest_setDebugFormat(me,WWW_SOURCE); return me; }
int main (int argc, char ** argv) { HTRequest * request; HTProfile_newPreemptiveClient("HTTPHeadApplication", "1.0"); request = HTRequest_new(); #if 0 /* Turn on TRACE so we can see what is going on */ HTSetTraceMessageMask("sop"); #endif /* We don't want any progress notifications */ HTAlert_setInteractive(NO); /* Parse the command line options */ if (argc >= 2) { char * url = argv[1]; /* Set the header field match (if any) */ if (argc >= 3) match = argv[2]; /* Need our own trace and print functions */ HTPrint_setCallback(printer); HTTrace_setCallback(tracer); /* Add our own filter to handle termination */ HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* Set the output format to source and put output to stdout */ HTRequest_setOutputStream(request, HTFWriter_new(request, stdout, YES)); /* Start the load */ if (url && *url) { HTHeadAbsolute(url, request); /* wait until the request has finished */ HTEventList_loop (request); } else HTPrint("Bad parameters - please try again\n"); } else { HTPrint("Type the URL to perform a HEAD request on.\n"); HTPrint("\t%s <url> <header-prefix>\n", argv[0]); HTPrint("where <header-prefix> is the prefix of the header fields\n"); HTPrint("you want to see, for example 'content*. If no \'*\' is used'\n"); HTPrint("then an exact match is needed. Default value is all header fields'\n"); } HTRequest_delete(request); /* Delete the request object */ HTProfile_delete(); return 0; }
/* Partial Response MIME parser stream ** ----------------------------------- ** In case we sent a Range conditional GET we may get back a partial ** response. This response must be appended to the already existing ** cache entry before presented to the user. ** We do this by continuing to load the new object into a temporary ** buffer and at the same time start the cache load of the already ** existing object. When we have loaded the cache we merge the two ** buffers. */ PUBLIC HTStream * HTMIMEPartial (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream) { #ifndef NO_CACHE HTParentAnchor * anchor = HTRequest_anchor(request); HTFormat format = HTAnchor_format(anchor); HTStream * pipe = NULL; /* ** The merge stream is a place holder for where we can put data when it ** arrives. We have two feeds: one from the cache and one from the net. ** We call the stream stack already now to get the right output stream. ** We can do this as we already know the content type from when we got the ** first part of the object. */ HTStream * merge = HTMerge(HTStreamStack(format, output_format, output_stream, request, YES), 2); /* ** Now we create the MIME parser stream in partial data mode. We also ** set the target to our merge stream. */ HTStream * me = HTMIMEConvert(request, param, input_format, output_format, output_stream); me->mode |= HT_MIME_PARTIAL; me->target = merge; #if 0 /* JK: this doesn't work because this work is repeated before */ /* ** Create the cache append stream, and a Tee stream */ { HTStream * append = HTStreamStack(WWW_CACHE_APPEND, output_format, output_stream, request, NO); if (append) me->target = HTTee(me->target, append, NULL); } #endif /* ** Create the pipe buffer stream to buffer the data that we read ** from the network */ if ((pipe = HTPipeBuffer(me->target, 0))) me->target = pipe; /* ** Now start the second load from the cache. First we read this data from ** the cache and then we flush the data that we have read from the net. */ { HTRequest * cache_request = HTRequest_new(); /* ** Set the output format to source and the output stream to the ** merge stream. As we have already set up the stream pipe, we just ** load it as source. */ HTRequest_setOutputFormat(cache_request, WWW_SOURCE); HTRequest_setOutputStream(cache_request, merge); /* ** Bind the anchor to the new request and also register a local ** AFTER filter to flush the pipe buffer so that we can get ** rest of the data through. */ HTRequest_setAnchor(cache_request, (HTAnchor *) anchor); HTRequest_addBefore(cache_request, HTCacheLoadFilter, NULL, NULL, HT_FILTER_FIRST, YES); HTRequest_addAfter(cache_request, HTCacheFlushFilter, NULL, pipe, HT_ALL, HT_FILTER_FIRST, YES); HTTRACE(STREAM_TRACE, "Partial..... Starting cache load\n"); HTLoad(cache_request, NO); } return me; #else return NULL; #endif }
PRIVATE int ServEvent (SOCKET soc, void * pVoid, HTEventType type) { https_info * http = (https_info *)pVoid; int status = HT_ERROR; HTNet * net = http->net; HTRequest * request = HTNet_request(net); if (!net || !request) { HTTRACE(PROT_TRACE, "Serv HTTP... Invalid argument\n"); return HT_ERROR; } if (type == HTEvent_CLOSE) { /* Interrupted */ ServerCleanup(request, net, HT_INTERRUPTED); return HT_OK; } else http = (https_info *) HTNet_context(net); /* Get existing copy */ /* Now jump into the machine. We know the state from the previous run */ while (1) { switch (http->state) { case HTTPS_BEGIN: { /* ** Create the request to handle the request and inherit the old ** context */ HTRequest * client = HTRequest_new(); void * context = HTRequest_context(request); if (context) HTRequest_setContext(client, context); HTRequest_setOutputConnected(client, NO); HTRequest_setGnHd(client, HTRequest_gnHd(request)); HTRequest_setRsHd(client, HTRequest_rsHd(request)); HTRequest_setEnHd(client, HTRequest_enHd(request)); HTList_addObject(http->clients, client); /* ** Create the HTTP output stream for generating the reply ** FROM the client request to the channel */ { HTOutputStream * output = HTNet_getOutput(net, NULL, 0); HTStream * app = HTTPReply_new(client, http,(HTStream*)output); HTRequest_setOutputStream(client, app); HTRequest_setOutputFormat(client, WWW_SOURCE); } http->state = HTTPS_NEED_REQUEST; } break; case HTTPS_NEED_REQUEST: if (type == HTEvent_READ || type == HTEvent_BEGIN) { status = HTHost_read(net->host, net); if (status == HT_WOULD_BLOCK) return HT_OK; else if (status == HT_CLOSED) http->state = HTTPS_OK; else if (status==HT_LOADED || status==HT_PAUSE) { http->state = HTTPS_LOAD_CLIENT; } else http->state = HTTPS_ERROR; } else http->state = HTTPS_ERROR; break; case HTTPS_LOAD_CLIENT: { HTRequest * client = HTList_removeFirstObject(http->clients); HTLoad(client, NO); http->state = HTTPS_BEGIN; break; } case HTTPS_OK: ServerCleanup(request, net, HT_IGNORE); return HT_OK; case HTTPS_ERROR: ServerCleanup(request, net, HT_ERROR); return HT_OK; } } }
int main (int argc, char ** argv) { int status = 0; int arg; int tokencount = 0; BOOL formdata = NO; HTChunk * keywords = NULL; /* From command line */ HTAssocList*formfields = NULL; HTMethod method = METHOD_GET; /* Default value */ ComLine * cl = ComLine_new(); BOOL cache = NO; /* Use persistent cache */ BOOL flush = NO; /* flush the persistent cache */ char * cache_root = NULL; /* Starts Mac GUSI socket library */ #ifdef GUSI GUSISetup(GUSIwithSIOUXSockets); GUSISetup(GUSIwithInternetSockets); #endif #ifdef __MWERKS__ /* STR */ InitGraf((Ptr) &qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); SIOUXSettings.asktosaveonclose = false; argc=ccommand(&argv); #endif /* Initiate W3C Reference Library with a client profile */ HTProfile_newNoCacheClient(APP_NAME, APP_VERSION); /* Need our own trace and print functions */ HTPrint_setCallback(printer); HTTrace_setCallback(tracer); /* ** Delete the default Username/password handler so that we can handle ** parameters handed to us from the command line. The default is set ** by the profile. */ HTAlert_deleteOpcode(HT_A_USER_PW); HTAlert_add(PromptUsernameAndPassword, HT_A_USER_PW); /* ** Add default content decoder. We insert a through line as it doesn't ** matter that we get an encoding that we don't know. */ HTFormat_addCoding("*", HTIdentityCoding, HTIdentityCoding, 0.3); /* Scan command Line for parameters */ for (arg=1; arg<argc; arg++) { if (*argv[arg] == '-') { /* - alone => filter */ if (argv[arg][1] == '\0') { cl->flags |= CL_FILTER; /* -? or -help: show the command line help page */ } else if (!strcmp(argv[arg],"-?") || !strcmp(argv[arg],"-help")) { cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(W3C_HELP); tokencount = 1; /* non-interactive */ } else if (!strcmp(argv[arg], "-n")) { HTAlert_setInteractive(NO); /* Treat the keywords as form data with a <name> "=" <value> */ } else if (!strcmp(argv[arg], "-form")) { formdata = YES; /* from -- Initial represntation (only with filter) */ } else if (!strcmp(argv[arg], "-from")) { cl->format = (arg+1 < argc && *argv[arg+1] != '-') ? HTAtom_for(argv[++arg]) : WWW_HTML; /* to -- Final representation */ } else if (!strcmp(argv[arg], "-to")) { HTFormat format = (arg+1 < argc && *argv[arg+1] != '-') ? HTAtom_for(argv[++arg]) : DEFAULT_FORMAT; HTRequest_setOutputFormat(cl->request, format); /* destination for PUT, POST etc. */ } else if (!strcmp(argv[arg], "-dest")) { if (arg+1 < argc && *argv[arg+1] != '-') { char * dest = HTParse(argv[++arg], cl->cwd, PARSE_ALL); cl->dest = (HTParentAnchor *) HTAnchor_findAddress(dest); HT_FREE(dest); } /* source please */ } else if (!strcmp(argv[arg], "-source")) { HTRequest_setOutputFormat(cl->request, WWW_RAW); /* log file */ } else if (!strcmp(argv[arg], "-l")) { cl->logfile = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : DEFAULT_LOG_FILE; /* Max forward hops in case of TRACE request */ } else if (!strcmp(argv[arg], "-hops") || !strcmp(argv[arg], "-maxforwards")) { int hops = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_HOPS; if (hops >= 0) HTRequest_setMaxForwards(cl->request, hops); /* automated authentication of format user:password@realm */ } else if (!strncmp(argv[arg], "-auth", 5)) { char * credentials = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : NULL; if (credentials) ParseCredentials(cl, credentials); /* rule file */ } else if (!strcmp(argv[arg], "-r")) { cl->rules = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : DEFAULT_RULE_FILE; /* output filename */ } else if (!strcmp(argv[arg], "-o")) { cl->outputfile = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : DEFAULT_OUTPUT_FILE; /* timeout -- Change the default request timeout */ } else if (!strcmp(argv[arg], "-timeout")) { int timeout = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_TIMEOUT; if (timeout >= 1) cl->timer = timeout*MILLIES; /* preemptive or non-preemptive access */ } else if (!strcmp(argv[arg], "-single")) { HTRequest_setPreemptive(cl->request, YES); /* content Length Counter */ } else if (!strcmp(argv[arg], "-cl")) { cl->flags |= CL_COUNT; /* print version and exit */ } else if (!strcmp(argv[arg], "-version")) { VersionInfo(argv[0]); Cleanup(cl, 0); /* run in quiet mode */ } else if (!strcmp(argv[arg], "-q")) { cl->flags |= CL_QUIET; /* Start the persistent cache */ } else if (!strcmp(argv[arg], "-cache")) { cache = YES; /* Determine the cache root */ } else if (!strcmp(argv[arg], "-cacheroot")) { cache_root = (arg+1 < argc && *argv[arg+1] != '-') ? argv[++arg] : NULL; /* Persistent cache flush */ } else if (!strcmp(argv[arg], "-flush")) { flush = YES; /* Do a cache validation */ } else if (!strcmp(argv[arg], "-validate")) { cl->flags |= CL_VALIDATE; /* Do an end-to-end cache-validation */ } else if (!strcmp(argv[arg], "-endvalidate")) { cl->flags |= CL_END_VALIDATE; /* Force complete reload */ } else if (!strcmp(argv[arg], "-nocache")) { cl->flags |= CL_CACHE_FLUSH; #ifdef WWWTRACE /* trace flags */ } else if (!strncmp(argv[arg], "-v", 2)) { HTSetTraceMessageMask(argv[arg]+2); #endif /* GET method */ } else if (!strcasecomp(argv[arg], "-get")) { method = METHOD_GET; /* HEAD method */ } else if (!strcasecomp(argv[arg], "-head")) { method = METHOD_HEAD; /* DELETE method */ } else if (!strcasecomp(argv[arg], "-delete")) { method = METHOD_DELETE; /* POST Method */ } else if (!strcasecomp(argv[arg], "-post")) { method = METHOD_POST; /* PUT Method */ } else if (!strcasecomp(argv[arg], "-put")) { method = METHOD_PUT; /* OPTIONS Method */ } else if (!strcasecomp(argv[arg], "-options")) { method = METHOD_OPTIONS; /* TRACE Method */ } else if (!strcasecomp(argv[arg], "-trace")) { method = METHOD_TRACE; } else { if (SHOW_MSG) HTPrint("Bad Argument (%s)\n", argv[arg]); } } else { /* If no leading `-' then check for URL or keywords */ if (!tokencount) { char * ref = HTParse(argv[arg], cl->cwd, PARSE_ALL); cl->anchor = (HTParentAnchor *) HTAnchor_findAddress(ref); tokencount = 1; HT_FREE(ref); } else if (formdata) { /* Keywords are form data */ char * string = argv[arg]; if (tokencount++ <= 1) formfields = HTAssocList_new(); HTParseFormInput(formfields, string); } else { /* keywords are search tokens */ char * escaped = HTEscape(argv[arg], URL_XALPHAS); if (tokencount++ <= 1) keywords = HTChunk_new(128); else HTChunk_putc(keywords, ' '); HTChunk_puts(keywords, HTStrip(escaped)); HT_FREE(escaped); } } } if (!tokencount && !cl->flags & CL_FILTER) { VersionInfo(argv[0]); Cleanup(cl, 0); } /* Should we use persistent cache? */ if (cache) { HTCacheInit(cache_root, 20); /* Should we start by flushing? */ if (flush) HTCache_flushAll(); } /* ** Check whether we should do some kind of cache validation on ** the load */ if (cl->flags & CL_VALIDATE) HTRequest_setReloadMode(cl->request, HT_CACHE_VALIDATE); else if (cl->flags & CL_END_VALIDATE) HTRequest_setReloadMode(cl->request, HT_CACHE_END_VALIDATE); else if (cl->flags & CL_CACHE_FLUSH) HTRequest_setReloadMode(cl->request, HT_CACHE_FLUSH); /* Add progress notification */ if (cl->flags & CL_QUIET) HTAlert_deleteOpcode(HT_A_PROGRESS); /* Output file specified? */ if (cl->outputfile) { if ((cl->output = fopen(cl->outputfile, "wb")) == NULL) { if (SHOW_MSG) HTPrint("Can't open `%s'\\n",cl->outputfile); cl->output = OUTPUT; } } /* ** Set up the output. Even though we don't use this explicit, it is ** required in order to show the stream stack that we know that we are ** getting raw data output on the output stream of the request object. */ HTRequest_setOutputStream(cl->request, HTFWriter_new(cl->request, cl->output, YES)); /* Setting event timeout */ HTHost_setEventTimeout(cl->timer); /* ** Make sure that the first request is flushed immediately and not ** buffered in the output buffer */ HTRequest_setFlush(cl->request, YES); /* Log file specifed? */ if (cl->logfile) { cl->log = HTLog_open(cl->logfile, YES, YES); if (cl->log) HTNet_addAfter(HTLogFilter, NULL, cl->log, HT_ALL, HT_FILTER_LATE); } /* Just convert formats */ if (cl->flags & CL_FILTER) { #ifdef STDIN_FILENO HTRequest_setAnchor(cl->request, (HTAnchor *) cl->anchor); HTRequest_setPreemptive(cl->request, YES); HTLoadSocket(STDIN_FILENO, cl->request); #endif Cleanup(cl, 0); } /* Content Length Counter */ if (cl->flags & CL_COUNT) { HTRequest_setOutputStream(cl->request, HTContentCounter(HTBlackHole(), cl->request, 0x2000)); } /* Rule file specified? */ if (cl->rules) { char * rules = HTParse(cl->rules, cl->cwd, PARSE_ALL); if (!HTLoadRulesAutomatically(rules)) if (SHOW_MSG) HTPrint("Can't access rules\n"); HT_FREE(rules); } /* Add our own filter to update the history list */ HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* Start the request */ switch (method) { case METHOD_GET: if (formdata) status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor, cl->request); else if (keywords) status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor, cl->request); else status = HTLoadAnchor((HTAnchor *) cl->anchor, cl->request); break; case METHOD_HEAD: if (formdata) { HTRequest_setMethod(cl->request, METHOD_HEAD); status = HTGetFormAnchor(formfields, (HTAnchor *) cl->anchor, cl->request); } else if (keywords) { HTRequest_setMethod(cl->request, METHOD_HEAD); status = HTSearchAnchor(keywords, (HTAnchor *) cl->anchor, cl->request); } else status = HTHeadAnchor((HTAnchor *) cl->anchor, cl->request); break; case METHOD_DELETE: status = HTDeleteAnchor((HTAnchor *) cl->anchor, cl->request); break; case METHOD_POST: if (formdata) { HTParentAnchor * posted = NULL; #if 1 posted = HTPostFormAnchor(formfields, (HTAnchor *) cl->anchor, cl->request); status = posted ? YES : NO; #else /* If we want output to a chunk instead */ post_result = HTPostFormAnchorToChunk(formfields, (HTAnchor *) cl->anchor, cl->request); status = post_result ? YES : NO; #endif } else { if (SHOW_MSG) HTPrint("Nothing to post to this address\n"); status = NO; } break; case METHOD_PUT: status = HTPutDocumentAnchor(cl->anchor, (HTAnchor *) cl->dest, cl->request); break; case METHOD_OPTIONS: status = HTOptionsAnchor((HTAnchor *) cl->anchor, cl->request); break; case METHOD_TRACE: status = HTTraceAnchor((HTAnchor *) cl->anchor, cl->request); break; default: if (SHOW_MSG) HTPrint("Don't know this method\n"); break; } if (keywords) HTChunk_delete(keywords); if (formfields) HTAssocList_delete(formfields); if (status != YES) { if (SHOW_MSG) HTPrint("Sorry, can't access resource\n"); Cleanup(cl, -1); } /* Go into the event loop... */ HTEventList_loop(cl->request); /* Only gets here if event loop fails */ Cleanup(cl, 0); return 0; }
int main (int argc, char ** argv) { ListenTool * ms = ListenTool_new(); int status = HT_ERROR; int arg = 0; /* ** Initiate libwww. Note that we don't call a profile as these set up ** all the client side specific things. Here we just want a very basic ** server which doesn't do anything but forwarding what it reads to ** stdout. */ HTLibInit(APP_NAME, APP_VERSION); /* Set up default event loop */ HTEventInit(); /* Need our own trace and print functions */ HTPrint_setCallback(printer); HTTrace_setCallback(tracer); /* Add our own filter to handle termination */ HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST); /* Check if we should just provide some help */ if (argc==1) { VersionInfo(argv[0]); Cleanup(ms, 0); } /* Scan command Line for parameters */ for (arg=1; arg<argc ; arg++) { if (*argv[arg] == '-') { /* server port */ if (!strncmp(argv[arg], "-p", 2)) { ms->port = (arg+1 < argc && *argv[arg+1] != '-') ? atoi(argv[++arg]) : DEFAULT_PORT; /* Print version and exit */ } else if (!strcmp(argv[arg], "-version")) { VersionInfo(argv[0]); Cleanup(ms, 0); #ifdef HTDEBUG /* trace flags */ } else if (!strncmp(argv[arg], "-v", 2)) { HTSetTraceMessageMask(argv[arg]+2); #endif } else { VersionInfo(argv[0]); Cleanup(ms, 0); } } else { VersionInfo(argv[0]); Cleanup(ms, 0); } } /* Set up a tool to listen on this port */ if (ms->port >= 0) { /* Register TCP as the transport */ HTTransport_add("tcp", HT_TP_SINGLE, HTReader_new, HTWriter_new); /* Register the "noop" application layer protocol for reading */ HTProtocol_add("noop", "tcp", ms->port, NO, NULL, HTLoadSocket); /* Set up the request */ ms->request = HTRequest_new(); HTRequest_setOutputFormat(ms->request, DEFAULT_FORMAT); HTRequest_setOutputStream(ms->request, HTFWriter_new(ms->request, OUTPUT, YES)); /* Start listening on the socket */ HTPrint("Listening on port %d\n", ms->port); if ((status = HTServeAbsolute("noop://localhost", ms->request)) == NO) { HTPrint("Can't listen on port %d\n", ms->port); Cleanup(ms, -1); } /* Go into the event loop... */ if (status == YES) HTEventList_newLoop(); } Cleanup(ms, 0); return 0; }