/* Translate by rules ** ------------------ ** The most recently defined rules are applied last. ** This function walks through the list of rules and translates the ** reference when matches are found. The list is traversed in order ** starting from the head of the list. It returns the address of the ** equivalent string allocated from the heap which the CALLER MUST ** FREE. */ PUBLIC char * HTRule_translate (HTList * list, const char * token, BOOL ignore_case) { HTRule * pres; char * replace = NULL; if (!token || !list) return NULL; HTTRACE(APP_TRACE, "Check rules. for `%s\'\n" _ token); while ((pres = (HTRule *) HTList_nextObject(list))) { char * rest = ignore_case ? HTStrCaseMatch(pres->pattern, token) : HTStrMatch(pres->pattern, token); if (!rest) continue; /* No match at all */ /* We found a match for this entry, now do operation */ switch (pres->op) { case HT_Pass: case HT_Map: if (!pres->replace) { /* No replace */ StrAllocCopy(replace, token); } else if (*rest && pres->insert >= 0) { if ((replace = (char *) HT_MALLOC(strlen(pres->replace)+strlen(rest))) == NULL) HT_OUTOFMEM("HTRule_translate"); strcpy(replace, pres->replace); strcpy(replace+pres->insert, rest); } else { /* Perfect match or no insetion point */ StrAllocCopy(replace, pres->replace); } if (pres->op == HT_Pass) { HTTRACE(APP_TRACE, "............ map into `%s'\n" _ replace); return replace; } break; case HT_Fail: default: HTTRACE(APP_TRACE, "............ FAIL `%s'\n" _ token); return NULL; } } if (!replace) StrAllocCopy(replace, token); return replace; }
PRIVATE void Event_trace (HTEvent * event) { if (event) { HTTRACE(ALL_TRACE, "%8p: %3d %6d %8p %8p %8p" _ event _ event->priority _ event->millis _ event->cbf _ event->param _ event->request); } }
PUBLIC int HTEvent_unregister (SOCKET s, HTEventType type) { if (!UnregisterCBF) { HTTRACE(CORE_TRACE, "Event....... No handler registered\n"); return -1; } return (*UnregisterCBF)(s, type); }
PUBLIC BOOL HTResponse_delete (HTResponse * me) { if (me) { HTTRACE(CORE_TRACE, "Response.... Delete %p\n" _ me); /* Access Authentication */ HT_FREE(me->realm); HT_FREE(me->scheme); if (me->challenge) HTAssocList_delete(me->challenge); /* Connection headers */ if (me->connection) HTAssocList_delete(me->connection); /* PEP Information */ if (me->protocol) HTAssocList_delete(me->protocol); if (me->protocol_request) HTAssocList_delete(me->protocol_request); if (me->protocol_info) HTAssocList_delete(me->protocol_info); /* Cache control headers */ if (me->cache_control) HTAssocList_delete(me->cache_control); /* Byte ranges */ if (me->byte_ranges) HTAssocList_delete(me->byte_ranges); /* Transfer Encodings */ if (me->transfer_encoding) HTList_delete(me->transfer_encoding); /* Trailers */ if (me->trailer) HTAssocList_delete(me->trailer); /* Variants */ if (me->variants) HTAssocList_delete(me->variants); /* ** Only delete Content Type parameters and original headers if the ** information is not used elsewhere, for example by the anchor ** object. */ if (!me->cached) { /* Content type parameters */ if (me->type_parameters) HTAssocList_delete(me->type_parameters); /* Content Encodings */ if (me->content_encoding) HTList_delete(me->content_encoding); /* List of all headers */ if (me->headers) HTAssocList_delete(me->headers); } /* HTTP reason string */ if (me->reason) HT_FREE (me->reason); HT_FREE(me); return YES; } return NO; }
PRIVATE int HTFWriter_abort (HTStream * me, HTList * e) { HTTRACE(STREAM_TRACE, "FileWriter.. ABORTING...\n"); if (me) { if (me->leave_open != YES) fclose(me->fp); HT_FREE(me); } return HT_ERROR; }
PUBLIC HTMuxSession * HTMuxSession_register (HTMuxChannel * muxch, HTMuxSessionId sid, HTProtocolId pid) { if (muxch) { HTMuxSession * session = muxch->sessions[sid]; if (session == NULL) { session = session_new(); session->sid = sid; session->pid = pid; muxch->sessions[sid] = session; HTTRACE(MUX_TRACE, "Mux Channel. Registered session %d on channel %p\n" _ sid _ muxch); } return session; } HTTRACE(MUX_TRACE, "Mux Channel. Can't register new session\n"); return NULL; }
PUBLIC HTMuxSessionId HTMuxSession_accept (HTMuxChannel * muxch, HTNet * net, HTProtocolId pid) { if (muxch && net) { HTMuxSession * session; HTMuxSessionId sid = SID_BASE + RECEIVER_OFFSET; for (; sid<MAX_SESSIONS; sid+=2) { if ((session = muxch->sessions[sid]) && session->net == NULL && session->pid == pid) { HTTRACE(MUX_TRACE, "Mux Channel. Accepting session %d on channel %p\n" _ sid _ muxch); return sid; } } } HTTRACE(MUX_TRACE, "Mux Channel. Can't accept new session\n"); return INVSID; }
PUBLIC BOOL HTTimer_registerDeleteTimerCallback (HTTimerSetCallback * cbf) { HTTRACE(CORE_TRACE, "Timer....... registering %p as timer delete cbf\n" _ cbf); if (cbf) { DeletePlatformTimer = cbf; return YES; } return NO; }
PRIVATE int HTXParse_free (HTStream * me) { HTTRACE(STREAM_TRACE, "HTXParse_free\n"); me->eps->finished = YES; (*(me->eps->call_client))(me->eps); /* client will free buffer */ HT_FREE(me->eps); HT_FREE(me); return HT_OK; }
PUBLIC BOOL HTCookie_deleteCallbacks (void) { HTTRACE(APP_TRACE, "Cookie...... Unregistering cookie callbacks\n"); SetCookie = NULL; SetCookieContext = NULL; FindCookie = NULL; FindCookieContext = NULL; return YES; }
/* HTCleanTelnetString() * Make sure that the given string doesn't contain characters that * could cause security holes, such as newlines in ftp, gopher, * news or telnet URLs; more specifically: allows everything between * ASCII 20-7E, and also A0-FE, inclusive. Also TAB ('\t') allowed! * * On entry, * str the string that is *modified* if necessary. The * string will be truncated at the first illegal * character that is encountered. * On exit, * returns YES, if the string was modified. * NO, otherwise. */ PUBLIC BOOL HTCleanTelnetString (char * str) { char * cur = str; if (!str) return NO; while (*cur) { int a = TOASCII((unsigned char) *cur); if (a != 0x9 && (a < 0x20 || (a > 0x7E && a < 0xA0) || a > 0xFE)) { HTTRACE(URI_TRACE, "Illegal..... character in URL: \"%s\"\n" _ str); *cur = 0; HTTRACE(URI_TRACE, "Truncated... \"%s\"\n" _ str); return YES; } cur++; } return NO; }
PRIVATE int HTBoundary_abort (HTStream * me, HTList * e) { int status = HT_ERROR; if (me->target) status = (*me->target->isa->abort)(me->target, e); HTTRACE(PROT_TRACE, "Boundary.... ABORTING...\n"); HT_FREE(me->boundary); HT_FREE(me); return status; }
PUBLIC BOOL HTEvent_delete (HTEvent * me) { if (me) { HT_FREE(me); HTTRACE(CORE_TRACE, "Event....... Deleted event %p\n" _ me); return YES; } return NO; }
PRIVATE int HTZLibInflate_abort (HTStream * me, HTList * e) { HTTRACE(STREAM_TRACE, "Zlib Inflate ABORTING...\n"); ZLib_terminate(me); (*me->target->isa->abort)(me->target, NULL); HT_FREE(me->zstream); HT_FREE(me); return HT_ERROR; }
/* ** Explicitly set the semaphore for this channel */ PUBLIC void HTChannel_setSemaphore (HTChannel * channel, int semaphore) { if (channel) { channel->semaphore = semaphore; if (channel->semaphore <= 0) channel->semaphore = 0; HTTRACE(PROT_TRACE, "Channel..... Semaphore set to %d for channel %p\n" _ channel->semaphore _ channel); } }
/* ** Decrease the semaphore for this channel */ PUBLIC void HTChannel_downSemaphore (HTChannel * channel) { if (channel) { channel->semaphore--; if (channel->semaphore <= 0) channel->semaphore = 0; HTTRACE(PROT_TRACE, "Channel..... Semaphore decreased to %d for channel %p\n" _ channel->semaphore _ channel); } }
/* Delete a AA context from the URL tree ** ------------------------------------- ** Each node in the AA URL tree is a list of the modules we must call ** for this particular node. */ PUBLIC BOOL HTAA_deleteNode (BOOL proxy_access, char const * scheme, const char * realm, const char * url) { HTUTree * tree = NULL; HTAAModule * module = NULL; if (!scheme || !url) { HTTRACE(AUTH_TRACE, "Auth Engine. Bad argument\n"); return NO; } HTTRACE(AUTH_TRACE, "Auth Engine. Deleting info for `%s'\n" _ url); /* Find the AA module with this name */ if ((module = HTAA_findModule(scheme)) == NULL) { HTTRACE(AUTH_TRACE, "Auth Engine. Module `%s\' not registered\n" _ scheme ? scheme : "<null>"); return NO; } /* Find an existing URL Tree or create a new one */ { char * host = HTParse(url, "", PARSE_HOST); char * colon = strchr(host, ':'); int port = DEFAULT_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_new(proxy_access ? AA_PROXY_TREE : AA_TREE, host, port, HTAA_deleteElement); HT_FREE(host); if (!tree) { HTTRACE(AUTH_TRACE, "Auth Engine. Can't create tree\n"); return NO; } } /* Delete any existing node */ { char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION); BOOL status = HTUTree_deleteNode(tree, realm, path); HT_FREE(path); return status; } }
/* ** Searches for NNTP header line until buffer fills up or a CRLF or LF ** is found */ PRIVATE int HTNewsStatus_put_block (HTStream * me, const char * b, int l) { int status; HTHost_setConsumed(me->host, l); while (!me->semi_trans && l-- > 0) { if (me->EOLstate == EOL_FCR) { if (*b == LF) { if (me->junk) me->junk = NO; me->EOLstate = EOL_BEGIN; if ((status = ScanResponse(me)) != HT_LOADED) return status; } } else if (*b == CR) { me->EOLstate = EOL_FCR; } else if (*b == LF) { if (me->junk) me->junk = NO; me->EOLstate = EOL_BEGIN; if ((status = ScanResponse(me)) != HT_LOADED) return status; } else { *(me->buffer+me->buflen++) = *b; if (me->buflen >= MAX_NEWS_LINE) { HTTRACE(PROT_TRACE, "News Status. Line too long - chopped\n"); me->junk = YES; if ((status = ScanResponse(me)) != HT_LOADED) return status; } } b++; } /* ** Now see if we have parts of the body to put down the stream pipe. ** At this point we are looking for CRLF.CRLF. We are guaranteed a stream */ if (l > 0) { int rest = l; const char *ptr = b; while (rest-- > 0) { if (*ptr == CR) { me->EOLstate = me->EOLstate==EOL_DOT ? EOL_SCR : EOL_FCR; } else if (*ptr == '.') { me->EOLstate = me->EOLstate==EOL_FLF ? EOL_DOT : EOL_BEGIN; } else if (*ptr == LF) { me->EOLstate = me->EOLstate>EOL_DOT ? EOL_SLF : EOL_FLF; } else me->EOLstate = EOL_BEGIN; ptr++; } if (me->EOLstate == EOL_SLF) { int status = PUTBLOCK(b, l-5); return status != HT_OK ? status : HT_LOADED; } else { int status = PUTBLOCK(b, l); return status; } } return HT_LOADED; }
/* HTRequest_dup ** ------------- ** Creates a new HTRequest object as a duplicate of the src request. ** Returns YES if OK, else NO */ PUBLIC HTRequest * HTRequest_dup (HTRequest * src) { HTRequest * me; if (!src) return NULL; if ((me = (HTRequest *) HT_MALLOC(sizeof(HTRequest))) == NULL) HT_OUTOFMEM("HTRequest_dup"); memcpy(me, src, sizeof(HTRequest)); HTTRACE(CORE_TRACE, "Request..... Duplicated %p to %p\n" _ src _ me); return me; }
/* HTMemoryCall_deleteAll ** ---------------------- ** Unregisters all call back functions */ PUBLIC BOOL HTMemoryCall_deleteAll (void) { HTTRACE(MEM_TRACE, "Mem Delete.. All Callback functions\n"); if (HTMemCall) { HTList_delete(HTMemCall); HTMemCall = NULL; return YES; } return NO; }
PUBLIC BOOL HTMLUseCharacterSet (HTMLCharacterSet i) { if (i == HTML_ISO_LATIN1) { CurrentEntityValues = ISO_Latin1; return YES; } else { HTTRACE(SGML_TRACE, "HTML Parser. Doesn't support this character set\n"); return NO; } }
PUBLIC HTStream * HTBlackHoleConverter (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream) { HTTRACE(STREAM_TRACE, "BlackHole... Converter Created\n"); HTBaseConverterStreamInstance.isa = &HTBlackHoleConverterClass; return &HTBaseConverterStreamInstance; }
PRIVATE int HTSSLReader_abort (HTInputStream * me, HTList * e) { HTNet * net = HTHost_getReadNet(me->host); HTTRACE(PROT_TRACE, "HTSSLReader. Abort %p\n" _ me); if (net && net->readStream) { int status = (*net->readStream->isa->abort)(net->readStream, NULL); if (status != HT_IGNORE) net->readStream = NULL; } return HT_ERROR; }
/* ** Destroy HTSSL object if no references to it remain in application */ PUBLIC void HTSSL_free (HTSSL * htssl) { (htssl->ref_count)--; HTTRACE(PROT_TRACE, "HTSSL Free.. ref_count = %d\n" _ htssl->ref_count); if (htssl->ref_count == 0) { HTTRACE(PROT_TRACE, "HTSSL.Free.. FINAL RELEASE\n"); if (htssl->ssl) { SSL_free(htssl->ssl); htssl->ssl = NULL; } HTList_removeObject(ssl_list, htssl); /* releases itself */ HT_FREE(htssl); } }
PRIVATE int CSUserList_abort (HTStream * me, HTList * e) { int status = HT_ERROR; if (me->target) status = (*me->target->isa->abort)(me->target, e); HTTRACE(APP_TRACE, "Rules....... ABORTING...\n"); HTChunkFree(me->buffer); /* HTList_delete(me->URLs); */ HT_FREE(me); return status; }
/* ** Allocates memory using calloc */ PUBLIC void * HTMemory_calloc (size_t nobj, size_t size) { void * ptr; ptr = calloc(nobj, LastAllocSize = size); if (ptr != NULL) return ptr; if (HTMemCall) { HTMemoryCallback * pres; size_t total = size * nobj; while ((pres = (HTMemoryCallback *) HTList_nextObject(HTMemCall))) { HTTRACE(MEM_TRACE, "Mem Calling. %p (size %d)\n" _ (void *) pres _ total); (*pres)(total); if ((ptr = calloc(nobj, size)) != NULL) return ptr; } } HTTRACE(MEM_TRACE, "Memory...... Couldn't allocate %d objects of size %d\n" _ nobj _ size); return NULL; }
PRIVATE int HTBufferWriter_abort (HTOutputStream * me, HTList * e) { HTTRACE(STREAM_TRACE, "Buffer...... ABORTING...\n"); if (me->timer) { HTTimer_delete(me->timer); me->timer = NULL; } if (me->target) (*me->target->isa->abort)(me->target, e); return HT_ERROR; }
/* End writing */ PRIVATE int HTMIME_abort (HTStream * me, HTList * e) { int status = HT_ERROR; if (me->target) status = (*me->target->isa->abort)(me->target, e); HTTRACE(PROT_TRACE, "MIME........ ABORTING...\n"); HTChunk_delete(me->token); HTChunk_delete(me->value); HT_FREE(me); return status; }
PUBLIC HTStream * HTCacheCopyHeaders (HTRequest * request, void * param, HTFormat input_format, HTFormat output_format, HTStream * output_stream) { HTTRACE(STREAM_TRACE, "Cache Copy Headers.. Copying headers into the response object\n"); HTMIME_anchor2response (request); return HT_OK; }
PUBLIC BOOL HText_select (HText * text) { if (text) { HTMainText = text; HTMainAnchor = text->node_anchor; display_page(text, text->top_of_screen); return YES; } HTTRACE(SGML_TRACE, "Rendering... Nothing to select!\n"); return NO; }