PUBLIC BOOL HTMuxProtocol_delete (HTMuxChannel * muxch, HTProtocolId pid) { if (muxch && muxch->protocols) { HTList * cur = muxch->protocols; HTMuxProtocol * pres; while ((pres = (HTMuxProtocol *) HTList_nextObject(cur))) { if (pres->pid == pid) { HTList_removeObject(muxch->protocols, pres); HT_FREE(pres); return YES; } } } return NO; }
/* ** Rule Translation BEFORE Filter ** ------------------------------ ** If we have a set of rules loaded (see the Rule manager) then check ** before each request whether how that should be translated. The trick ** is that a parent anchor has a "address" which is the part from the URL ** we used when we created the anchor. However, it also have a "physical ** address" which is the place we are actually going to look for the ** resource. Hence this filter translates the physical address ** (if any translations are found) */ PUBLIC int HTRuleFilter (HTRequest * request, void * param, int mode) { HTList * list = HTRule_global(); HTParentAnchor * anchor = HTRequest_anchor(request); char * addr = HTAnchor_physical(anchor); char * physical = HTRule_translate(list, addr, NO); if (!physical) { HTRequest_addError(request, ERR_FATAL, NO, HTERR_FORBIDDEN, NULL, 0, "HTRuleFilter"); return HT_ERROR; } HTAnchor_setPhysical(anchor, physical); HT_FREE(physical); return HT_OK; }
PUBLIC BOOL HTextImp_delete (HTextImp * me) { if (me) { /* ** Note that we do not call the delete method on the app ** HText object as this normally stays around after the ** request has been deleted and certainly it should be ** deleted by the app and not libwww */ HT_FREE(me); return YES; } return NO; }
/* ** Use the set of bindings to find the combination of language, ** media type and encoding of a given object. This information can either be ** stored in the anchor obejct or in the response object depending on which ** function is called. ** ** We comprise here as bindings only can have one language and one encoding. ** If more than one suffix is found they are all searched. The last suffix ** has highest priority, the first one lowest. See also HTBind_getFormat() */ PUBLIC BOOL HTBind_getAnchorBindings (HTParentAnchor * anchor) { BOOL status = NO; double quality=1.0; /* @@@ Should we add this into the anchor? */ if (anchor) { char *addr = HTAnchor_address((HTAnchor *) anchor); char *path = HTParse(addr, "", PARSE_PATH+PARSE_PUNCTUATION); char *file; char *end; if ((end = strchr(path, ';')) || (end = strchr(path, '?')) || (end = strchr(path, '#'))) *end = '\0'; if ((file = strrchr(path, '/'))) { HTFormat format = NULL; HTEncoding encoding = NULL; HTEncoding transfer = NULL; HTLanguage language = NULL; HTTRACE(BIND_TRACE, "Anchor...... Get bindings for `%s\'\n" _ path); status = HTBind_getFormat(file, &format, &encoding, &transfer, &language, &quality); if (status) { HTAnchor_setFormat(anchor, format); HTAnchor_setContentTransferEncoding(anchor, transfer); HTAnchor_deleteEncodingAll(anchor); HTAnchor_addEncoding(anchor, encoding); HTAnchor_deleteLanguageAll(anchor); HTAnchor_addLanguage(anchor, language); } } HT_FREE(addr); HT_FREE(path); } return status; }
PRIVATE int CSParse_put_block (HTStream * me, const char * b, int l) { if (PICS_TRACE) { char * ptr; if ((ptr = (char *) HT_MALLOC(l+1)) == NULL) HT_OUTOFMEM("diagnostic buffer"); strncpy(ptr, b, l); ptr[l] = 0; HTTRACE(PICS_TRACE, "PICS: parser %p parsing block \"%s\"\n" _ me->pCSParse _ ptr); HT_FREE(ptr); } if (CSParse_parseChunk(me->pCSParse, b, l, 0) == CSDoMore_error) return HT_ERROR; return HT_OK; }
/* ** Find AA Element ** --------------- ** Seaches the set of authentication information bases for a match ** In order to find an anode we do the following: ** ** 1) Find the right auth base ** 2) See if there is a realm match ** 3) See if there is a template match for URL ** ** Return the node found else NULL which means that we don't have any ** authentication information to hook on to this request or response */ PRIVATE HTAAElement * HTAA_findElement (BOOL proxy_access, const char * realm, const char * url) { HTUTree * tree; if (!url) { HTTRACE(AUTH_TRACE, "Auth Engine. Bad argument\n"); return NULL; } HTTRACE(AUTH_TRACE, "Auth Engine. Looking up `%s'\n" _ url); /* Find an existing URL Tree for this URL (if any) */ { 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_find(proxy_access ? AA_PROXY_TREE : AA_TREE, host,port); HT_FREE(host); if (!tree) { HTTRACE(AUTH_TRACE, "Auth Engine. No information\n"); return NULL; } } /* Find a matching AA element (if any) */ { char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION); HTAAElement *element = (HTAAElement*)HTUTree_findNode(tree,realm,path); HT_FREE(path); return element; } return NULL; }
/* ** Creates a temporary anchor that doesn't exist */ PUBLIC HTParentAnchor * HTTmpAnchor (HTUserProfile * up) { static int offset = 0; /* Just keep counting... */ HTParentAnchor * htpa = NULL; time_t t = time(NULL); char * tmpfile = HTGetTmpFileName(HTUserProfile_tmp(up)); char * tmpurl = HTParse(tmpfile, "file:", PARSE_ALL); if (tmpfile && tmpurl && t >= 0) { char * result; if (!(result = (char *) HT_MALLOC(strlen(tmpurl)+20))) HT_OUTOFMEM("HTTmpAnchor"); #ifdef HAVE_LONG_TIME_T sprintf(result, "%s.%ld.%d", tmpurl, t, offset++); #else sprintf(result, "%s.%d.%d", tmpurl, t, offset++); #endif HTTRACE(APP_TRACE, "Tmp Anchor.. With location `%s\'\n" _ result); htpa = HTAnchor_parent(HTAnchor_findAddress(result)); HT_FREE(result); } HT_FREE(tmpfile); HT_FREE(tmpurl); return htpa; }
PRIVATE BOOL HTNewsCache_update (HTRequest * request, const char * url, HTArray * array) { HTUTree * tree = NULL; if (request && url) { char * newshost = NULL; if (!strncasecomp(url, "news:", 5)) { HTUserProfile * up = HTRequest_userProfile(request); StrAllocCopy(newshost, HTUserProfile_news(up)); } else if (!strncasecomp(url, "nntp:", 5)) { newshost = HTParse(url, "", PARSE_HOST); } /* ** If the news server was found then update the data entry. Otherwise ** create a new entry */ if (newshost) { char * colon = strchr(newshost, ':'); int port = NEWS_PORT; if (colon ) { *(colon++) = '\0'; /* Chop off port number */ port = atoi(colon); } tree = HTUTree_new(NEWS_TREE, newshost, port, HTNewsCache_delete); HT_FREE(newshost); if (!tree) { HTTRACE(PROT_TRACE, "News Cache.. Can't create tree\n"); return NO; } /* Add new cache information to the tree */ { HTNewsCache * element = NULL; BOOL status; if ((element=(HTNewsCache *) HTUTree_findNode(tree, "", "/"))){ element->cache = array; status = YES; } else { element = HTNewsCache_new(url, array); status = HTUTree_addNode(tree, "", "/", element); } return status; } } } return NO; }
/* ** Error and Information AFTER filter ** ---------------------------------- ** It checks the status code from a request and generates an ** error/information message if required. */ PUBLIC int HTInfoFilter (HTRequest * request, HTResponse * response, void * param, int status) { HTParentAnchor * anchor = HTRequest_anchor(request); char * uri = HTAnchor_address((HTAnchor*) anchor); switch (status) { case HT_RETRY: { HTAlertCallback *cbf = HTAlert_find(HT_A_MESSAGE); if (cbf) (*cbf)(request, HT_A_MESSAGE, HT_MSG_NULL, NULL, HTRequest_error(request), NULL); HTTRACE(PROT_TRACE, "Load End.... NOT AVAILABLE, RETRY AT %ld\n" _ HTResponse_retryTime(response)); } break; case HT_NO_DATA: { /* ** The document was empty */ HTAlertCallback *cbf = HTAlert_find(HT_A_MESSAGE); if (cbf) (*cbf)(request, HT_A_MESSAGE, HT_MSG_NULL, NULL, HTRequest_error(request), NULL); HTTRACE(PROT_TRACE, "Load End.... EMPTY: No content `%s\'\n" _ uri ? uri : "<UNKNOWN>"); break; } case HT_LOADED: HTTRACE(PROT_TRACE, "Load End.... OK: `%s\'\n" _ uri); break; default: { /* ** See if we have a function registered for outputting errors. ** If so then call it and present the message to the user */ HTAlertCallback *cbf = HTAlert_find(HT_A_MESSAGE); if (cbf) (*cbf)(request, HT_A_MESSAGE, HT_MSG_NULL, NULL, HTRequest_error(request), NULL); HTTRACE(PROT_TRACE, "Load End.... Request ended with code %d\n" _ status); break; } } HT_FREE(uri); return HT_OK; }
PUBLIC void * HTList_removeFirstObject (HTList * me) { if (me && me->next) { HTList * prevNode; void *firstObject; while (me->next) { prevNode = me; me = me->next; } firstObject = me->object; prevNode->next = NULL; HT_FREE(me); return firstObject; } else /* Empty list */ return NULL; }
PUBLIC BOOL HTList_removeObject (HTList * me, void * oldObject) { if (me) { HTList *previous; while (me->next) { previous = me; me = me->next; if (me->object == oldObject) { previous->next = me->next; HT_FREE(me); return YES; /* Success */ } } } return NO; /* object not found or NULL list */ }
PRIVATE BOOL HTCookieHolder_delete (HTCookieHolder * me) { if (me) { if (me->cookies) { HTList * cookies = me->cookies; HTCookie * cookie; while ((cookie = (HTCookie *) HTList_nextObject(cookies))) HTCookie_delete(cookie); HTList_delete(me->cookies); } HTList_removeObject(cookie_holder, me); HT_FREE(me); return YES; } return NO; }
/* Free a stream object ** -------------------- */ PRIVATE int HTMIME_free (HTStream * me) { int status = HT_OK; if (!me->transparent) if (_stream2dispatchParsers(me) == HT_OK) pumpData(me); if (me->target) { if ((status = (*me->target->isa->_free)(me->target))==HT_WOULD_BLOCK) return HT_WOULD_BLOCK; } HTTRACE(PROT_TRACE, "MIME........ FREEING....\n"); HTChunk_delete(me->token); HTChunk_delete(me->value); HT_FREE(me); return status; }
/* HTAlertCall_delete ** ------------------ ** Unregister a call back function from a list */ PUBLIC BOOL HTAlertCall_delete (HTList * list, HTAlertCallback *cbf) { HTTRACE(CORE_TRACE, "Alert Call.. Delete Alert Handler %p\n" _ (void *) cbf); if (list && cbf) { HTList *cur = list; HTAlert *pres; while ((pres = (HTAlert *) HTList_nextObject(cur))) { if (pres->cbf == cbf) { HTList_removeObject(list, (void *) pres); HT_FREE(pres); return YES; } } } return NO; }
PUBLIC BOOL UserProgress (HTRequest * request, HTAlertOpcode op, int msgnum, const char * dfault, void * input, HTAlertPar * reply) { char * msg = HTDialog_progressMessage(request, op, msgnum, dfault, input); CRequest * req = (CRequest *) HTRequest_context(request); ASSERT(request != NULL); ASSERT(req != NULL); CProgressCtrl * progress = req->GetProgressBar(); switch (op) { case HT_PROG_READ: { long cl = HTAnchor_length(HTRequest_anchor(request)); if (cl > 0) { long b_read = HTRequest_bodyRead(request); double pro = (double) b_read/cl*100; progress->SetPos((int) pro); } } break; case HT_PROG_WRITE: { long cl = HTAnchor_length(HTRequest_entityAnchor(request)); if (cl > 0) { long b_written = HTRequest_bodyWritten(request); double pro = (double) b_written/cl*100; progress->SetPos((int) pro); } } break; } // Update pane 0 of the status bar if (msg) { CWinComDoc * doc = req->m_pDoc; if (doc) { POSITION pos = doc->GetFirstViewPosition(); CView * view = doc->GetNextView( pos ); CMainFrame * mainframe = (CMainFrame *) view->GetParentFrame(); mainframe->m_wndStatusBar.SetPaneText(ID_SEPARATOR, msg); } HT_FREE(msg); } return YES; }
/* HTDNS_deleteAll ** --------------- ** Destroys the cache completely */ PUBLIC BOOL HTDNS_deleteAll (void) { int cnt; HTList *cur; if (!CacheTable) return NO; for (cnt=0; cnt<HT_M_HASH_SIZE; cnt++) { if ((cur = CacheTable[cnt])) { HTdns *pres; while ((pres = (HTdns *) HTList_nextObject(cur)) != NULL) free_object(pres); } HTList_delete(CacheTable[cnt]); CacheTable[cnt] = NULL; } HT_FREE(CacheTable); return YES; }
PUBLIC BOOL HTMuxChannel_deleteAll (void) { if (muxchs) { HTList * cur; int cnt; for (cnt=0; cnt<HOST_HASH_SIZE; cnt++) { if ((cur = muxchs[cnt])) { HTMuxChannel * pres; while ((pres = (HTMuxChannel *) HTList_nextObject(cur))) channel_delete(pres); } HTList_delete(muxchs[cnt]); } HT_FREE(muxchs); } return YES; }
PRIVATE void foundLink (HText * text, int element_number, int attribute_number, HTChildAnchor * anchor, const BOOL * present, const char ** value) { if (anchor) { /* ** Find out which link we got. The anchor we are passed is ** a child anchor of the anchor we are current parsing. We ** have to go from this child anchor to the actual destination. */ HTAnchor * dest = HTAnchor_followMainLink((HTAnchor *) anchor); char * address = HTAnchor_address(dest); HTPrint("Found link `%s\'\n", address); HT_FREE(address); } }
/* ** Retry through Proxy AFTER Filter ** -------------------------------- ** This filter handles a 305 Use Proxy response and retries the request ** through the proxy */ PUBLIC int HTUseProxyFilter (HTRequest * request, HTResponse * response, void * param, int status) { HTAlertCallback * cbf = HTAlert_find(HT_A_CONFIRM); HTAnchor * proxy_anchor = HTResponse_redirection(response); if (!proxy_anchor) { HTTRACE(PROT_TRACE, "Use Proxy... No proxy location\n"); return HT_OK; } /* ** Add the proxy to the list. Assume HTTP access method only! ** Because evil servers may rediret the client to an untrusted ** proxy, we can only accept redirects for this particular ** server. Also, we do not know whether this is for HTTP or all ** other requests as well */ if ((cbf && (*cbf)(request, HT_A_CONFIRM, HT_MSG_PROXY, NULL,NULL,NULL))) { char * addr = HTAnchor_address(proxy_anchor); HTProxy_add("http", addr); HT_FREE(addr); /* ** Start new request through the proxy if we haven't reached the max ** number of redirections for this request */ if (HTRequest_doRetry(request)) { HTLoadAnchor(proxy_anchor, request); } else { HTRequest_addError(request, ERR_FATAL, NO, HTERR_MAX_REDIRECT, NULL, 0, "HTRedirectFilter"); } /* ** By returning HT_ERROR we make sure that this is the last handler to be ** called. We do this as we don't want any other filter to delete the ** request object now when we have just started a new one ourselves */ return HT_ERROR; } else { HTRequest_addError(request, ERR_FATAL, NO, HTERR_NO_AUTO_PROXY, NULL, 0, "HTUseProxyFilter"); return HT_OK; } }
/* HTChannel_deleteAll ** ------------------- ** Destroys all channels. This is called by HTLibTerminate(0 */ PUBLIC BOOL HTChannel_deleteAll (void) { if (channels) { HTList * cur; int cnt; for (cnt=0; cnt<HT_M_HASH_SIZE; cnt++) { if ((cur = channels[cnt])) { HTChannel * pres; while ((pres = (HTChannel *) HTList_nextObject(cur)) != NULL) free_channel(pres); } HTList_delete(channels[cnt]); } HT_FREE(channels); } return YES; }
/* HTAlertCall_deleteOpcode ** ------------------------ ** Unregister all handlers registered for a given opcode. */ PUBLIC BOOL HTAlertCall_deleteOpcode (HTList * list, HTAlertOpcode opcode) { HTTRACE(CORE_TRACE, "Alert Call.. Delete all handlers with opcode %d\n" _ opcode); if (list) { HTList * cur = list; HTAlert * pres; while ((pres = (HTAlert *) HTList_nextObject(cur))) { if (pres->opcode == opcode) { HTList_removeObject(list, (void *) pres); HT_FREE(pres); cur = list; } } return YES; } return NO; }
/* HTAA_beforeFilter ** ------------------ ** Make a lookup in the URL tree to find any context for this node, ** If no context is found then we assume that we don't know anything about ** this URL and hence we don't call any BEFORE filters at all. ** Return HT_OK or whatever callback returns */ PUBLIC int HTAA_beforeFilter (HTRequest * request, void * param, int mode) { char * url = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); const char * realm = HTRequest_realm(request); HTAAElement * element = HTAA_findElement(NO, realm, url); HT_FREE(url); /* If we have an element then call the before filter with this scheme */ if (element) { HTAAModule * module = HTAA_findModule(element->scheme); if (module) { HTTRACE(AUTH_TRACE, "Auth Engine. Found BEFORE filter %p\n" _ module->before); return (*module->before)(request, element->context, mode); } } return HT_OK; }
/* ** A small BEFORE filter that just finds a cache entry unconditionally ** and loads the entry. All freshness and any other constraints are ** ignored. */ PRIVATE int HTCacheLoadFilter (HTRequest * request, void * param, int mode) { HTParentAnchor * anchor = HTRequest_anchor(request); char * default_name; HTCache * cache; default_name = HTRequest_defaultPutName (request); cache = HTCache_find(anchor, default_name); HTTRACE(STREAM_TRACE, "Cache Load.. loading partial cache entry\n"); if (cache) { char * name = HTCache_name(cache); HTAnchor_setPhysical(anchor, name); HTCache_addHit(cache); HT_FREE(name); } return HT_OK; }
/* ** Searches the whole list and removes all elements with this name */ PUBLIC BOOL HTAssocList_removeObject (HTAssocList * list, const char * name) { BOOL found = NO; if (list && name) { HTAssocList * cur = list; HTAssoc * assoc; int len = strlen(name); while ((assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strncasecomp(assoc->name, name, len)) { HTList_removeObject(list, assoc); HT_FREE(assoc); found = YES; cur = list; } } } return found; }
/* ** Delete a user profile */ PUBLIC BOOL HTUserProfile_delete (HTUserProfile * up) { if (up) { HT_FREE(up->user); HT_FREE(up->fqdn); HT_FREE(up->email); HT_FREE(up->news); HT_FREE(up->tmp); HT_FREE(up); return YES; } return NO; }
/* HTDir_headLine ** -------------- ** Puts out the header line of the list itself ** Returns YES if OK, else NO */ PRIVATE BOOL HTDir_headLine (HTDir *dir) { if (dir) { char *tp; HTStructured *target = dir->target; START(HTML_PRE); if (dir->show & HT_DS_ICON) { HTIconNode * icon = HTIcon_find(HT_IS_BLANK, NULL, NULL); if (icon) { char * alt = HTIcon_alternative(icon, NO); HTMLPutImg(target, HTIcon_url(icon), alt, NULL); HT_FREE(alt); PUTC(' '); } } tp = dir->fnbuf; LeftStr(&tp, "Name", dir->curfw); LeftStr(&tp, " ", HT_DLEN_SPACE); *tp = '\0'; PUTS(dir->fnbuf); tp = dir->lnbuf; if (dir->show & HT_DS_DATE) { LeftStr(&tp, "Last Modified", HT_DLEN_DATE); LeftStr(&tp, " ", HT_DLEN_SPACE); } if (dir->show & HT_DS_SIZE) { RightStr(&tp, "Size", HT_DLEN_SIZE); LeftStr(&tp, " ", HT_DLEN_SPACE); } if (dir->show & HT_DS_DES) { LeftStr(&tp, "Description", HT_DLEN_DATE); LeftStr(&tp, " ", HT_DLEN_SPACE); } *tp = '\0'; PUTS(dir->lnbuf); END(HTML_PRE); START(HTML_HR); START(HTML_PRE); return YES; } return NO; }
PUBLIC BOOL HTTimer_deleteAll (void) { HTList * cur = Timers; HTTimer * pres; if (Timers) { while ((pres = (HTTimer *) HTList_nextObject(cur))) { /* ** Call any platform specific timer handler */ if (DeletePlatformTimer) DeletePlatformTimer(pres); HT_FREE(pres); } HTList_delete(Timers); Timers = NULL; return YES; } return NO; }
/* DELETE ALL ANCHORS ** ------------------ ** Deletes all anchors and return a list of all the HyperDocs found. ** It is for the application to delete any HyperDocs. ** If NULL then no hyperdocs are returned ** Return YES if OK, else NO */ PUBLIC BOOL HTAnchor_deleteAll (HTList * documents) { int cnt; HTList *cur; if (!adult_table) return NO; for (cnt=0; cnt<PARENT_HASH_SIZE; cnt++) { if ((cur = adult_table[cnt])) { HTParentAnchor *pres; while ((pres = (HTParentAnchor *) HTList_nextObject(cur)) != NULL){ void * doc = delete_family((HTAnchor *) pres); if (doc && documents) HTList_addObject(documents, doc); } } HTList_delete(adult_table[cnt]); } HT_FREE(adult_table); return YES; }
/* Add entry to the log file ** ------------------------- ** Format: <HOST> - - <DATE> <METHOD> <URI> <RESULT> <CONTENT_LENTGH> ** which is almost equivalent to Common Logformat. Permissions on UNIX ** are modified by umask. ** ** Returns YES if OK, NO on error ** ** BUG: No result code is produced :-( Should be taken from HTError.c */ PUBLIC BOOL HTLog_addCLF (HTLog * log, HTRequest * request, int status) { if (log && log->fp) { time_t now = time(NULL); HTParentAnchor * anchor = HTRequest_anchor(request); char * uri = HTAnchor_address((HTAnchor *) anchor); HTTRACE(APP_TRACE, "Log......... Writing CLF log\n"); fprintf(log->fp, "localhost - - [%s] %s %s %d %ld\n", HTDateTimeStr(&now, log->localtime), HTMethod_name(HTRequest_method(request)), uri ? uri : "<null>", /* Bill Rizzi */ abs(status), HTAnchor_length(anchor)); HT_FREE(uri); log->accesses++; return (fflush(log->fp) != EOF); /* Actually update it on disk */ } return NO; }
/* ** 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); } }