PUBLIC char HTGetSSLCharacter ARGS1(void *, handle) { char ch; interrupted_in_htgetcharacter = 0; if(!handle) return (char)EOF; do { if (input_pointer >= input_limit) { int status = SSL_read((SSL *)handle, input_buffer, INPUT_BUFFER_SIZE); if (status <= 0) { if (status == 0) return (char)EOF; if (status == HT_INTERRUPTED) { CTRACE((tfp, "HTFormat: Interrupted in HTGetSSLCharacter\n")); interrupted_in_htgetcharacter = 1; return (char)EOF; } CTRACE((tfp, "HTFormat: SSL_read error %d\n", status)); return (char)EOF; /* -1 is returned by UCX at end of HTTP link */ } input_pointer = input_buffer; input_limit = input_buffer + status; } ch = *input_pointer++; } while (ch == (char) 13); /* Ignore ASCII carriage return */ return FROMASCII(ch); }
char *LYKeycodeToString(int c, int upper8) { static char buf[30]; unsigned n; BOOLEAN named = FALSE; for (n = 0; n < TABLESIZE(named_keys); n++) { if (named_keys[n].key == c) { named = TRUE; LYStrNCpy(buf, named_keys[n].name, sizeof(buf) - 1); break; } } if (!named) { if (c <= 0377 && TOASCII(c) > TOASCII(' ') && TOASCII(c) < 0177) sprintf(buf, "%c", c); else if (upper8 && TOASCII(c) > TOASCII(' ') && c <= 0377 && c <= LYlowest_eightbit[current_char_set]) sprintf(buf, "%c", c); else if (TOASCII(c) < TOASCII(' ')) sprintf(buf, "^%c", FROMASCII(TOASCII(c) | 0100)); else if (c >= 0400) sprintf(buf, "key-0x%x", c); else sprintf(buf, "0x%x", c); } return buf; }
/* Decode %xx escaped characters HTUnEscape() * ** ----------------------------- * ** * ** This function takes a pointer to a string in which some * ** characters may have been encoded in %xy form, where xy is * ** the acsii hex code for character 16x+y. * ** The string is converted in place, as it will never grow. * */ char * HTUnEscape (char * str) { char * p = str; char * q = str; /* 16.3.2007 Chris Kronberg: Removed Null entry test. In our case not relevant. */ if (!(p && *p)) return str; while(*p != '\0') { if (*p == HEX_ESCAPE ) { if ( p[1] == '2' && p[2] == '0' ) { /* 16.3.2007 Christine Kronberg */ /* We do not want to decode the whitespace */ *q++ = *p++; } else { p++; if (*p) { *q = HTAsciiHexToChar(*p++) * 16; } #if 1 /* Suggestion from Markku Savela */ if (*p) { *q = FROMASCII(*q + HTAsciiHexToChar(*p)), ++p; } q++; #else if (*p) { *q = FROMASCII(*q + HTAsciiHexToChar(*p)); } p++, q++; #endif } } else { *q++ = *p++; } } *q++ = 0; return str; } /* HTUnEscape */
PRIVATE void NetToText_put_character ARGS2(HTStream *, me, char, net_char) { char c = FROMASCII(net_char); if (me->had_cr) { if (c == LF) { me->sink->isa->put_character(me->sink, '\n'); /* Newline */ me->had_cr = NO; return; } else { me->sink->isa->put_character(me->sink, CR); /* leftover */ } } me->had_cr = (BOOL) (c == CR); if (!me->had_cr) me->sink->isa->put_character(me->sink, c); /* normal */ }
int LYKeyForEditAction(int lec) { int editaction, i; for (i = FIRST_I; i >= 0; i = NEXT_I(i, KEYMAP_SIZE - 1)) { editaction = CurrentLineEditor()[i]; if (editaction == lec) { #ifdef NOT_ASCII if (i < 256) { return FROMASCII(i); } else #endif return i; } } return (-1); }
/* * Given a lynxactioncode, return a key (lynxkeycode) or sequence of two keys * that results in the given action while forms-editing. The main keycode is * returned as function value, possibly with modifier bits set; in addition, if * applicable, a key that sets the required modifier flag is returned in * *pmodkey if (pmodkey!=NULL). Non-lineediting bindings that would require * typing LYE_LKCMD (default ^V) to activate are not checked here, the caller * should do that separately if required. If no key is bound by current * line-editor bindings to the action, -1 is returned. * * This is all a bit long - it is general enough to continue to work should the * three Mod<N>Binding[] become different tables. - kw */ int LYEditKeyForAction(int lac, int *pmodkey) { int editaction, i, c; int mod1found = -1, mod2found = -1, mod3found = -1; if (pmodkey) *pmodkey = -1; for (i = FIRST_I; i >= 0; i = NEXT_I(i, KEYMAP_SIZE - 1)) { editaction = CurrentLineEditor()[i]; #ifdef NOT_ASCII if (i < 256) { c = FROMASCII(i); } else #endif c = i; if (editaction == (lac | LYE_FORM_LAC)) return c; if (editaction == LYE_FORM_PASS) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, c) == lac) return c; #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, c) == lac) return c; } if (editaction == LYE_TAB) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, '\t') == lac) return c; #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, '\t') == lac) return c; } if (editaction == LYE_SETM1 && mod1found < 0) mod1found = i; if (editaction == LYE_SETM2 && mod2found < 0) mod2found = i; if ((editaction & LYE_DF) && mod3found < 0) mod3found = i; } #ifdef USE_ALT_BINDINGS if (mod3found >= 0) { for (i = mod3found; i >= 0; i = NEXT_I(i, LAST_MOD3_LKC)) { editaction = CurrentLineEditor()[i]; if (!(editaction & LYE_DF)) continue; editaction = Mod3Binding[i]; #ifdef NOT_ASCII if (i < 256) { c = FROMASCII(i); } else #endif c = i; if (pmodkey) *pmodkey = c; if (editaction == (lac | LYE_FORM_LAC)) return (c | LKC_MOD3); if (editaction == LYE_FORM_PASS) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, c) == lac) return (c | LKC_MOD3); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, c) == lac) return (c | LKC_MOD3); } if (editaction == LYE_TAB) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, '\t') == lac) return (c | LKC_MOD3); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, '\t') == lac) return (c | LKC_MOD3); } } } if (mod1found >= 0) { if (pmodkey) { #ifdef NOT_ASCII if (mod1found < 256) { *pmodkey = FROMASCII(mod1found); } else #endif *pmodkey = mod1found; } for (i = FIRST_I; i >= 0; i = NEXT_I(i, LAST_MOD1_LKC)) { editaction = Mod1Binding[i]; #ifdef NOT_ASCII if (i < 256) { c = FROMASCII(i); } else #endif c = i; if (editaction == (lac | LYE_FORM_LAC)) return (c | LKC_MOD1); if (editaction == LYE_FORM_PASS) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, c) == lac) return (c | LKC_MOD1); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, c) == lac) return (c | LKC_MOD1); } if (editaction == LYE_TAB) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, '\t') == lac) return (c | LKC_MOD1); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, '\t') == lac) return (c | LKC_MOD1); } } } if (mod2found >= 0) { if (pmodkey) { #ifdef NOT_ASCII if (mod1found < 256) { *pmodkey = FROMASCII(mod1found); } else #endif *pmodkey = mod1found; } for (i = FIRST_I; i >= 0; i = NEXT_I(i, LAST_MOD2_LKC)) { editaction = Mod2Binding[i]; #ifdef NOT_ASCII if (i < 256) { c = FROMASCII(i); } else #endif c = i; if (editaction == (lac | LYE_FORM_LAC)) return (c | LKC_MOD2); if (editaction == LYE_FORM_PASS) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, c) == lac) return (c | LKC_MOD2); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, c) == lac) return (c | LKC_MOD2); } if (editaction == LYE_TAB) { #if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE) if (lynx_edit_mode && !no_dired_support && lac && LKC_TO_LAC(key_override, '\t') == lac) return (c | LKC_MOD2); #endif /* DIRED_SUPPORT && OK_OVERRIDE */ if (LKC_TO_LAC(keymap, '\t') == lac) return (c | LKC_MOD2); } } } #endif /* USE_ALT_BINDINGS */ if (pmodkey) *pmodkey = -1; return (-1); }
/* Push data from a socket down a stream ** ------------------------------------- ** ** This routine is responsible for creating and PRESENTING any ** graphic (or other) objects described by the file. ** ** The file number given is assumed to be a TELNET stream, i.e., containing ** CRLF at the end of lines which need to be stripped to LF for unix ** when the format is textual. ** ** State of socket and target stream on entry: ** socket (file_number) assumed open, ** target (sink) assumed valid. ** ** Return values: ** HT_INTERRUPTED Interruption or error after some data received. ** -2 Unexpected disconnect before any data received. ** -1 Interruption or error before any data received, or ** (UNIX) other read error before any data received, or ** download cancelled. ** HT_LOADED Normal close of socket (end of file indication ** received), or ** unexpected disconnect after some data received, or ** other read error after some data received, or ** (not UNIX) other read error before any data received. ** ** State of socket and target stream on return depends on return value: ** HT_INTERRUPTED socket still open, target aborted. ** -2 socket still open, target stream still valid. ** -1 socket still open, target aborted. ** otherwise socket closed, target stream still valid. */ PUBLIC int HTCopy ARGS4( HTParentAnchor *, anchor, int, file_number, void*, handle GCC_UNUSED, HTStream*, sink) { HTStreamClass targetClass; BOOL suppress_readprogress = NO; int bytes; int rv = 0; /* Push the data down the stream */ targetClass = *(sink->isa); /* Copy pointers to procedures */ /* Push binary from socket down sink ** ** This operation could be put into a main event loop */ HTReadProgress(bytes = 0, 0); for (;;) { int status; if (LYCancelDownload) { LYCancelDownload = FALSE; (*targetClass._abort)(sink, NULL); rv = -1; goto finished; } if (HTCheckForInterrupt()) { _HTProgress (TRANSFER_INTERRUPTED); (*targetClass._abort)(sink, NULL); if (bytes) rv = HT_INTERRUPTED; else rv = -1; goto finished; } #ifdef USE_SSL if (handle) status = SSL_read((SSL *)handle, input_buffer, INPUT_BUFFER_SIZE); else status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); #else status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE); #endif /* USE_SSL */ if (status <= 0) { if (status == 0) { break; } else if (status == HT_INTERRUPTED) { _HTProgress (TRANSFER_INTERRUPTED); (*targetClass._abort)(sink, NULL); if (bytes) rv = HT_INTERRUPTED; else rv = -1; goto finished; } else if (SOCKET_ERRNO == ENOTCONN || #ifdef _WINDOWS /* 1997/11/10 (Mon) 16:57:18 */ SOCKET_ERRNO == ETIMEDOUT || #endif SOCKET_ERRNO == ECONNRESET || SOCKET_ERRNO == EPIPE) { /* * Arrrrgh, HTTP 0/1 compatibility problem, maybe. */ if (bytes <= 0) { /* * Don't have any data, so let the calling * function decide what to do about it. - FM */ rv = -2; goto finished; } else { #ifdef UNIX /* * Treat what we've received already as the complete * transmission, but not without giving the user * an alert. I don't know about all the different * TCP stacks for VMS etc., so this is currently * only for UNIX. - kw */ HTInetStatus("NETREAD"); HTAlert("Unexpected server disconnect."); CTRACE((tfp, "HTCopy: Unexpected server disconnect. Treating as completed.\n")); status = 0; break; #else /* !UNIX */ /* * Treat what we've gotten already * as the complete transmission. - FM */ CTRACE((tfp, "HTCopy: Unexpected server disconnect. Treating as completed.\n")); status = 0; break; #endif /* UNIX */ } #ifdef UNIX } else { /* status < 0 and other errno */ /* * Treat what we've received already as the complete * transmission, but not without giving the user * an alert. I don't know about all the different * TCP stacks for VMS etc., so this is currently * only for UNIX. - kw */ HTInetStatus("NETREAD"); HTAlert("Unexpected read error."); if (bytes) { (void)NETCLOSE(file_number); rv = HT_LOADED; } else { (*targetClass._abort)(sink, NULL); rv = -1; } goto finished; #endif } break; } /* * Suppress ReadProgress messages when collecting a redirection * message, at least initially (unless/until anchor->content_type * gets changed, probably by the MIME message parser). That way * messages put up by the HTTP module or elsewhere can linger in * the statusline for a while. - kw */ suppress_readprogress = (anchor && anchor->content_type && !strcmp(anchor->content_type, "message/x-http-redirection")); #ifdef NOT_ASCII { char * p; for (p = input_buffer; p < input_buffer+status; p++) { *p = FROMASCII(*p); } } #endif /* NOT_ASCII */ (*targetClass.put_block)(sink, input_buffer, status); bytes += status; if (!suppress_readprogress) HTReadProgress(bytes, anchor ? anchor->content_length : 0); HTDisplayPartial(); } /* next bufferload */ _HTProgress(TRANSFER_COMPLETE); (void)NETCLOSE(file_number); rv = HT_LOADED; finished: HTFinishDisplayPartial(); return(rv); }
PRIVATE int HTSSLReader_read (HTInputStream * me) { HTHost * host = me->host; SOCKET soc = HTChannel_socket(me->ch); HTNet * net = HTHost_getReadNet(host); HTRequest * request = HTNet_request(net); int status; if (!net->readStream) { HTTRACE(STREAM_TRACE, "HTSSLReader. No read stream for net object %p\n" _ net); return HT_ERROR; } /* Setting SSL */ if (!me->htssl) { if ((me->htssl = HTSSL_new(soc)) == NULL) { HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO, "SSLREAD"); return HT_ERROR; } } /* Read from socket if we got rid of all the data previously read */ do { /* Don't read if we have to push unwritten data from last call */ if (me->write >= me->read) { me->b_read = 0; me->data[0] ='\0'; me->b_read = HTSSL_read(me->htssl, soc, me->data, INPUT_BUFFER_SIZE); status = HTSSL_getError(me->htssl, me->b_read); HTTRACE(STREAM_TRACE, "HTSSLReader. SSL returned %d\n" _ status); /* Check what we got done */ switch (status) { case SSL_ERROR_NONE: HTTRACEDATA(me->data, me->b_read, "Reading from socket %d" _ soc); me->write = me->data; me->read = me->data + me->b_read; HTTRACE(STREAM_TRACE, "HTSSLReader. %d bytes read from socket %d\n" _ me->b_read _ soc); /* Make progress notification */ if (request) { HTAlertCallback * cbf = HTAlert_find(HT_PROG_READ); if (HTNet_rawBytesCount(net)) HTNet_addBytesRead(net, me->b_read); if (cbf) { int tr = HTNet_bytesRead(net); (*cbf)(request, HT_PROG_READ, HT_MSG_NULL, NULL, &tr, NULL); } } break; case SSL_ERROR_WANT_READ: HTTRACE(STREAM_TRACE, "HTSSLReader. WOULD BLOCK fd %d\n" _ soc); HTHost_register(host, net, HTEvent_READ); /* ** There seems to be a bug as even though it says "read finished" ** it doesn't say that it wants to write. We therefore have to make ** an explicit flush to make sure that we don't block forever. */ HTHost_forceFlush(host); return HT_WOULD_BLOCK; case SSL_ERROR_WANT_WRITE: return HTHost_forceFlush(host); case SSL_ERROR_WANT_X509_LOOKUP: /* @@@ what to do here? @@@ */ return HT_OK; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SSL: case SSL_ERROR_SYSCALL: HTTRACE(PROT_TRACE, "HTSSLReader. FIN received on socket %d\n" _ soc); HTHost_unregister(host, net, HTEvent_READ); HTHost_register(host, net, HTEvent_CLOSE); HTSSL_close(me->htssl); HTSSL_free(me->htssl); me->htssl = NULL; return HT_CLOSED; } } #ifdef FIND_SIGNATURES { char * ptr = me->data; int len = me->b_read; while ((ptr = strnstr(ptr, &len, "HTTP/1.1 200 OK")) != NULL) { HTTRACE(STREAM_TRACE, "HTSSLReader. Signature found at 0x%x of 0x%x.\n" _ ptr - me->data _ me->b_read); ptr++; len--; } } #endif /* FIND_SIGNATURES */ #ifdef NOT_ASCII { char *p = me->data; while (p < me->read) { *p = FROMASCII(*p); p++; } } #endif /* NOT_ASCII */ /* Now push the data down the stream */ if ((status = (*net->readStream->isa->put_block) (net->readStream, me->write, me->b_read)) != HT_OK) { if (status == HT_WOULD_BLOCK) { HTTRACE(STREAM_TRACE, "HTSSLReader. Target WOULD BLOCK\n"); HTHost_unregister(host, net, HTEvent_READ); return HT_WOULD_BLOCK; } else if (status == HT_PAUSE) { HTTRACE(STREAM_TRACE, "HTSSLReader. Target PAUSED\n"); HTHost_unregister(host, net, HTEvent_READ); return HT_PAUSE; /* CONTINUE code or stream code means data was consumed */ } else if (status == HT_CONTINUE || status > 0) { if (status == HT_CONTINUE) { HTTRACE(STREAM_TRACE, "HTSSLReader. CONTINUE\n"); } else HTTRACE(STREAM_TRACE, "HTSSLReader. Target returns %d\n" _ status); /* me->write = me->read; */ return status; } else { /* We have a real error */ HTTRACE(STREAM_TRACE, "HTSSLReader. Target ERROR %d\n" _ status); return status; } } me->write = me->read; { int remaining = HTHost_remainingRead(host); if (remaining > 0) { HTTRACE(STREAM_TRACE, "HTSSLReader. DIDN'T CONSUME %d BYTES: `%s\'\n" _ remaining _ me->read); HTHost_setConsumed(host, remaining); } } } while (net->preemptive); HTHost_register(host, net, HTEvent_READ); return HT_WOULD_BLOCK; }
/* Handle one message ** ------------------ ** ** On entry, ** soc A file descriptor for input and output. ** On exit, ** returns >0 Channel is still open. ** 0 End of file was found, please close file ** <0 Error found, please close file. */ int handle(int soc) { #define COMMAND_SIZE 255 #define MAX_LINES 10000 /* Maximum number of lines returned */ char command[COMMAND_SIZE+1]; char buffer[BUFFER_SIZE]; int status; char * arg; /* Pointer to the argument string */ char * filename; /* Pointer to filename or group list*/ char * keywords; /* pointer to keywords */ char system_command[COMMAND_SIZE+1]; int lines; /* Number of lines returned by EXEC file */ int fd; /* File descriptor number */ int isIndex = 0; /* Is the thing asked for an index? */ for (;;) { status = read(soc, command, COMMAND_SIZE); if (status<=0) { if (TRACE) printf("read returned %i, errno=%i\n", status, errno); return status; /* Return and close file */ } command[status]=0; /* terminate the string */ #ifdef VM { char * p; for (p=command; *p; p++) { *p = FROMASCII(*p); if (*p == '\n') *p = ' '; } } #endif if (TRACE) printf("read string is `%s'\n", command); arg=strchr(command,' '); if (arg) { *arg++ = 0; /* Terminate command */ arg = strip(arg); /* Strip space */ if (0==strcmp("GET", command)) { /* Get a file */ /* Remove host and any punctuation. (Could use HTParse to remove access too @) */ filename = arg; if (arg[0]=='/') { if (arg[1]=='/') { filename = strchr(arg+2, '/'); /* Skip //host/ */ if (!filename) filename=arg+strlen(arg); } else { filename = arg+1; /* Assume root: skip slash */ } } if (*filename) { /* (else return test message) */ keywords=strchr(filename, '?'); if (keywords) *keywords++=0; /* Split into two */ #ifdef VM /* Formats supported by FIND are: ** ** /FIND Help for find general index ** /FIND/ (same) ** /FIND/? (same) ** /FIND/group.disk.ft.fn Get a document from a disk- NOT INDEX ** /FIND/grouplist? Help for group index ** /FIND/grouplist?keylist Search a set of disks for keywords ** where grouplist = group+group+group.. or void ** keylist = key+key+key... (not void) */ if(( (0==strncmp(filename,"FIND",4)) || (0==strncmp(filename,"find",4)) ) && ( (filename[4]==0) || (filename[4]=='/') || (filename[4]='?') )) { filename=filename+4; if (*filename=='/') filename++; /* Skip first slash */ if (!*filename) { /* If no data at all, */ if (!keywords) keywords = filename; /* Respond as if just "?" given */ } if (keywords) { char *p; while((p=strchr(filename,'+'))!=0) *p=' ';/* Remove +s */ while((p=strchr(keywords,'+'))!=0) *p=' ';/* Remove +s */ if (!*keywords) { /* If no keywords */ write_ascii(soc, "<IsIndex><TITLE>"); write_ascii(soc, filename); write_ascii(soc, " keyword index</TITLE>\n"); if (*filename) { write_ascii(soc, "This index covers groups: `"); write_ascii(soc, filename); write_ascii(soc, "'"); } else { write_ascii(soc, "This is the general CERN public document index"); } write_ascii(soc, ".<P>You may use your browser's keyword search on this index.<P>\n"); return 0; } strcpy(system_command,"EXEC NICFIND1 "); strcat(system_command, keywords); if (*filename) { strcat(system_command, " ( "); strcat(system_command, filename); } isIndex = 1; } else { strcpy(system_command,"EXEC NICFOUN1 "); strcat(system_command, filename); isIndex = 0; } } /* if FIND */ /* Formats supported by NEWS are: ** ** /NEWS General news ** /NEWS/grouplist News for given groups ** /NEWS/grouplist? All news for all given groups ** /NEWS/grouplist?keylist Search news for keywords ** where grouplist = group+group+group.. or void ** keylist = key+key+key... (can be void) */ else if(( (0==strncmp(filename,"NEWS",4)) || (0==strncmp(filename,"news",4)) ) && ( (filename[4]==0) || (filename[4]=='/') || (filename[4]='?') )) { isIndex = 1; filename=filename+4; if (*filename=='/') filename++; /* Skip first slash */ if (!*filename) { /* If no data at all, */ if (!keywords) keywords = filename; /* Respond as if just "?" given */ } if (!keywords) keywords = ""; /* "If nun, write none"-1066 */ { char *p; while((p=strchr(filename,'+'))!=0) *p=' ';/* Remove +s */ while((p=strchr(keywords,'+'))!=0) *p=' ';/* Remove +s */ strcpy(system_command,"EXEC NICFIND1 "); if (keywords) strcat(system_command, keywords); strcat(system_command, " ( NEWS "); if (*filename) { strcat(system_command, "("); strcat(system_command, filename); strcat(system_command, ") "); } } } else { /* not FIND or NEWS */ write_ascii(soc, "Bad syntax. No such document.\n"); return 0; } /* Execute system command and get the results */ lines = system(system_command); if (TRACE) printf("Command `%s' returned %i lines.\n", system_command, lines); if (lines<=0) { write_ascii(soc, "\nSorry, the FIND server could not execute\n `"); write_ascii(soc, system_command); write_ascii(soc, "'\n\n"); return 0; } /* Copy the file across: */ if (isIndex) write_ascii(soc, "<IsIndex>\n"); for(;lines; lines--){ /* Speed necessary here */ char *p; fgets(buffer, BUFFER_SIZE, stdin); /* if (strcmp(buffer,"<END_OF_FILE>")==0) break; */ for(p=buffer; *p; p++) *p = TOASCII(*p); write(soc, buffer, p-buffer); } return 0; #else fd = open(arg, O_RDONLY, 0 ); /* un*x open @@ */ if (fd<0) return fd; status = read_file(soc, fd); close(fd); return 0; #endif } } } write_ascii(soc, "<h1>FIND Server v1.03</h1><h2>Test response</h2>\n"); write_ascii(soc, "\n\nThe (unrecognised) command used was `"); write_ascii(soc, command); write_ascii(soc, "'.\n\n"); if (TRACE) printf("Return test string written back'\n"); return 0; /* End of file - please close socket */ } /* for */ } /* handle */
PRIVATE void HTMIME_put_character ARGS2(HTStream *, me, char, c) { if (me->state == MIME_TRANSPARENT) { (*me->targetClass.put_character)(me->target, c);/* MUST BE FAST */ return; } /* This slightly simple conversion just strips CR and turns LF to ** newline. On unix LF is \n but on Mac \n is CR for example. ** See NetToText for an implementation which preserves single CR or LF. */ if (me->net_ascii) { c = FROMASCII(c); if (c == CR) return; else if (c == LF) c = '\n'; } switch(me->state) { case MIME_IGNORE: return; case MIME_TRANSPARENT: /* Not reached see above */ (*me->targetClass.put_character)(me->target, c); return; case MIME_NET_ASCII: (*me->targetClass.put_character)(me->target, c); /* MUST BE FAST */ return; case NEWLINE: if (c != '\n' && WHITE(c)) { /* Folded line */ me->state = me->fold_state; /* pop state before newline */ break; } /* else Falls through */ case BEGINNING_OF_LINE: switch(c) { case 'c': case 'C': me->check_pointer = "ontent-t"; me->if_ok = CONTENT_T; me->state = CHECK; break; case '\n': /* Blank line: End of Header! */ { if (TRACE) fprintf(stderr, "HTMIME: MIME content type is %s, converting to %s\n", HTAtom_name(me->format), HTAtom_name(me->targetRep)); me->target = HTStreamStack(me->format, me->request, NO); if (!me->target) { if (TRACE) fprintf(stderr, "MIME: Can't translate! ** \n"); me->target = me->sink; /* Cheat */ } if (me->target) { me->targetClass = *me->target->isa; /* Check for encoding and select state from there @@ */ me->state = MIME_TRANSPARENT; /* From now push straigh through */ } else { me->state = MIME_IGNORE; /* What else to do? */ } } break; default: goto bad_field_name; break; } /* switch on character */ break; case CHECK: /* Check against string */ if (TOLOWER(c) == *(me->check_pointer)++) { if (!*me->check_pointer) me->state = me->if_ok; } else { /* Error */ if (TRACE) fprintf(stderr, "HTMIME: Bad character `%c' found where `%s' expected\n", c, me->check_pointer - 1); goto bad_field_name; } break; case CONTENT_T: switch(c) { case 'r': case 'R': me->check_pointer = "ansfer-encoding:"; me->if_ok = CONTENT_TRANSFER_ENCODING; me->state = CHECK; break; case 'y': case 'Y': me->check_pointer = "pe:"; me->if_ok = CONTENT_TYPE; me->state = CHECK; break; default: goto bad_field_name; } /* switch on character */ break; case CONTENT_TYPE: case CONTENT_TRANSFER_ENCODING: me->field = me->state; /* remember it */ me->state = SKIP_GET_VALUE; /* Fall through! */ case SKIP_GET_VALUE: if (c == '\n') { me->fold_state = me->state; me->state = NEWLINE; break; } if (WHITE(c)) break; /* Skip white space */ me->value_pointer = me->value; me->state = GET_VALUE; /* Fall through to store first character */ case GET_VALUE: if (WHITE(c)) { /* End of field */ *me->value_pointer = 0; switch (me->field) { case CONTENT_TYPE: me->format = HTAtom_for(me->value); break; case CONTENT_TRANSFER_ENCODING: me->encoding = HTAtom_for(me->value); break; default: /* Should never get here */ break; } } else { if (me->value_pointer < me->value + VALUE_SIZE - 1) { *me->value_pointer++ = c; break; } else { goto value_too_long; } } /* Fall through */ case JUNK_LINE: if (c == '\n') { me->state = NEWLINE; me->fold_state = me->state; } break; } /* switch on state*/ return; value_too_long: if (TRACE) fprintf(stderr, "HTMIME: *** Syntax error. (string too long)\n"); bad_field_name: /* Ignore it */ me->state = JUNK_LINE; return; }
/* Handle one message ** ------------------ ** ** On entry, ** soc A file descriptor for input and output. ** On exit, ** returns >0 Channel is still open. ** 0 End of file was found, please close file ** <0 Error found, please close file. */ PUBLIC int HTHandle ARGS1(int, soc) { #define COMMAND_SIZE 2048 /* @@@@ WAIS queries can be big! */ #define MAX_LINES 10000 /* Maximum number of lines returned */ char command[COMMAND_SIZE+1]; char *keywords; /* pointer to keywords in address */ int status; char * arg; /* Pointer to the argument string */ time_t theTime; /* A long integer giving the datetime in secs */ for (;;) { int allocated = COMMAND_SIZE; command = (char *)malloc(allocated+1); if (!command) { fprintf(stderr, "Daemon: insufficient memrory!\n"); exit(-5); } for(;;) { if (allocated - bytes_read < MINIMUM_READ) { allocated = allocated + ALLOCATION_UNIT; command = (char *)realloc(command, allocated+1); if (!command) { fprintf(stderr, "Daemon: No memory to reallocate command!!\n"); exit(-6); } } status = NETREAD(soc, command + bytes_read, allocated - bytes_read); if (TRACE) fprintf(stderr, "NETREAD returned %d, errono=%d\n", status, errno); if (status<=0) { free(command); return status; /* Return and close file */ } { char * p= command + bytes_read; for(p=command + bytes_read; p < command + bytes_read + status; p++) { if (!*p) { free(command); return -1; /* No LF */ } if (*p==10) { break; } } bytes_read = bytes_read + status; if (p=command+bytes_read)/* No terminators yet */ continue; } break;/* Terminator found */ } command[bytes_read]=0; /* terminate the string */ #ifdef NOT_ASCII { char * p; for (p=command; *p; p++) { *p = FROMASCII(*p); if (*p == '\n') *p = ' '; } } #endif /* Log the call: */ if (logfile) { time(&theTime); fprintf(logfile, "%24.24s %s %s", ctime(&theTime), HTClientHost, command); fflush(logfile); /* Actually update it on disk */ if (TRACE) printf("Log: %24.24s %s %s", ctime(&theTime), HTClientHost, command); } arg=strchr(command,' '); if (arg) { int stat; *arg++ = 0; /* Terminate command */ arg = strip(arg); /* Strip space */ if (0==strcmp("GET", command)) { /* Get a file */ keywords=strchr(arg, '?'); if (keywords) *keywords++=0; /* Split into two */ stat = HTRetrieve(arg, keywords, soc); free(command); return stat; } } /* Space found supplied */ HTWriteASCII(soc, "<h1>HTTP Server v1.02</h1><h2>Test response</h2>\n"); HTWriteASCII(soc, "\n\nThe (unrecognised) command used was `"); HTWriteASCII(soc, command); HTWriteASCII(soc, "'.\n\n"); if (TRACE) printf("Return test string written back'\n"); free(command); return 0; /* End of file - please close socket */ } /* for */ } /* handle */