/* N O T E S - to be removed before release executable l:\projects\libwww\www\linemode\pics\windows\windebug\wwwpics.exe working dir l:\projects\libwww\www\library\implementation\windows\windebug args dlls l:\projects\libwww\www\pics\implementation\windows\windebug\wwwpics.dll switch to HTStrMatch */ #include #include #include "WWWLib.h" #include "WWWApp.h" #include "WWWFile.h" #include "HTHeader.h" #include "CSLApp.h" #include "CSParse.h" #include "CSLUtils.h" #include "CSLL.h" #include "CSUser.h" #include "CSUserSt.h" #include "CSUsrLst.h" /* ReqParms - list of pending HTRequests and their callbacks an' stuff */ typedef struct { HTRequest * pReq; enum {reqState_NEW, reqState_PROT_REQ, reqState_BUREAU_START, reqState_BUREAU_MIDDLE, reqState_BUREAU_DONE, reqState_BUREAU_ERR} reqState; CSDisposition_criteria criteria;/* if the criteria are met */ CSDisposition_callback * pCallback; /* call pCallback */ CSError_t disposition; /* with */ CSLabel_t * pCSLabel; /* all */ CSUser_t * pCSUser; /* these */ void * pVoid; /* parameters */ HTParentAnchor * anchor; HTFormat outputFormat; HTStream * outputStream; HTMethod method; } ReqParms_t; ReqParms_t DefaultReqParms = {0, reqState_NEW, CSApp_neverCall, 0, CSError_APP, 0, 0, 0}; /* handy strings */ PRIVATE char * S_mimeLabel = "PICS-Label"; PRIVATE char * S_machRead = "application/x-pics-machine-readable"; PRIVATE char * S_label = "application/pics-label"; PRIVATE char * S_user = "application/x-pics-user"; PRIVATE char * S_URLList = "application/x-url-list"; PRIVATE HTList * ListWithHeaderGenerator = NULL; /* LoadURLToConverter - load a URL and set the output to go to converter. Useful for loading user list and profiles. */ PRIVATE BOOL LoadURLToConverter(const char * url, const char * relatedName, const char * type, HTConverter * converter, const char * errMessage) { BOOL ret; char * fullURL; HTRequest * pRequest; HTParentAnchor * pParentAnchor; HTList * conversions = HTList_new(); pRequest = HTRequest_new(); fullURL = HTParse(url, relatedName, PARSE_ALL); pParentAnchor = (HTParentAnchor *) HTAnchor_findAddress(fullURL); HTRequest_setPreemptive(pRequest, YES); if (converter) { HTConversion_add(conversions, type, "*/*", converter, 1.0, 0.0, 0.0); HTRequest_setConversion(pRequest, conversions, YES); } if ((ret = HTLoadAnchor((HTAnchor *) pParentAnchor, pRequest)) != YES) HTPrint("PICS: Can't access %s.\n", errMessage); if (converter) HTConversion_deleteAll(conversions); else HTList_delete(conversions); HTRequest_delete(pRequest); HT_FREE(fullURL); return ret; } /* This should be in CSUserList, but that would require that LoadURLToConverter and S_URLList be PUBLIC and added to some header, which one? */ PUBLIC BOOL CSUserList_load(char * url, char * relatedName) { return LoadURLToConverter(url, relatedName, S_URLList, CSUserLists, "PICS user list"); } /* L O A D E D U S E R */ /* LoadedUsers is a list of all the users who have had their descritpion files loaded */ typedef struct { CSUser_t * pCSUser; char * url; } CSLoadedUser_t; PRIVATE HTList * LoadedUsers = 0; PRIVATE CSLoadedUser_t * CSLoadedUser_new(CSUser_t * pCSUser, char * url) { CSLoadedUser_t * pCSLoadedUser; if ((pCSLoadedUser = (CSLoadedUser_t *)HT_MALLOC(sizeof(CSLoadedUser_t))) == NULL) HT_OUTOFMEM("CSLoadedUser_t"); pCSLoadedUser->pCSUser = pCSUser; pCSLoadedUser->url = 0; StrAllocCopy(pCSLoadedUser->url, url); return pCSLoadedUser; } PRIVATE void CSLoadedUser_delete(CSLoadedUser_t * pCSLoadedUser) { CSUser_free(pCSLoadedUser->pCSUser); HT_FREE(pCSLoadedUser->url); HT_FREE(pCSLoadedUser); } PRIVATE CSLoadedUser_t * CSLoadedUser_findUser(CSUser_t * pCSUser) { HTList * cur = LoadedUsers; CSLoadedUser_t * pCSLoadedUser; while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_nextObject(cur))) { if (pCSLoadedUser->pCSUser == pCSUser) return pCSLoadedUser; } return 0; } PRIVATE CSLoadedUser_t * CSLoadedUser_findName(char * name) { HTList * cur = LoadedUsers; CSLoadedUser_t * pCSLoadedUser; while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_nextObject(cur))) { if (!strcasecomp(CSUser_name(pCSLoadedUser->pCSUser), name)) return pCSLoadedUser; } return 0; } PUBLIC BOOL CSLoadedUser_remove(CSUser_t * pCSUser) { CSLoadedUser_t * pCSLoadedUser; if (!(pCSLoadedUser = CSLoadedUser_findUser(pCSUser))) return NO; HTList_removeObject(LoadedUsers, (void *)pCSLoadedUser); CSLoadedUser_delete(pCSLoadedUser); return YES; } /* PUBLIC version of findName */ PUBLIC BOOL CSLoadedUser_find(char * name) { return (CSLoadedUser_findName(name) != 0); } PRIVATE CSLoadedUser_t * CSLoadedUser_findUrl(char * url) { HTList * cur = LoadedUsers; CSLoadedUser_t * pCSLoadedUser; while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_nextObject(cur))) { if (!strcasecomp(pCSLoadedUser->url, url)) return pCSLoadedUser; } return 0; } CSApp_userCallback * PUserCallback = 0; PUBLIC BOOL CSLoadedUser_add(CSUser_t * pCSUser, char * url) { int callBackRet; CSLoadedUser_t * pCSLoadedUser; callBackRet = (*PUserCallback)(pCSUser, DefaultReqParms.pVoid); switch (callBackRet) { case 1: DefaultReqParms.pCSUser = pCSUser; HTTRACE(PICS_TRACE, "PICS: Setting default user to \"%s\".\n" _ CSUser_name(pCSUser)); break; case 0: HTTRACE(PICS_TRACE, "PICS: Loaded user \"%s\".\n" _ CSUser_name(pCSUser)); break; case -1: HTTRACE(PICS_TRACE, "PICS: User \"%s\" not loaded.\n" _ CSUser_name(pCSUser)); return YES; default: HTTRACE(PICS_TRACE, "PICS: Aborting load user \"%s\".\n" _ CSUser_name(pCSUser)); return NO; } if ((pCSLoadedUser = CSLoadedUser_findName(CSUser_name(pCSUser)))) { HTPrint("PICS: Replacing previous user \"%s\".\n", CSUser_name(pCSUser)); HTList_removeObject(LoadedUsers, (void *)pCSLoadedUser); } pCSLoadedUser = CSLoadedUser_new(pCSUser, url); return (HTList_addObject(LoadedUsers, (void *)pCSLoadedUser)); } PUBLIC BOOL CSLoadedUser_deleteAll (void) { CSLoadedUser_t * pCSLoadedUser; while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_removeLastObject(LoadedUsers))) { CSLoadedUser_delete(pCSLoadedUser); } HTList_delete(LoadedUsers); LoadedUsers = NULL; return YES; } PUBLIC int CSLoadedUser_enum(CSLoadedUserCallback * pCallback, void * pVoid) { HTList * cur = LoadedUsers; CSLoadedUser_t * pCSLoadedUser; int retVal, i = 0; while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_nextObject(cur))) { if ((retVal = (*pCallback)(pCSLoadedUser->pCSUser, i, pVoid)) != CSError_OK) return (retVal); i++; } return 0; } PUBLIC CSUser_t * CSLoadedUser_load(char * url, char * relatedName) { BOOL err = 0; char * fullURL = HTParse(url, relatedName, PARSE_ALL); CSLoadedUser_t * pCSLoadedUser; if (!LoadURLToConverter(fullURL, 0, 0, 0, "PICS user file")) /* if (!LoadURLToConverter(fullURL, 0, S_user, CSParseUser, "PICS user file", 0, 0, 0)) */ err = 1; else if ((pCSLoadedUser = CSLoadedUser_findUrl(fullURL)) == NULL) err = 1; HT_FREE(fullURL); return err ? 0 : pCSLoadedUser->pCSUser; } /* R E Q P A R M S */ HTList * ReqParms = 0; PRIVATE ReqParms_t * ReqParms_new(HTRequest * pReq, CSUser_t * pCSUser, CSDisposition_callback * pCallback, CSDisposition_criteria criteria, void * pVoid) { ReqParms_t * me; if ((me = (ReqParms_t *) HT_CALLOC(1, sizeof(ReqParms_t))) == NULL) HT_OUTOFMEM("ReqParms_t"); me->pReq = pReq; me->disposition = CSError_APP; me->reqState = reqState_NEW; me->pCSUser = pCSUser; me->pCallback = pCallback; me->criteria = criteria; me->pVoid = pVoid; return me; } PRIVATE void ReqParms_free(ReqParms_t * pReqParms) { HT_FREE(pReqParms); } PRIVATE ReqParms_t * ReqParms_copy(ReqParms_t * old) { ReqParms_t * me; if ((me = (ReqParms_t *) HT_CALLOC(1, sizeof(ReqParms_t))) == NULL) HT_OUTOFMEM("ReqParms_t"); me->pReq = old->pReq; me->disposition = old->disposition; me->reqState = old->reqState; me->pCSUser = old->pCSUser; me->pCallback = old->pCallback; me->criteria = old->criteria; me->pVoid = old->pVoid; return me; } PRIVATE ReqParms_t * ReqParms_getReq(HTRequest * pReq) { HTList * cur = ReqParms; ReqParms_t * pReqParms; while ((pReqParms = (ReqParms_t *) HTList_nextObject(cur))) if (pReqParms->pReq == pReq) return pReqParms; return 0; } /* PRIVATE ReqParms_t * ReqParms_getBureauReq(HTRequest * pBureauReq) { HTList * cur = ReqParms; ReqParms_t * pReqParms; while ((pReqParms = (ReqParms_t *) HTList_nextObject(cur))) if (pReqParms->pBureauReq == pBureauReq) return pReqParms; return 0; } */ PRIVATE BOOL ReqParms_cache(ReqParms_t * pReqParms, CSLabel_t * pCSLabel) { return NO; } PRIVATE BOOL ReqParms_checkCache(ReqParms_t * pReqParms, int * pRet) { return NO; } PUBLIC BOOL CSApp_label(HTRequest * pReq, CSLabel_t * pCSLabel) { ReqParms_t * pReqParms; if (!(pReqParms = ReqParms_getReq(pReq))) pReqParms = &DefaultReqParms; /* if (!(pReqParms = ReqParms_getBureauReq(pReq))) pReqParms = &DefaultReqParms; if (pReqParms->pBureauReq != pReq) { HTPrint("PICS: Could not find original request\n"); return NO; } */ pReqParms->pCSLabel = pCSLabel; pReqParms->disposition = CSCheckLabel_checkLabelAndUser(pCSLabel, pReqParms->pCSUser); ReqParms_cache(pReqParms, pCSLabel); return YES; } PRIVATE int ReqParms_checkDisposition(ReqParms_t * pReqParms) { int kill; kill = pReqParms->disposition != CSError_OK; if ((kill && pReqParms->criteria & CSApp_callOnBad) || (!kill && pReqParms->criteria & CSApp_callOnGood)) pReqParms->disposition = (*pReqParms->pCallback)(pReqParms->pReq, pReqParms->pCSLabel, pReqParms->pCSUser, pReqParms->disposition, pReqParms->pVoid); return (pReqParms->disposition == CSError_OK ? HT_OK : HT_INTERRUPTED); CSLabel_free(pReqParms->pCSLabel); if (pReqParms->disposition == CSError_OK) return HT_OK; return HT_OK; } PRIVATE BOOL ReqParms_removeRequest(ReqParms_t * pReqParms) { HTList_removeObject(ReqParms, (void *)pReqParms); ReqParms_free(pReqParms); return YES; } /* PRIVATE BOOL ReqParms_removeRequest(HTRequest * pReq) { ReqParms_t * pReqParms; if ((pReqParms = ReqParms_getReq(pReq))) return HTList_removeObject(ReqParms, (void *)pReqParms); return NO; } PRIVATE CSUser_t * ReqParms_getUser(HTRequest * pReq) { ReqParms_t * pReqParms; if ((pReqParms = ReqParms_getReq(pReq))) return pReqParms->pCSUser; return 0; } */ /* U S E R */ PUBLIC BOOL CSApp_registerDefaultUserByName(char * user, char * password) { CSUser_t * pCSUser; CSLoadedUser_t * pCSLoadedUser; if (!(pCSLoadedUser = CSLoadedUser_findName(user))) { HTTRACE(PICS_TRACE, "PICS: User \"%s\" not found.\n" _ CSUser_name(pCSUser)); return NO; } pCSUser = pCSLoadedUser->pCSUser; if (CSUser_checkPassword(pCSUser, password) == NO) { HTPrint("PICS: Bad password for user \"%s\".\n", CSUser_name(pCSUser)); return NO; } DefaultReqParms.pCSUser = pCSUser; return YES; } PUBLIC CSUser_t * CSApp_registerUserByName(char* user, char* password) { CSLoadedUser_t * pCSLoadedUser; if (!(pCSLoadedUser = CSLoadedUser_findName(user))) return 0; if (CSUser_checkPassword(pCSLoadedUser->pCSUser, password) == NO) { HTPrint("PICS: Bad password for user \"%s\"\n", CSUser_name(pCSLoadedUser->pCSUser)); return 0; } return pCSLoadedUser->pCSUser; } PUBLIC BOOL CSApp_setDefaultUser(CSUser_t * pCSUser) { if (!pCSUser) return NO; DefaultReqParms.pCSUser = pCSUser; return YES; } PUBLIC BOOL CSApp_checkHUser(CSUser_t * pCSUser) { return YES; } PUBLIC BOOL CSApp_unregisterDefaultUser(void) { DefaultReqParms.pCSUser = 0; return YES; } PUBLIC BOOL CSApp_unregisterUser(CSUser_t * pCSUser) { if (DefaultReqParms.pCSUser == pCSUser) DefaultReqParms.pCSUser = 0; return CSLoadedUser_remove(pCSUser); } /* base of all streams */ #define PUTBLOCK(b, l) (*target->isa->put_block)(target, b, l) struct _HTStream { const HTStreamClass * isa; /* ... */ }; /* HTNet Filters */ PRIVATE HTNetAfter CSApp_bureauError; PRIVATE int CSApp_bureauAfter (HTRequest * pReq, HTResponse * response, void * context, int status) { ReqParms_t * pReqParms = (ReqParms_t *)context; /* if (!pReqParms || (pReq != pReqParms->pBureauReq)) return HT_ERROR; */ pReqParms->reqState = reqState_BUREAU_DONE; HTRequest_deleteAfter(pReq, CSApp_bureauAfter); HTRequest_deleteAfter(pReq, CSApp_bureauError); HTTRACE(PICS_TRACE, "PICS: Load was %sOK\n" _ pReqParms->disposition == CSError_OK ? "" : "!"); ReqParms_removeRequest(pReqParms); if (pReqParms->disposition != CSError_OK) return HT_OK; /* HTRequest_setAnchor(pReq, pReqParms->anchor); */ HTRequest_setOutputFormat(pReq, pReqParms->outputFormat); HTRequest_setOutputStream(pReq, pReqParms->outputStream); HTRequest_setMethod(pReq, pReqParms->method); return HTLoadAnchor((HTAnchor *)pReqParms->anchor, pReq); } PRIVATE int CSApp_bureauError (HTRequest * pReq, HTResponse * response, void * context, int status) { ReqParms_t * pReqParms = (ReqParms_t *)context; /* if (!pReqParms || (pReq != pReqParms->pBureauReq)) return HT_ERROR; */ pReqParms->reqState = reqState_BUREAU_ERR; HTPrint("PICS: couldn't find label service.\n"); return HT_OK; } PRIVATE int CSApp_netBefore (HTRequest * pReq, void * param, int mode) { HTParentAnchor * pParentAnchor; ReqParms_t * pReqParms; char * bureau; char * url; char * ptr; int ret; /* if (ReqParms_getBureauReq(pReq) || pReq == DefaultReqParms.pBureauReq) return HT_OK; if (!(pReqParms = ReqParms_getReq(pReq))) { pReqParms = &DefaultReqParms; DefaultReqParms.pReq = pReq; } */ if ((pReqParms = ReqParms_getReq(pReq))) { if (pReqParms->reqState == reqState_BUREAU_START) /* bureau req */ return HT_OK; /* so ignore */ } else { if (!DefaultReqParms.pCSUser) return HT_OK; /* no PICS user so no PICS */ pReqParms = ReqParms_copy(&DefaultReqParms); pReqParms->pReq = pReq; } if (!(bureau = CSUser_bureau(pReqParms->pCSUser))) { HTRequest_setGenerator(pReq, ListWithHeaderGenerator, NO); return HT_OK; /* Header will handle it */ } if (ReqParms_checkCache(pReqParms, &ret)) return ret; url = HTAnchor_address((HTAnchor*)HTRequest_anchor(pReq)); ptr = CSUser_getLabels(pReqParms->pCSUser, url, CSOption_normal, CSCompleteness_full); pReqParms->anchor = HTRequest_anchor(pReq); pReqParms->outputFormat = HTRequest_outputFormat(pReq); HTRequest_setOutputFormat(pReq, WWW_SOURCE); pReqParms->outputStream = HTRequest_outputStream(pReq); HTRequest_setOutputStream(pReq, CSParseLabel(pReq, 0, 0, 0, 0)); /* pReqParms->pBureauReq = pReq; */ pReqParms->reqState = reqState_BUREAU_START; /* mark as a BUREAU req */ HTRequest_setPreemptive(pReq, YES); HTTRACE(PICS_TRACE, "PICS: label request:\n%s\n" _ ptr); /* get label and set disposition */ HTRequest_addAfter(pReq, CSApp_bureauAfter, NULL, (void *) pReqParms, HT_LOADED, HT_FILTER_MIDDLE, YES); HTRequest_addAfter(pReq, CSApp_bureauError, NULL, (void *) pReqParms, HT_ERROR, HT_FILTER_MIDDLE, YES); pParentAnchor = (HTParentAnchor *) HTAnchor_findAddress(ptr); if ((ret = HTLoadAnchor((HTAnchor *) pParentAnchor, pReq)) != YES) HTPrint("PICS: Can't access label bureau at %s.\n", ptr); return HT_OK; } /*HTPostCallback CSApp_headerGenerator;*/ PRIVATE int CSApp_headerGenerator (HTRequest * pReq, HTStream * target) { char * translated; HTParentAnchor *anchor = HTRequest_anchor(pReq); char * url; ReqParms_t * pReqParms = ReqParms_getReq(pReq); /* if (!pReqParms) { if ((pReqParms = ReqParms_getBureauReq(pReq))) return HT_OK; pReqParms = &DefaultReqParms; } */ if (!pReqParms || pReqParms->reqState != reqState_NEW || !pReqParms->pCSUser) HTPrint("PICS: CSApp_headerGenerator prob\n"); #if 0 if (!pReqParms->pCSUser) { HTTRACE(PICS_TRACE, "PICS: No user selected\n"); return HT_OK; } if (CSUser_bureau(pReqParms->pCSUser)) /* handled by CSApp_netBefore */ return HT_OK; #endif url = HTAnchor_address((HTAnchor *) anchor); if ((translated = CSUser_acceptLabels(pReqParms->pCSUser, CSCompleteness_full))) { HTTRACE(PICS_TRACE, "PICS: Accept \"%s\".\n" _ translated); PUTBLOCK(translated, strlen(translated)); HT_FREE(translated); } HT_FREE(url); return HT_OK; } /*HTParserCallback CSApp_headerParser;*/ PRIVATE int CSApp_headerParser (HTRequest * pReq, HTResponse * response, char * token, char * value) { CSParse_t * pCSParse; ReqParms_t * pReqParms = ReqParms_getReq(pReq); if (!pReqParms) { pReqParms = &DefaultReqParms; DefaultReqParms.pReq = pReq; } if (!pReqParms->pCSUser) /* if there is no user */ return HT_OK; /* send the document on its way */ /* pReqParms->disposition = CSCheckLabel_parseAndValidateLabelStr(value, pReqParms->pCSUser); */ pCSParse = CSParse_newLabel(0, 0); CSParse_parseChunk(pCSParse, value, (int) strlen(value), 0); pReqParms->disposition = CSCheckLabel_checkLabelAndUser(CSParse_getLabel(pCSParse), pReqParms->pCSUser); pReqParms->pCSLabel = CSParse_getLabel(pCSParse); CSParse_delete(pCSParse); HTTRACE(PICS_TRACE, "PICS: PICS mime header \"%s\" got %d.\n" _ value _ pReqParms->disposition); return ReqParms_checkDisposition(pReqParms); } /* application functions */ PUBLIC BOOL CSApp_registerApp(CSDisposition_callback * pCallback, CSDisposition_criteria criteria, CSApp_userCallback * pUserCallback, void * pVoid) { HTList* conversions; PUserCallback = pUserCallback; /* set up DefaultReqParms */ DefaultReqParms.pCallback = pCallback; DefaultReqParms.criteria = criteria; DefaultReqParms.pVoid = pVoid; /* Tell HTMIME which headers we will deal with */ if (!ListWithHeaderGenerator) ListWithHeaderGenerator = HTList_new(); HTList_addObject(ListWithHeaderGenerator, (void *)CSApp_headerGenerator); /* HTHeader_addGenerator(CSApp_headerGenerator); */ HTNet_addBefore(CSApp_netBefore, NULL, NULL, 5); HTHeader_addParser(S_mimeLabel, FALSE, CSApp_headerParser); /* set converters so pics profiles may be read */ conversions = HTFormat_conversion(); #if 0 HTConversion_add(conversions, S_machRead, "*/*", CSParseMachRead, 1.0, 0.0, 0.0); HTConversion_add(conversions, S_label, "*/*", CSParseLabel, 1.0, 0.0, 0.0); #endif HTConversion_add(conversions, S_user, "*/*", CSParseUser, 1.0, 0.0, 0.0); HTBind_add("rat", S_machRead, "7bit", NULL, NULL, 1.0); HTBind_add("pcu", S_user, "7bit", NULL, NULL, 1.0); HTBind_add("lab", S_label, "7bit", NULL, NULL, 1.0); HTBind_add("url", S_URLList, "7bit", NULL, NULL, 1.0); if (!LoadedUsers) LoadedUsers = HTList_new(); return YES; } /* while ((pCSLoadedUser = (CSLoadedUser_t *) HTList_removeLastObject(LoadedUsers))) HTList_removeObject(pCSLoadedUser); return YES; */ PUBLIC BOOL CSApp_unregisterApp() { HTHeader_deleteGenerator(CSApp_headerGenerator); HTHeader_deleteParser(S_mimeLabel); return YES; } PUBLIC BOOL CSApp_registerReq(HTRequest* pReq, CSUser_t * pCSUser, CSDisposition_callback pCallback, CSDisposition_criteria criteria, void * pVoid) { ReqParms_t * pReqParms; if ((pReqParms = ReqParms_getReq(pReq))) { return NO; } if (!pReq || !pCSUser) return NO; pReqParms = ReqParms_new(pReq, pCSUser, pCallback, criteria, pVoid); if (!ReqParms) ReqParms = HTList_new(); HTList_addObject(ReqParms, (void *)pReqParms); return YES; } PUBLIC BOOL CSApp_unregisterReq(HTRequest* pReq) { ReqParms_t * pReqParms; if ((pReqParms = ReqParms_getReq(pReq)) == NULL) { return NO; } HTList_removeObject(ReqParms, (void *)pReqParms); ReqParms_free(pReqParms); return YES; } PUBLIC HTRequest * CSApp_originalRequest(HTRequest* pReq) { /* ReqParms_t * pReqParms; if ((pReqParms = ReqParms_getBureauReq(pReq)) == NULL) { return NULL; } return pReqParms->pReq; */ return pReq; } /* M I S C */ PUBLIC char * CSApp_libraryVersion(void) { return "1.1"; }