?? htgopher.c
字號(hào):
cont = me->CSO ? GopherCSOLine(me, me->buffer) : GopherMenuLine(me, me->buffer); if (cont == NO) return HT_LOADED; } else me->junk = NO; /* back to normal */ } me->buflen = 0; me->state = EOL_BEGIN; } else if (*b == CR) { me->state = EOL_FCR; } else if (*b == LF && me->buflen) { if (!me->junk) { BOOL cont; *(me->buffer+me->buflen) = '\0'; cont = me->CSO ? GopherCSOLine(me, me->buffer) : GopherMenuLine(me, me->buffer); if (cont == NO) return HT_LOADED; } else me->junk = NO; /* back to normal */ me->buflen = 0; me->state = EOL_BEGIN; } else { *(me->buffer+me->buflen++) = *b; if (me->buflen >= MAX_GOPHER_LINE) { HTTRACE(PROT_TRACE, "Gopher...... Line too long - ignored\n"); me->buflen = 0; me->junk = YES; } } b++; } return HT_OK;}PRIVATE int GopherMenu_put_string (HTStream * me, const char* s){ return GopherMenu_put_block(me, s, (int) strlen(s));}PRIVATE int GopherMenu_put_character (HTStream * me, char c){ return GopherMenu_put_block(me, &c, 1);}PRIVATE int GopherMenu_flush (HTStream * me){ return (*me->target->isa->flush)(me->target);}PRIVATE int GopherMenu_free (HTStream * me){ int status = HT_OK; GopherBottom(me); if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; HT_FREE(me); return HT_OK;}PRIVATE int GopherMenu_abort (HTStream * me, HTList * e){ (*me->target->isa->abort)(me->target, e); HT_FREE(me); HTTRACE(PROT_TRACE, "Gopher...... ABORTING...\n"); return HT_ERROR;}/* Goper Menu Stream** -----------------*/PRIVATE const HTStreamClass GopherMenuClass ={ "GopherMenu", GopherMenu_flush, GopherMenu_free, GopherMenu_abort, GopherMenu_put_character, GopherMenu_put_string, GopherMenu_put_block};/*** Stream for creating a HTML object out of a Gopher Menu object*/PRIVATE HTStream * GopherMenu_new (HTRequest * request, char *url, BOOL CSO){ HTStream * me; if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL) HT_OUTOFMEM("GopherMenu_new"); me->isa = &GopherMenuClass; me->target = HTMLGenerator(request, NULL, WWW_HTML, HTRequest_outputFormat(request), HTRequest_outputStream(request)); HTAnchor_setFormat(HTRequest_anchor(request), WWW_HTML); me->request = request; me->state = EOL_BEGIN; me->url = url; me->CSO = CSO; GopherTitle(me); return me;}/* ------------------------------------------------------------------------- *//* GOPHER STATE MACHINE *//* ------------------------------------------------------------------------- *//* GopherCleanup** -------------** This function closes the connection and frees memory.** Returns YES if OK, else NO*/PRIVATE BOOL GopherCleanup (HTRequest * request, int status){ HTNet * net = HTRequest_net(request); gopher_info * gopher = (gopher_info *) HTNet_context(net); HTStream * input = HTRequest_inputStream(request); /* Free stream with data TO network */ if (input) { if (status == HT_INTERRUPTED) (*input->isa->abort)(input, NULL); else (*input->isa->_free)(input); } /* Remove the request object and our own context structure for gopher */ HTNet_delete(net, status); if (gopher) { HT_FREE(gopher->cmd); HT_FREE(gopher); } return YES;}/* Display a Gopher Index document** -------------------------------** We create a small HTML object as we have no network activity*/PRIVATE void display_index (HTRequest * request){ HTParentAnchor * anchor = HTRequest_anchor(request); HTStructured *target = HTMLGenerator(request, NULL, WWW_HTML, HTRequest_outputFormat(request), HTRequest_outputStream(request)); /* Update anchor information */ HTAnchor_setFormat(anchor, WWW_HTML); HTAnchor_setTitle(anchor, "Searchable Gopher Index"); /* @@@ We don't set Content-Length */ START(HTML_HTML); START(HTML_HEAD); START(HTML_TITLE); PUTS("Searchable Gopher Index"); END(HTML_TITLE); END(HTML_HEAD); START(HTML_BODY); START(HTML_H1); PUTS("Searchable Gopher Index"); END(HTML_H1); START(HTML_ISINDEX); END(HTML_BODY); END(HTML_HTML); (*target->isa->_free)(target);}/* Display a CSO index document** -------------------------------** We create a small HTML object as we have no network activity*/PRIVATE void display_cso (HTRequest * request){ HTParentAnchor * anchor = HTRequest_anchor(request); HTStructured *target = HTMLGenerator(request, NULL, WWW_HTML, HTRequest_outputFormat(request), HTRequest_outputStream(request)); /* Update anchor information */ HTAnchor_setFormat(anchor, WWW_HTML); HTAnchor_setTitle(anchor, "Searchable SCO Index"); /* @@@ We don't set Content-Length */ START(HTML_HTML); START(HTML_HEAD); START(HTML_TITLE); PUTS("Searchable Index of a CSO Name Server"); END(HTML_TITLE); END(HTML_HEAD); START(HTML_BODY); START(HTML_H1); PUTS("Searchable Index of a CSO Name Server"); END(HTML_H1); PUTS("A CSO Name Server usually provides directory information about people."); START(HTML_ISINDEX); END(HTML_BODY); END(HTML_HTML); (*target->isa->_free)(target);}/* HTLoadGopher** ------------** Given a hypertext address, this routine loads a gopher document**** On entry,** request This is the request structure** On Exit** returns HT_ERROR Error has occured in call back** HT_OK Call back was OK*/PRIVATE int GopherEvent (SOCKET soc, void * pVoid, HTEventType type);PUBLIC int HTLoadGopher (SOCKET soc, HTRequest * request){ gopher_info * gopher; HTNet * net = HTRequest_net(request); HTParentAnchor * anchor = HTRequest_anchor(request); char * url = HTAnchor_physical(anchor); /* ** Initiate a new gopher structure and bind to request structure ** This is actually state GOPHER_BEGIN, but it can't be in the state ** machine as we need the structure first. */ HTTRACE(PROT_TRACE, "Gopher...... Looking for `%s\'\n" _ url); if ((gopher = (gopher_info *) HT_CALLOC(1, sizeof(gopher_info))) == NULL) HT_OUTOFMEM("HTLoadGopher"); gopher->type = GT_MENU; gopher->state = GOPHER_BEGIN; gopher->net = net; HTNet_setContext(net, gopher); HTNet_setEventCallback(net, GopherEvent); HTNet_setEventParam(net, gopher); /* callbacks get http* */ return GopherEvent(soc, gopher, HTEvent_BEGIN); /* get it started - ops is ignored */}PRIVATE int GopherEvent (SOCKET soc, void * pVoid, HTEventType type){ gopher_info * gopher = (gopher_info *)pVoid; int status = HT_ERROR; HTNet * net = gopher->net; HTRequest * request = HTNet_request(net); HTParentAnchor * anchor = HTRequest_anchor(request); HTHost * host = HTNet_host(net); char * url = HTAnchor_physical(anchor); if (type == HTEvent_CLOSE) { /* Interrupted */ GopherCleanup(request, HT_INTERRUPTED); return HT_OK; } else gopher = (gopher_info *) HTNet_context(net); /* Get existing copy */ /* Now jump into the machine. We know the state from the previous run */ while (1) { switch (gopher->state) { case GOPHER_BEGIN: /* Get entity type, and selector string */ { char *path = HTParse(url, "", PARSE_PATH); char *selector = path; char *query = NULL; char *separator = NULL; if (*selector) gopher->type = (HTGopherType) *selector++; if (gopher->type == GT_INDEX) { HTAnchor_setIndex(anchor); /* Is index */ query = strchr(selector, '?'); /* Display local cover page only if no search requested */ if (!query || !*(query+1)) { /* No search required */ display_index(request); gopher->state = GOPHER_GOT_DATA; HT_FREE(path); break; } else { *query++ = 0; /* Skip '?' */ separator = "\t"; } } else if (gopher->type == GT_CSO) { HTAnchor_setIndex(anchor); /* Search is allowed */ query = strchr(selector, '?'); /* Look for search string */ /* Display local cover page only if no search requested */ if (!query || !*(query+1)) { /* No search required */ display_cso(request); gopher->state = GOPHER_GOT_DATA; HT_FREE(path); break; } else { *query++ = 0; /* Skip '?' */ *selector = 0; separator = "query "; } } /* Now generate the final command */ { char crlf[3]; StrAllocCopy(gopher->cmd, selector); if (query) { char *p; for (p=query; *p; p++) /* Remove plus signs 921006 */ if (*p == '+') *p = ' '; StrAllocCat(gopher->cmd, separator); StrAllocCat(gopher->cmd, query); } HTUnEscape(gopher->cmd); HTCleanTelnetString(gopher->cmd); /* Prevent sec holes */ *crlf = CR; /* Telnet termination */ *(crlf+1) = LF; *(crlf+2) = '\0'; StrAllocCat(gopher->cmd, crlf); } HT_FREE(path); gopher->state = GOPHER_NEED_CONNECTION; } break; case GOPHER_NEED_CONNECTION: status = HTHost_connect(host, net, url); host = HTNet_host(net); if (status == HT_OK) { /* ** Check the protocol class to see if we have connected to a ** the right class of server, in this case HTTP. */ { HTHost * host = HTNet_host(net); char * s_class = HTHost_class(host); if (s_class && strcasecomp(s_class, "gopher")) { HTRequest_addError(request, ERR_FATAL, NO, HTERR_CLASS, NULL, 0, "HTLoadGopher"); gopher->state = GOPHER_ERROR; break; } HTHost_setClass(host, "gopher"); } /* ** Create the stream pipe FROM the channel to the application. ** The target for the input stream pipe is set up using the ** stream stack. */ { if (gopher->type == GT_MENU || gopher->type == GT_INDEX) net->readStream = GopherMenu_new(request, url, NO); else if (gopher->type == GT_CSO) net->readStream = GopherMenu_new(request, url, YES); else net->readStream = HTStreamStack(WWW_UNKNOWN, HTRequest_outputFormat(request), HTRequest_outputStream(request), request, NO); HTRequest_setOutputConnected(request, YES); } /* ** Create the stream pipe TO the channel from the application ** and hook it up to the request object */ { HTOutputStream * output = HTNet_getOutput(net, NULL, 0); HTRequest_setInputStream(request, (HTStream *) output); } gopher->state = GOPHER_NEED_REQUEST; } else if (status == HT_WOULD_BLOCK) return HT_OK; else gopher->state = GOPHER_ERROR; break; case GOPHER_NEED_REQUEST: HTTRACE(PROT_TRACE, "Gopher Tx... `%s\'" _ gopher->cmd); { HTStream * input = HTRequest_inputStream(request); status = (*input->isa->put_block) (input, gopher->cmd, strlen(gopher->cmd)); if (status == HT_WOULD_BLOCK) return HT_OK; else if (status == HT_ERROR) gopher->state = GOPHER_ERROR; else gopher->state = GOPHER_NEED_RESPONSE; } break; case GOPHER_NEED_RESPONSE: status = HTHost_read(net->host, net); if (status == HT_WOULD_BLOCK) return HT_OK; else if (status == HT_LOADED || status == HT_CLOSED) gopher->state = GOPHER_GOT_DATA; else gopher->state = GOPHER_ERROR; break; case GOPHER_GOT_DATA: GopherCleanup(request, HT_LOADED); return HT_OK; break; case GOPHER_NO_DATA: GopherCleanup(request, HT_NO_DATA); return HT_OK; break; case GOPHER_ERROR: GopherCleanup(request, HT_ERROR); return HT_OK; break; } } /* while(1) */}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -