/* W3 Copyright statement Copyright 1995 by: Massachusetts Institute of Technology (MIT), INRIA This W3C software is being provided by the copyright holders under the following license. By obtaining, using and/or copying this software, you agree that you have read, understood, and will comply with the following terms and conditions: Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee or royalty is hereby granted, provided that the full text of this NOTICE appears on ALL copies of the software and documentation or portions thereof, including modifications, that you make. THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR DOCUMENTATION. The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders. */ /* --- BEGIN added by mharmsen@netscape.com on 7/9/97 --- */ #include "xp.h" /* --- END added by mharmsen@netscape.com on 7/9/97 --- */ /* #include "sysdep.h" jhines--7/9/97 */ /*#include "HTUtils.h" */ #include "htlist.h" #include "htstring.h" #include "csparse.h" #include "csll.h" #include "csllst.h" #define GetCSLabel(A) ((A)->target.pCSLabel) #define SETNEXTSTATE(target, subState) \ pCSParse->pTargetObject = target; \ pCSParse->currentSubState = subState; /* C H A R A C T E R S E T V A L I D A T I O N */ /* The BNF for PICS labels describes the valid character ranges for each of * the label fields. Defining NO_CHAR_TEST will disable the tedious checking * of these ranges for a slight performance increase. */ #ifdef NO_CHAR_TEST #define charSetOK(A, B, C) #define CHECK_CAR_SET(A) #define SET_CHAR_SET(A) #else /* !NO_CHAR_TEST */ typedef enum {CharSet_ALPHAS = 1, CharSet_DIGITS = 2, CharSet_PLUSMINUS = 4, CharSet_FORSLASH = 8, CharSet_EXTENS = 0x10, CharSet_BASE64_EXTRAS = 0x20, CharSet_DATE_EXTRAS = 0x40, CharSet_URL_EXTRAS = 0x80, /* ------------------ BNF names are combinations of the above ------------------- */ CharSet_NUMBER = CharSet_DIGITS | CharSet_PLUSMINUS, CharSet_ALPHANUMPM = CharSet_ALPHAS | CharSet_DIGITS | CharSet_PLUSMINUS, CharSet_TRANSMIT_NAME = CharSet_ALPHANUMPM | CharSet_URL_EXTRAS, CharSet_EXT_ALPHANUM = CharSet_ALPHANUMPM | CharSet_EXTENS, CharSet_BASE64 = CharSet_ALPHAS | CharSet_DIGITS | CharSet_BASE64_EXTRAS, CharSet_URL = CharSet_ALPHAS | CharSet_DIGITS | CharSet_URL_EXTRAS, CharSet_DATE = CharSet_DIGITS | CharSet_DATE_EXTRAS, CharSet_EXT_DATA = CharSet_DATE | CharSet_URL | CharSet_NUMBER | CharSet_EXT_ALPHANUM } CharSet_t; PRIVATE BOOL charSetOK(CSParse_t * pCSParse, char * checkMe, CharSet_t set); #define CHECK_CAR_SET(A) \ if (!charSetOK(pCSParse, token, A)) \ return StateRet_ERROR_BAD_CHAR; #define SET_CHAR_SET(A) pCSLabel->targetCharSet = A; #endif /* !NO_CHAR_TEST */ /* C S L L S t a t e */ /* This holds label list data and the methods to view it. All application * interface is intended to go through these methods. See User/Parsing.html */ struct CSLabel_s { CSLLData_t * pCSLLData; LabelError_t * pCurrentLabelError; LabelOptions_t * pCurrentLabelOptions; Extension_t * pCurrentExtension; ExtensionData_t * pCurrentExtensionData; ServiceInfo_t * pCurrentServiceInfo; Label_t * pCurrentLabel; int currentLabelNumber; HTList * pCurrentLabelTree; SingleLabel_t * pCurrentSingleLabel; LabelRating_t * pCurrentLabelRating; Range_t * pCurrentRange; #ifndef NO_CHAR_TEST CharSet_t targetCharSet; #endif LabelTargetCallback_t * pLabelTargetCallback; LLErrorHandler_t * pLLErrorHandler; }; /* forward references to parser functions */ PRIVATE TargetObject_t LabelList_targetObject; PRIVATE TargetObject_t ServiceInfo_targetObject; PRIVATE TargetObject_t ServiceNoRat_targetObject; PRIVATE TargetObject_t ServiceError_targetObject; PRIVATE TargetObject_t Label_targetObject; PRIVATE TargetObject_t LabelError_targetObject; PRIVATE TargetObject_t LabelTree_targetObject; PRIVATE TargetObject_t SingleLabel_targetObject; PRIVATE TargetObject_t LabelRating_targetObject; PRIVATE TargetObject_t LabelRatingRange_targetObject; PRIVATE TargetObject_t Extension_targetObject; PRIVATE TargetObject_t ExtensionData_targetObject; PRIVATE TargetObject_t Awkward_targetObject; PRIVATE Check_t hasToken; PRIVATE Check_t LabelList_getVersion; PRIVATE Check_t ServiceInfo_getServiceId; PRIVATE Check_t error_getExpl; PRIVATE Check_t getOption; PRIVATE Check_t getOptionValue; PRIVATE Check_t LabelRating_getId; PRIVATE Check_t LabelRating_getValue; PRIVATE Check_t LabelRatingRange_get; PRIVATE Check_t isQuoted; PRIVATE Check_t Extension_getURL; PRIVATE Check_t ExtensionData_getData; PRIVATE Open_t LabelList_open; PRIVATE Open_t ServiceInfo_open; PRIVATE Open_t error_open; PRIVATE Open_t Label_open; PRIVATE Open_t LabelTree_open; PRIVATE Open_t SingleLabel_open; PRIVATE Open_t LabelRating_open; PRIVATE Open_t LabelRatingRange_open; PRIVATE Open_t Awkward_open; PRIVATE Open_t Extension_open; PRIVATE Open_t ExtensionData_open; PRIVATE Close_t LabelList_close; PRIVATE Close_t ServiceInfo_close; PRIVATE Close_t error_close; PRIVATE Close_t Label_close; PRIVATE Close_t LabelTree_close; PRIVATE Close_t SingleLabel_close; PRIVATE Close_t LabelRating_close; PRIVATE Close_t LabelRatingRange_close; PRIVATE Close_t Awkward_close; PRIVATE Close_t Extension_close; PRIVATE Close_t ExtensionData_close; PRIVATE Destroy_t LabelList_destroy; PRIVATE Destroy_t ServiceInfo_destroy; PRIVATE Destroy_t Label_destroy; PRIVATE Destroy_t LabelTree_destroy; PRIVATE Destroy_t SingleLabel_destroy; PRIVATE Destroy_t LabelRating_destroy; PRIVATE Destroy_t LabelRatingRange_destroy; PRIVATE Destroy_t Awkward_destroy; PRIVATE Destroy_t error_destroy; PRIVATE Destroy_t Extension_destroy; PRIVATE Destroy_t ExtensionData_destroy; PRIVATE Prep_t ServiceInfo_clearOpts; PRIVATE Prep_t LabelRating_next; PRIVATE Prep_t Extension_mandatory; PRIVATE Prep_t Extension_next; PRIVATE Prep_t ExtensionData_next; PRIVATE Prep_t SingleLabel_doClose; PRIVATE Prep_t Label_doClose; PRIVATE TargetChangeCallback_t targetChangeCallback; PRIVATE ParseErrorHandler_t parseErrorHandler; /* CSParse_doc states */ /* L A B E L L I S T P A R S E R S T A T E S */ /* This contains all the states in the BNF for PICS labels. * See User/Parsing.html for details. */ PRIVATE StateToken_t LabelList_stateTokens[] = { /* A: fresh LabelList C: expect end */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelList_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, {"get version", SubState_A, Punct_WHITE, &LabelList_getVersion, 0, 0, 0, &ServiceInfo_targetObject, SubState_N, Command_NONE, 0}, {"end of list", SubState_C, Punct_RPAREN, 0, 0, 0, 0, &LabelList_targetObject, SubState_A, Command_MATCHANY_CLOSE, 0} }; PRIVATE StateToken_t ServiceInfo_stateTokens[] = { /* A: fresh ServiceInfo B: has service id C: needs option value D: call from Awkward or NoRat to close E: call from Awkward to re-enter F: call from Awkward to handle no-ratings error */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "error w/o id", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &ServiceNoRat_targetObject, SubState_N, Command_NONE, 0}, { "service id", SubState_A, Punct_WHITE, &ServiceInfo_getServiceId, 0, 0, 0, &ServiceInfo_targetObject, SubState_B, Command_NONE, 0}, { "service error", SubState_B, Punct_LPAREN, 0, "error", 0, 0, &ServiceError_targetObject, SubState_N, Command_NONE, 0}, { "service option", SubState_B, Punct_WHITE, &getOption, 0, 0, 0, &ServiceInfo_targetObject, SubState_C, Command_NONE, 0}, {"service extension", SubState_B, Punct_LPAREN, 0, "extension", 0, 0, &Extension_targetObject, SubState_N, Command_NONE, 0}, { "label-mark close", SubState_B, Punct_RPAREN, 0, "l", "labels", 0, &LabelList_targetObject, SubState_C, Command_CLOSE_CHAIN, 0}, { "label-mark", SubState_B, Punct_WHITE_LPAREN, 0, "l", "labels", 0, &Label_targetObject, SubState_N, Command_CHAIN, &ServiceInfo_clearOpts}, { "option value", SubState_C, Punct_WHITE, &getOptionValue, 0, 0, 0, &ServiceInfo_targetObject, SubState_B, Command_NONE, 0}, { "close", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelList_targetObject, SubState_C, Command_MATCHANY_CLOSE_CHAIN, 0}, { "re-enter", SubState_E, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_N, Command_MATCHANY_CLOSE_CHAIN, 0}, { "to no-rat", SubState_F, Punct_ALL, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_G, Command_MATCHANY_CLOSE_CHAIN, 0}, { "no-rat opener", SubState_G, Punct_ALL, 0, 0, 0, 0, &ServiceNoRat_targetObject, SubState_N, Command_MATCHANY_OPEN_CHAIN, 0} }; PRIVATE StateToken_t Label_stateTokens[] = { /* A: fresh SingleLabel C: route to Awkward from LabelTree and LabelError D: from Awkward to LabelError */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Label_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "single label mark", SubState_A, Punct_WHITE, 0, "l", "labels", 0, &Label_targetObject, SubState_A, Command_NONE, 0}, /* stick around */ { "tree label mark", SubState_A, Punct_LPAREN, 0, "l", "labels", 0, &LabelTree_targetObject, SubState_N, Command_NONE, 0}, { "start tree", SubState_A, Punct_LPAREN, 0, 0, 0, 0, &LabelTree_targetObject, SubState_N, Command_NONE, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &LabelError_targetObject, SubState_N, Command_NONE, 0}, {"SingleLabel option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "ratings", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "to awkward", SubState_C, Punct_ALL, 0, 0, 0, 0, &Awkward_targetObject, SubState_A, Command_MATCHANY_CLOSE, 0}, { "awkward to error", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelError_targetObject, SubState_N, Command_MATCHANY_OPEN_CHAIN, 0} }; PRIVATE StateToken_t LabelTree_stateTokens[] = { /* A: LabelTrees have no state */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelTree_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &LabelError_targetObject, SubState_N, Command_NONE, 0}, {"SingleLabel option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "ratingword", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &SingleLabel_targetObject, SubState_N, Command_CHAIN, 0}, { "end of tree", SubState_A, Punct_RPAREN, 0, 0, 0, 0, &Label_targetObject, SubState_C, Command_CLOSE_CHAIN, 0} }; PRIVATE StateToken_t SingleLabel_stateTokens[] = { /* A: fresh SingleLabel B: needs option value */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &SingleLabel_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, {"label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &Extension_targetObject, SubState_N, Command_NONE, 0}, { "label option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &SingleLabel_targetObject, SubState_B, Command_NONE, 0}, { "ratingword", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &LabelRating_targetObject, SubState_N, Command_NONE, 0}, { "option value", SubState_B, Punct_WHITE, &getOptionValue, 0, 0, 0, &SingleLabel_targetObject, SubState_A, Command_NONE, 0} }; PRIVATE StateToken_t LabelRating_stateTokens[] = { /* A: looking for transmit name B: looking for value C: return from range (either creates a new rating or ends) D: close and re-open */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelRating_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "id before value", SubState_A, Punct_WHITE, &LabelRating_getId, 0, 0, 0, &LabelRating_targetObject, SubState_B, Command_NONE, 0}, { "id before range", SubState_A, Punct_LPAREN, &LabelRating_getId, 0, 0, 0, &LabelRatingRange_targetObject, SubState_N, Command_NONE, 0}, { "value next", SubState_B, Punct_WHITE, &LabelRating_getValue, 0, 0, 0, &LabelRating_targetObject, SubState_D, Command_NONE, 0}, /* opener must close last rating first */ { "value close", SubState_B, Punct_RPAREN, &LabelRating_getValue, 0, 0, 0, 0, SubState_X, Command_CLOSE, &LabelRating_next}, { "close", SubState_C, Punct_RPAREN, 0, 0, 0, 0, 0, SubState_X, Command_CLOSE, &LabelRating_next}, {"value after range", SubState_C, Punct_WHITE_LPAREN, &hasToken, 0, 0, 0, &LabelRating_targetObject, SubState_D, Command_CHAIN, 0}, /* opener must close last rating first */ { "re-enter", SubState_D, Punct_ALL, 0, 0, 0, 0, &LabelRating_targetObject, SubState_N, Command_MATCHANY_CLOSE_CHAIN, 0} }; PRIVATE StateToken_t LabelRatingRange_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelRatingRange_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "range data", SubState_A, Punct_WHITE, &LabelRatingRange_get, 0, 0, 0, &LabelRatingRange_targetObject, SubState_A, Command_NONE, 0}, {"range close", SubState_A, Punct_RPAREN, &LabelRatingRange_get, 0, 0, 0, &LabelRating_targetObject, SubState_C, Command_CLOSE, 0} }; /* Awkward assumes that the current Label has been closed. It decides whether to chain to LabelTree, Label, or ServiceInfo */ PRIVATE StateToken_t Awkward_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Awkward_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "start tree", SubState_A, Punct_LPAREN, 0, 0, 0, 0, &LabelTree_targetObject, SubState_N, Command_NONE, 0}, { "label error", SubState_A, Punct_LPAREN, 0, "error", 0, 0, &Awkward_targetObject, SubState_B, Command_NONE, 0}, { "label option", SubState_A, Punct_WHITE, &getOption, 0, 0, 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, {"label extension", SubState_A, Punct_LPAREN, 0, "extension", 0, 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, { "rating", SubState_A, Punct_LPAREN, 0, "r", "ratings", 0, &Label_targetObject, SubState_N, Command_CHAIN, 0}, { "new service id", SubState_A, Punct_WHITE, &isQuoted, 0, 0, 0, &ServiceInfo_targetObject, SubState_E, Command_CHAIN, 0}, { "close", SubState_A, Punct_RPAREN, 0, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CHAIN, 0}, /* close of LabelList */ { "req-denied", SubState_B, Punct_WHITE, 0, "request-denied", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "req-denied close", SubState_B, Punct_RPAREN, 0, "request-denied", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "not-labeled", SubState_B, Punct_WHITE, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, {"not-labeled close", SubState_B, Punct_RPAREN, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_D, Command_CHAIN, 0}, { "no-ratings", SubState_B, Punct_WHITE, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_F, Command_CHAIN, 0}, { "no-ratings close", SubState_B, Punct_RPAREN, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_F, Command_CHAIN, 0} }; /* error parsing states */ PRIVATE StateToken_t ServiceNoRat_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceNoRat_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "no-ratings", SubState_A, Punct_WHITE, 0, "no-ratings", 0, 0, &ServiceNoRat_targetObject, SubState_B, Command_NONE, 0}, { "no-ratings close", SubState_A, Punct_RPAREN, 0, "no-ratings", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &ServiceNoRat_targetObject, SubState_B, Command_NONE, 0}, {"explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE_CHAIN, 0} }; PRIVATE StateToken_t ServiceError_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ServiceError_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "req-denied", SubState_A, Punct_WHITE, 0, "request-denied", 0, 0, &ServiceError_targetObject, SubState_B, Command_NONE, 0}, { "req-denied close", SubState_A, Punct_RPAREN, 0, "request-denied", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE_CHAIN, 0}, { "service-unavail", SubState_A, Punct_WHITE, 0,"service-unavailable", 0, 0, &ServiceError_targetObject, SubState_B, Command_NONE, 0}, {"service-unavail close", SubState_A, Punct_RPAREN, 0,"service-unavailable", 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &ServiceError_targetObject, SubState_B, Command_NONE, 0}, { "explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &ServiceInfo_targetObject, SubState_D, Command_CLOSE_CHAIN, 0} }; PRIVATE StateToken_t LabelError_stateTokens[] = { { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &LabelError_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "req-denied", SubState_A, Punct_WHITE, 0, "request-denied", 0, 0, &LabelError_targetObject, SubState_B, Command_NONE, 0}, { "req-denied close", SubState_A, Punct_RPAREN, 0, "request-denied", 0, 0, &Label_targetObject, SubState_C, Command_CLOSE_CHAIN, 0}, { "not-labeled", SubState_A, Punct_WHITE, 0, "not-labeled", 0, 0, &LabelError_targetObject, SubState_B, Command_NONE, 0}, {"not-labeled close", SubState_A, Punct_RPAREN, 0, "not-labeled", 0, 0, &Label_targetObject, SubState_C, Command_CLOSE_CHAIN, 0}, { "explanation", SubState_B, Punct_WHITE, &error_getExpl, 0, 0, 0, &LabelError_targetObject, SubState_B, Command_NONE, 0}, {"explanation close", SubState_B, Punct_RPAREN, &error_getExpl, 0, 0, 0, &Label_targetObject, SubState_C, Command_CLOSE_CHAIN, 0} }; PRIVATE StateToken_t Extension_stateTokens[] = { /* A: looking for mand/opt B: looking for URL C: back from ExtensionData */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &Extension_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "mandatory", SubState_A, Punct_WHITE, 0, "mandatory", 0, 0, &Extension_targetObject, SubState_B, Command_NONE, &Extension_mandatory}, { "optional", SubState_A, Punct_WHITE, 0, "optional", 0, 0, &Extension_targetObject, SubState_B, Command_NONE, 0}, { "URL", SubState_B, Punct_WHITE, &Extension_getURL, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_NONE, 0}, { "URL open", SubState_B, Punct_LPAREN, &Extension_getURL, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_CHAIN_NOTOKEN, 0}, { "URL close", SubState_B, Punct_RPAREN, &Extension_getURL, 0, 0, 0, 0, SubState_X, Command_CLOSE, &Extension_next}, { "more data", SubState_C, Punct_WHITE_LPAREN_RPAREN, &hasToken, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_CHAIN, 0}, { "nest", SubState_C, Punct_LPAREN, 0, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_CHAIN, 0}, { "close", SubState_C, Punct_RPAREN, 0, 0, 0, 0, 0, SubState_X, Command_CLOSE, &Extension_next} }; PRIVATE StateToken_t ExtensionData_stateTokens[] = { /* A: looking for data B: back from recursive ExtensionData (identical to Extension B) */ { "open", SubState_N, Punct_ALL, 0, 0, 0, 0, &ExtensionData_targetObject, SubState_A, Command_MATCHANY_OPEN_CHAIN, 0}, { "lparen", SubState_A, Punct_LPAREN, 0, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_NONE, 0}, { "close", SubState_A, Punct_RPAREN, 0, 0, 0, 0, 0, SubState_X, Command_CLOSE, &ExtensionData_next}, { "data", SubState_A, Punct_WHITE, &ExtensionData_getData, 0, 0, 0, 0, SubState_X, Command_CLOSE, &ExtensionData_next}, {"data punct", SubState_A, Punct_LPAREN_RPAREN, &ExtensionData_getData, 0, 0, 0, 0, SubState_X, Command_CLOSE_CHAIN_NOTOKEN, &ExtensionData_next}, { "more data", SubState_B, Punct_WHITE_LPAREN_RPAREN, &hasToken, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_CHAIN, 0}, { "nest", SubState_B, Punct_LPAREN, 0, 0, 0, 0, &ExtensionData_targetObject, SubState_N, Command_CHAIN, 0}, { "close", SubState_B, Punct_RPAREN, 0, 0, 0, 0, 0, SubState_X, Command_CLOSE, &ExtensionData_next} }; PRIVATE void init_target_obj(TargetObject_t *obj, char *note, Open_t *pOpen, Close_t *pClose, Destroy_t *pDestroy, StateToken_t *stateToken, int stateTokenCount, CSParseTC_t targetChange) { obj->note = note; obj->pOpen = pOpen; obj->pClose = pClose; obj->pDestroy = pDestroy; obj->stateTokens = stateToken; obj->stateTokenCount = stateTokenCount; obj->targetChange = targetChange; } PRIVATE void CSinitialize_global_data(void) { static XP_Bool first_time=TRUE; if(first_time) { first_time = FALSE; init_target_obj(&LabelList_targetObject, "LabelList", &LabelList_open, &LabelList_close, &LabelList_destroy, LabelList_stateTokens, raysize(LabelList_stateTokens), CSLLTC_LIST); init_target_obj(&ServiceInfo_targetObject, "ServiceInfo", ServiceInfo_open, &ServiceInfo_close, &ServiceInfo_destroy, ServiceInfo_stateTokens, raysize(ServiceInfo_stateTokens), CSLLTC_SERVICE); init_target_obj(&Label_targetObject, "Label", &Label_open, &Label_close, &Label_destroy, Label_stateTokens, raysize(Label_stateTokens), CSLLTC_LABEL); init_target_obj(&LabelTree_targetObject, "LabelTree", &LabelTree_open, &LabelTree_close, &LabelTree_destroy, LabelTree_stateTokens, raysize(LabelTree_stateTokens), CSLLTC_LABTREE); init_target_obj(&SingleLabel_targetObject, "SingleLabel", &SingleLabel_open, &SingleLabel_close, &SingleLabel_destroy, SingleLabel_stateTokens, raysize(SingleLabel_stateTokens), CSLLTC_SINGLE); init_target_obj(&LabelRating_targetObject, "LabelRating", &LabelRating_open, &LabelRating_close, &LabelRating_destroy, LabelRating_stateTokens, raysize(LabelRating_stateTokens), CSLLTC_RATING); init_target_obj(&LabelRatingRange_targetObject, "LabelRatingRange", &LabelRatingRange_open, &LabelRatingRange_close, &LabelRatingRange_destroy, LabelRatingRange_stateTokens, raysize(LabelRatingRange_stateTokens), CSLLTC_RANGE); init_target_obj(&Awkward_targetObject, "Awkward", &Awkward_open, &Awkward_close, &Awkward_destroy, Awkward_stateTokens, raysize(Awkward_stateTokens), 0); init_target_obj(&ServiceNoRat_targetObject, "ServiceNoRat", &error_open, &error_close, &error_destroy, ServiceNoRat_stateTokens, raysize(ServiceNoRat_stateTokens), CSLLTC_NORAT); init_target_obj(&LabelError_targetObject, "LabelError", &error_open, &error_close, &error_destroy, LabelError_stateTokens, raysize(LabelError_stateTokens), CSLLTC_LABERR); init_target_obj(&ServiceError_targetObject, "ServiceError", &error_open, &error_close, &error_destroy, ServiceError_stateTokens, raysize(ServiceError_stateTokens), CSLLTC_SRVERR); init_target_obj(&Extension_targetObject, "Extension", &Extension_open, &Extension_close, &Extension_destroy, Extension_stateTokens, raysize(Extension_stateTokens), CSLLTC_EXTEN); init_target_obj(&ExtensionData_targetObject, "ExtensionData", &ExtensionData_open, &ExtensionData_close, &ExtensionData_destroy, ExtensionData_stateTokens, raysize(ExtensionData_stateTokens), CSLLTC_EXTDATA); } } /* CSParse_doc end */ /* S T A T E A S S O C I A T I O N - associate a CSLabel with the label list data The label list data is kept around until all states referencing it are destroyed */ typedef struct { CSLabel_t * pCSLabel; CSLLData_t * pCSLLData; } CSLabelAssoc_t; PRIVATE HTList * CSLabelAssocs = 0; PRIVATE void CSLabelAssoc_add(CSLabel_t * pCSLabel, CSLLData_t * pCSLLData) { CSLabelAssoc_t * pElement; if ((pElement = (CSLabelAssoc_t *) HT_CALLOC(1, sizeof(CSLabelAssoc_t))) == NULL) HT_OUTOFMEM("CSLabelAssoc_t"); pElement->pCSLabel = pCSLabel; pElement->pCSLLData = pCSLLData; if (!CSLabelAssocs) CSLabelAssocs = HTList_new(); HTList_appendObject(CSLabelAssocs, (void *)pElement); } PRIVATE CSLabelAssoc_t * CSLabelAssoc_findByData(CSLLData_t * pCSLLData) { HTList * assocs = CSLabelAssocs; CSLabelAssoc_t * pElement; while ((pElement = (CSLabelAssoc_t *) HTList_nextObject(assocs)) != NULL) if (pElement->pCSLLData == pCSLLData) return pElement; return 0; } PRIVATE CSLabelAssoc_t * CSLabelAssoc_findByState(CSLabel_t * pCSLabel) { HTList * assocs = CSLabelAssocs; CSLabelAssoc_t * pElement; while ((pElement = (CSLabelAssoc_t *) HTList_nextObject(assocs)) != NULL) if (pElement->pCSLabel == pCSLabel) return pElement; return 0; } PRIVATE void CSLabelAssoc_removeByState(CSLabel_t * pCSLabel) { CSLabelAssoc_t * pElement = CSLabelAssoc_findByState(pCSLabel); if (!pElement) return; HTList_removeObject(CSLabelAssocs, (void *)pElement); HT_FREE(pElement); } /* P R I V A T E C O N S T R U C T O R S / D E S T R U C T O R S */ /* These serve the public constructors */ PRIVATE LabelError_t * LabelError_new(void) { LabelError_t * me; if ((me = (LabelError_t *) HT_CALLOC(1, sizeof(LabelError_t))) == NULL) HT_OUTOFMEM("LabelError_t"); me->explanations = HTList_new(); return me; } PRIVATE void LabelError_free(LabelError_t * me) { char * explanation; if (!me) return; while ((explanation = (char *) HTList_removeLastObject(me->explanations)) != NULL) HT_FREE(explanation); HT_FREE(me); } PRIVATE LabelOptions_t * LabelOptions_new(LabelOptions_t * pParentLabelOptions) { LabelOptions_t * me; if ((me = (LabelOptions_t *) HT_CALLOC(1, sizeof(LabelOptions_t))) == NULL) HT_OUTOFMEM("LabelOptions_t"); me->pParentLabelOptions = pParentLabelOptions; return me; } PRIVATE void LabelOptions_free(LabelOptions_t * me) { char * comment; DVal_clear(&me->at); SVal_clear(&me->by); SVal_clear(&me->complete_label); BVal_clear(&me->generic); SVal_clear(&me->fur); SVal_clear(&me->MIC_md5); DVal_clear(&me->on); SVal_clear(&me->signature_PKCS); DVal_clear(&me->until); while ((comment = HTList_removeLastObject(me->comments)) != NULL) HT_FREE(comment); HT_FREE(me); } PRIVATE ExtensionData_t * ExtensionData_new(void) { ExtensionData_t * me; if ((me = (ExtensionData_t *) HT_CALLOC(1, sizeof(ExtensionData_t))) == NULL) HT_OUTOFMEM("ExtensionData_t"); return me; } PRIVATE void ExtensionData_free(ExtensionData_t * me) { ExtensionData_t * pExtensionData; while ((pExtensionData = (ExtensionData_t *) HTList_removeLastObject(me->moreData)) != NULL) ExtensionData_free(pExtensionData); HT_FREE(me->text); HT_FREE(me); } PRIVATE Extension_t * Extension_new(void) { Extension_t * me; if ((me = (Extension_t *) HT_CALLOC(1, sizeof(Extension_t))) == NULL) HT_OUTOFMEM("Extension_t"); return me; } PRIVATE void Extension_free(Extension_t * me) { ExtensionData_t * pExtensionData; while ((pExtensionData = (ExtensionData_t *) HTList_removeLastObject(me->extensionData)) != NULL) ExtensionData_free(pExtensionData); SVal_clear(&me->url); HT_FREE(me); } PRIVATE LabelRating_t * LabelRating_new(void) { LabelRating_t * me; if ((me = (LabelRating_t *) HT_CALLOC(1, sizeof(LabelRating_t))) == NULL) HT_OUTOFMEM("LabelRating_t"); /* don't initialize HTList me->ranges as it may be just a value */ return me; } PRIVATE void LabelRating_free(LabelRating_t * me) { Range_t * pRange; while ((pRange = (Range_t *) HTList_removeLastObject(me->ranges)) != NULL) HT_FREE(pRange); SVal_clear(&me->identifier); HT_FREE(me); } PRIVATE SingleLabel_t * SingleLabel_new(LabelOptions_t * pLabelOptions, LabelOptions_t * pParentLabelOptions) { SingleLabel_t * me; if ((me = (SingleLabel_t *) HT_CALLOC(1, sizeof(SingleLabel_t))) == NULL) HT_OUTOFMEM("SingleLabel_t"); me->labelRatings = HTList_new(); me->pLabelOptions = pLabelOptions ? pLabelOptions : LabelOptions_new(pParentLabelOptions); return me; } PRIVATE void SingleLabel_free(SingleLabel_t * me) { LabelRating_t * pLabelRating; while ((pLabelRating = (LabelRating_t *) HTList_removeLastObject(me->labelRatings)) != NULL) LabelRating_free(pLabelRating); LabelOptions_free(me->pLabelOptions); HT_FREE(me); } PRIVATE Label_t * Label_new(void) { Label_t * me; if ((me = (Label_t *) HT_CALLOC(1, sizeof(Label_t))) == NULL) HT_OUTOFMEM("Label_t"); /* dont initialize HTList me->singleLabels */ return me; } PRIVATE void Label_free(Label_t * me) { SingleLabel_t * pSingleLabel; if (me->pSingleLabel) SingleLabel_free(me->pSingleLabel); else /* if both of these are (erroneously) defined, mem checkers will pick it up */ while ((pSingleLabel = (SingleLabel_t *) HTList_removeLastObject(me->singleLabels)) != NULL) SingleLabel_free(pSingleLabel); LabelError_free(me->pLabelError); HT_FREE(me); } PRIVATE ServiceInfo_t * ServiceInfo_new() { ServiceInfo_t * me; if ((me = (ServiceInfo_t *) HT_CALLOC(1, sizeof(ServiceInfo_t))) == NULL) HT_OUTOFMEM("ServiceInfo_t"); me->labels = HTList_new(); me->pLabelOptions = LabelOptions_new(0); return me; } PRIVATE void ServiceInfo_free(ServiceInfo_t * me) { Label_t * pLabel; while ((pLabel = (Label_t *) HTList_removeLastObject(me->labels)) != NULL) Label_free(pLabel); SVal_clear(&me->rating_service); LabelOptions_free(me->pLabelOptions); LabelError_free(me->pLabelError); HT_FREE(me); } PRIVATE CSLLData_t * CSLLData_new(void) { CSLLData_t * me; if ((me = (CSLLData_t *) HT_CALLOC(1, sizeof(CSLLData_t))) == NULL) HT_OUTOFMEM("CSLLData_t"); me->serviceInfos = HTList_new(); return me; } PRIVATE void CSLLData_free(CSLLData_t * me) { ServiceInfo_t * pServiceInfo; if (CSLabelAssoc_findByData(me)) return; while ((pServiceInfo = (ServiceInfo_t *) HTList_removeLastObject(me->serviceInfos)) != NULL) ServiceInfo_free(pServiceInfo); FVal_clear(&me->version); LabelError_free(me->pLabelError); HT_FREE(me); } /* P U B L I C C O N S T R U C T O R S / D E S T R U C T O R S */ PRIVATE CSLabel_t * CSLabel_new(CSLLData_t * pCSLLData, LabelTargetCallback_t * pLabelTargetCallback, LLErrorHandler_t * pLLErrorHandler) { CSLabel_t * me; if ((me = (CSLabel_t *) HT_CALLOC(1, sizeof(CSLabel_t))) == NULL) HT_OUTOFMEM("CSLabel_t"); me->pCSLLData = pCSLLData; me->pLabelTargetCallback = pLabelTargetCallback; me->pLLErrorHandler = pLLErrorHandler; CSLabelAssoc_add(me, pCSLLData); return me; } PUBLIC CSLabel_t * CSLabel_copy(CSLabel_t * old) { CSLabel_t * me = CSLabel_new(old->pCSLLData, old->pLabelTargetCallback, old->pLLErrorHandler); /* --- BEGIN converted by mharmsen@netscape.com on 7/9/97 --- */ XP_MEMCPY(me, old, sizeof(CSLabel_t)); /* --- END converted by mharmsen@netscape.com on 7/9/97 --- */ return me; } PUBLIC void CSLabel_free(CSLabel_t * me) { CSLLData_t * pCSLLData = me->pCSLLData; CSLabelAssoc_removeByState(me); HT_FREE(me); CSLLData_free(pCSLLData); } PUBLIC CSLLData_t * CSLabel_getCSLLData(CSLabel_t * me) {return me->pCSLLData;} PUBLIC LabelError_t * CSLabel_getLabelError(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentLabelError;} PUBLIC LabelOptions_t * CSLabel_getLabelOptions(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentLabelOptions;} PUBLIC ServiceInfo_t * CSLabel_getServiceInfo(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentServiceInfo;} PUBLIC char * CSLabel_getServiceName(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentServiceInfo ? SVal_value(&pCSLabel->pCurrentServiceInfo->rating_service): 0;} PUBLIC Label_t * CSLabel_getLabel(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentLabel;} PUBLIC int CSLabel_getLabelNumber(CSLabel_t * pCSLabel) {return pCSLabel->currentLabelNumber;} PUBLIC SingleLabel_t * CSLabel_getSingleLabel(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentSingleLabel;} PUBLIC LabelRating_t * CSLabel_getLabelRating(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentLabelRating;} PUBLIC char * CSLabel_getRatingName(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentLabelRating ? SVal_value(&pCSLabel->pCurrentLabelRating->identifier): 0;} PUBLIC Range_t * CSLabel_getLabelRatingRange(CSLabel_t * pCSLabel) {return pCSLabel->pCurrentRange;} PUBLIC char * CSLabel_getRatingStr(CSLabel_t * pCSLabel) { HTChunk * pChunk; HTList * ranges; Range_t * curRange; FVal_t fVal; int count = 0; fVal = CSLabel_getLabelRating(pCSLabel)->value; if (FVal_initialized(&fVal)) return FVal_toStr(&fVal); pChunk = HTChunk_new(20); ranges = CSLabel_getLabelRating(pCSLabel)->ranges; while ((curRange = (Range_t *) HTList_nextObject(ranges)) != NULL) { char * ptr; count++; ptr = Range_toStr(curRange); if (count > 1) HTChunk_puts(pChunk, " "); HTChunk_puts(pChunk, ptr); HT_FREE(ptr); } return HTChunk_toCString(pChunk); } PUBLIC CSParse_t * CSParse_newLabel(LabelTargetCallback_t * pLabelTargetCallback, LLErrorHandler_t * pLLErrorHandler) { CSParse_t * me = CSParse_new(); CSinitialize_global_data(); me->pParseContext->engineOf = &CSParse_targetParser; me->pParseContext->pTargetChangeCallback = &targetChangeCallback; me->pParseContext->pParseErrorHandler = &parseErrorHandler; me->target.pCSLabel = CSLabel_new(CSLLData_new(), pLabelTargetCallback, pLLErrorHandler); me->pTargetObject = &LabelList_targetObject; me->currentSubState = SubState_N; return me; } PUBLIC CSLabel_t * CSParse_getLabel(CSParse_t * me) { return (me->target.pCSLabel); } PUBLIC BOOL CSParse_deleteLabel(CSParse_t * pCSParse) { CSLabel_t * me = GetCSLabel(pCSParse); CSLLData_free(CSLabel_getCSLLData(me)); CSLabel_free(me); CSParse_delete(pCSParse); return YES; } /* D E F A U L T P A R S I N G H A N D L E R S */ PRIVATE StateRet_t targetChangeCallback(CSParse_t * pCSParse, TargetObject_t * pTargetObject, CSParseTC_t target, BOOL closed, void * pVoid) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); if (pCSLabel->pLabelTargetCallback) return (*pCSLabel->pLabelTargetCallback)(pCSLabel, pCSParse, (CSLLTC_t)target, closed, pVoid); return StateRet_OK; } PRIVATE StateRet_t parseErrorHandler(CSParse_t * pCSParse, const char * token, char demark, StateRet_t errorCode) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); if (pCSLabel->pLLErrorHandler) return (*pCSLabel->pLLErrorHandler)(pCSLabel, pCSParse, token, demark, errorCode); return errorCode; } /* CSParse_doc methods */ /* P A R S I N G S T A T E F U N C T I O N S */ #ifndef NO_CHAR_TEST PRIVATE BOOL charSetOK(CSParse_t * pCSParse, char * checkMe, CharSet_t set) { if(!checkMe) return FALSE; for (;*checkMe;checkMe++) { if (set & CharSet_ALPHAS && ((*checkMe >= 'A' && *checkMe <= 'Z') || (*checkMe >= 'a' && *checkMe <= 'z'))) continue; if (set & CharSet_DIGITS && ((*checkMe >= '0' && *checkMe <= '9') || *checkMe == '.')) continue; if (set & CharSet_PLUSMINUS && ((*checkMe == '+' || *checkMe == '-'))) continue; if (set & CharSet_FORSLASH && *checkMe == '/') continue; if (set & CharSet_BASE64_EXTRAS && ((*checkMe == '+' || *checkMe == '/' || *checkMe == '='))) continue; if (set & CharSet_DATE_EXTRAS && (*checkMe == '.' || *checkMe == ':' || *checkMe == '-' || *checkMe == 'T')) continue; /* RFC1738:2.1:"+.-","#%",";/"?:@=&" 2.2:"$-_.+!*'()," */ if (set & CharSet_URL_EXTRAS && (*checkMe == ':' || *checkMe == '?' || *checkMe == '#' || *checkMe == '%' || *checkMe == '/' || *checkMe == '.' || *checkMe == '-' || *checkMe == '_' || *checkMe == '~' || *checkMe == '\\'|| *checkMe == '@')) continue; /* '.' | ' ' | ',' | ';' | ':' | '&' | '=' | '?' | '!' | '*' | '~' | '@' | '#' */ if (set & CharSet_EXTENS && (*checkMe == '.' || *checkMe == ' ' || *checkMe == ',' || *checkMe == ';' || *checkMe == ':' || *checkMe == '&' || *checkMe == '=' || *checkMe == '?' || *checkMe == '!' || *checkMe == '*' || *checkMe == '~' || *checkMe == '@' || *checkMe == '#' || *checkMe == '\''|| *checkMe == '/' || *checkMe == '-')) continue; pCSParse->pParseContext->pTokenError = checkMe; return FALSE; } return TRUE; } #endif /* !NO_CHAR_TEST */ PRIVATE StateRet_t isQuoted(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { ParseContext_t * pParseContext = pCSParse->pParseContext; if (!pParseContext->observedQuotes) return StateRet_WARN_NO_MATCH; if (Punct_badDemark(pStateToken->validPunctuation, demark)) return StateRet_WARN_BAD_PUNCT; return StateRet_OK; } PRIVATE StateRet_t hasToken(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { return token ? StateRet_OK : StateRet_WARN_NO_MATCH; } #if 0 PRIVATE StateRet_t clearToken(CSParse_t * pCSParse, char * token, char demark) { HTChunk_clear(pCSParse->token); return StateRet_OK; } #endif /* getOption - see if token matches an option. This may be called by: ServiceInfo: add option to existent options, pCurrentLabelError is set by ServiceInfo_open Label: kick off SingleLabel - SingleLabel_new(), pCurrentLabelError is 0 SingleLabel: add another option to existent options, pCurrentLabelError is set by SingleLabel_open */ #define CSOffsetOf(s,m) (size_t)&(((s *)0)->m) /* --- BEGIN converted by mharmsen@netscape.com on 7/9/97 --- */ #define CHECK_OPTION_TOKEN_BVAL1(text, pointer) \ if (!XP_STRCASECMP(token, text)) {\ pCSParse->pParseContext->valTarget.pTargetBVal = pointer;\ pCSParse->pParseContext->valType = ValType_BVAL;\ break;\ } #define CHECK_OPTION_TOKEN_FVAL1(text, pointer) \ if (!XP_STRCASECMP(token, text)) {\ pCSParse->pParseContext->valTarget.pTargetFVal = pointer;\ pCSParse->pParseContext->valType = ValType_FVAL;\ break;\ } #define CHECK_OPTION_TOKEN_SVAL1(text, pointer, charSet) \ if (!XP_STRCASECMP(token, text)) {\ pCSParse->pParseContext->valTarget.pTargetSVal = pointer;\ pCSParse->pParseContext->valType = ValType_SVAL;\ SET_CHAR_SET(charSet)\ break;\ } #define CHECK_OPTION_TOKEN_DVAL1(text, pointer) \ if (!XP_STRCASECMP(token, text)) {\ pCSParse->pParseContext->valTarget.pTargetDVal = pointer;\ pCSParse->pParseContext->valType = ValType_DVAL;\ break;\ } /* --- END converted by mharmsen@netscape.com on 7/9/97 --- */ PRIVATE StateRet_t getOption(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); LabelOptions_t * me = pCSLabel->pCurrentLabelOptions; if (!token) return StateRet_WARN_NO_MATCH; if (!me) me = pCSLabel->pCurrentLabelOptions = LabelOptions_new(pCSLabel->pCurrentServiceInfo->pLabelOptions); /* match token against legal options */ pCSParse->pParseContext->valType = ValType_NONE; /* use valType to flag a match */ /* --- BEGIN converted by mharmsen@netscape.com on 7/9/97 --- */ do { /* fake do loop for break statements (to religiously avoid the goto) */ CHECK_OPTION_TOKEN_DVAL1("at", &me->at) CHECK_OPTION_TOKEN_SVAL1("by", &me->by, CharSet_EXT_ALPHANUM) CHECK_OPTION_TOKEN_SVAL1("complete_label", &me->complete_label, CharSet_URL) CHECK_OPTION_TOKEN_SVAL1("full", &me->complete_label, CharSet_URL) CHECK_OPTION_TOKEN_SVAL1("for", &me->fur, CharSet_URL) CHECK_OPTION_TOKEN_BVAL1("generic", &me->generic) CHECK_OPTION_TOKEN_BVAL1("gen", &me->generic) CHECK_OPTION_TOKEN_SVAL1("MIC-md5", &me->MIC_md5, CharSet_BASE64) CHECK_OPTION_TOKEN_SVAL1("md5", &me->MIC_md5, CharSet_BASE64) CHECK_OPTION_TOKEN_DVAL1("on", &me->on) CHECK_OPTION_TOKEN_SVAL1("signature-PKCS", &me->signature_PKCS, CharSet_BASE64) CHECK_OPTION_TOKEN_DVAL1("until", &me->until) CHECK_OPTION_TOKEN_DVAL1("exp", &me->until) if (!XP_STRCASECMP(token, "comment")) { pCSParse->pParseContext->valTarget.pTargetList = &me->comments; pCSParse->pParseContext->valType = ValType_COMMENT; break; } } while (0); /* --- END converted by mharmsen@netscape.com on 7/9/97 --- */ if (pCSParse->pParseContext->valType == ValType_NONE) return StateRet_WARN_NO_MATCH; if (Punct_badDemark(pStateToken->validPunctuation, demark)) return StateRet_WARN_BAD_PUNCT; return StateRet_OK; } PRIVATE StateRet_t getOptionValue(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); switch (pCSParse->pParseContext->valType) { case ValType_BVAL: BVal_readVal(pCSParse->pParseContext->valTarget.pTargetBVal, token); pCSParse->pParseContext->valType = ValType_NONE; break; case ValType_FVAL: CHECK_CAR_SET(CharSet_NUMBER) FVal_readVal(pCSParse->pParseContext->valTarget.pTargetFVal, token); pCSParse->pParseContext->valType = ValType_NONE; break; case ValType_SVAL: CHECK_CAR_SET(pCSLabel->targetCharSet) SVal_readVal(pCSParse->pParseContext->valTarget.pTargetSVal, token); pCSParse->pParseContext->valType = ValType_NONE; break; case ValType_DVAL: CHECK_CAR_SET(CharSet_DATE) DVal_readVal(pCSParse->pParseContext->valTarget.pTargetDVal, token); pCSParse->pParseContext->valType = ValType_NONE; break; case ValType_COMMENT: CHECK_CAR_SET(CharSet_EXT_ALPHANUM) { char * ptr = 0; StrAllocCopy(ptr, token); HTList_appendObject(*pCSParse->pParseContext->valTarget.pTargetList, (void *)ptr); } break; default: break; } return StateRet_OK; } PRIVATE StateRet_t LabelList_open(CSParse_t * pCSParse, char * token, char demark) { return StateRet_OK; } PRIVATE StateRet_t LabelList_getVersion(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { static const char versionPrefix[] = "PICS-"; CSLabel_t * pCSLabel = GetCSLabel(pCSParse); if (!token) return StateRet_WARN_NO_MATCH; if (strncasecomp(token, versionPrefix, sizeof(versionPrefix)-1)) return StateRet_WARN_NO_MATCH; token += sizeof(versionPrefix)-1; CHECK_CAR_SET(CharSet_NUMBER) FVal_readVal(&pCSLabel->pCSLLData->version, token); return StateRet_OK; } PRIVATE StateRet_t LabelList_close(CSParse_t * pCSParse, char * token, char demark) { return StateRet_DONE; } PRIVATE void LabelList_destroy(CSParse_t * pCSParse) { } PRIVATE StateRet_t ServiceInfo_open(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentServiceInfo = ServiceInfo_new(); pCSLabel->currentLabelNumber = 0; HTList_appendObject(pCSLabel->pCSLLData->serviceInfos, (void *)pCSLabel->pCurrentServiceInfo); pCSLabel->pCurrentLabelOptions = pCSLabel->pCurrentServiceInfo->pLabelOptions; return StateRet_OK; } PRIVATE StateRet_t ServiceInfo_getServiceId(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); ParseContext_t * pParseContext = pCSParse->pParseContext; if (!token || !pParseContext->observedQuotes) return StateRet_WARN_NO_MATCH; if (Punct_badDemark(pStateToken->validPunctuation, demark)) return StateRet_WARN_BAD_PUNCT; CHECK_CAR_SET(CharSet_URL) SVal_readVal(&pCSLabel->pCurrentServiceInfo->rating_service, token); return StateRet_OK; } PRIVATE StateRet_t ServiceInfo_close(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentServiceInfo = 0; return StateRet_OK; } PRIVATE void ServiceInfo_destroy(CSParse_t * pCSParse) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); HTList_removeObject(pCSLabel->pCSLLData->serviceInfos, (void *)pCSLabel->pCurrentServiceInfo); ServiceInfo_free(pCSLabel->pCurrentServiceInfo); pCSLabel->pCurrentServiceInfo = 0; } PRIVATE StateRet_t ServiceInfo_clearOpts(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentLabelOptions = 0; /* needed to flag new SingleLabel started by option */ return StateRet_OK; } PRIVATE StateRet_t Label_open(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentLabel = Label_new(); pCSLabel->currentLabelNumber++; HTList_appendObject(pCSLabel->pCurrentServiceInfo->labels, (void*)pCSLabel->pCurrentLabel); return StateRet_OK; } PRIVATE StateRet_t Label_close(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentLabel = 0; return StateRet_OK; } PRIVATE void Label_destroy(CSParse_t * pCSParse) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); HTList_removeObject(pCSLabel->pCurrentServiceInfo->labels, pCSLabel->pCurrentLabel); Label_free(pCSLabel->pCurrentLabel); pCSLabel->pCurrentLabel = 0; } PRIVATE StateRet_t LabelTree_open(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCSLLData->hasTree = 1; pCSLabel->pCurrentLabelTree = pCSLabel->pCurrentLabel->singleLabels = HTList_new(); return StateRet_OK; } PRIVATE StateRet_t LabelTree_close(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); /* Label_close(pCSParse, token, demark); */ pCSLabel->pCurrentLabelTree = 0; return StateRet_OK; } PRIVATE void LabelTree_destroy(CSParse_t * pCSParse) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); SingleLabel_t * pSingleLabel; while ((pSingleLabel = (SingleLabel_t *) HTList_removeLastObject(pCSLabel->pCurrentLabel->singleLabels)) != NULL) SingleLabel_free(pSingleLabel); HTList_delete(pCSLabel->pCurrentLabel->singleLabels); pCSLabel->pCurrentLabel->singleLabels = 0; } PRIVATE StateRet_t SingleLabel_open(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentSingleLabel = SingleLabel_new(pCSLabel->pCurrentLabelOptions, pCSLabel->pCurrentServiceInfo->pLabelOptions); if (pCSLabel->pCurrentLabel->singleLabels) HTList_appendObject(pCSLabel->pCurrentLabel->singleLabels, (void*)pCSLabel->pCurrentSingleLabel); else pCSLabel->pCurrentLabel->pSingleLabel = pCSLabel->pCurrentSingleLabel; pCSLabel->pCurrentLabelOptions = pCSLabel->pCurrentSingleLabel->pLabelOptions; return StateRet_OK; } PRIVATE StateRet_t SingleLabel_close(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); pCSLabel->pCurrentSingleLabel = 0; return StateRet_OK; } PRIVATE void SingleLabel_destroy(CSParse_t * pCSParse) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); if (pCSLabel->pCurrentLabel->pSingleLabel) pCSLabel->pCurrentLabel->pSingleLabel = 0; else HTList_removeObject(pCSLabel->pCurrentLabel->singleLabels, (void *)pCSLabel->pCurrentSingleLabel); SingleLabel_free(pCSLabel->pCurrentSingleLabel); pCSLabel->pCurrentSingleLabel = 0; } PRIVATE StateRet_t LabelRating_open(CSParse_t * pCSParse, char * token, char demark) { CSLabel_t * pCSLabel = GetCSLabel(pCSParse); if (!pCSLabel->pCurrentSingleLabel) /* switched from label to rating on "r" rather than