/* * Added by [email protected] (94/04/08) */ PRIVATE BOOL lang_match (HTAtom * tmplate, HTAtom * actual) { const char *t, *a; char *st, *sa; BOOL match = NO; if (tmplate && actual && (t = HTAtom_name(tmplate)) && (a = HTAtom_name(actual))) { st = strchr(t, '_'); sa = strchr(a, '_'); if ((st != NULL) && (sa != NULL)) { if (!strcasecomp(t, a)) match = YES; else match = NO; } else { if (st != NULL) *st = 0; if (sa != NULL) *sa = 0; if (!strcasecomp(t, a)) match = YES; else match = NO; if (st != NULL) *st = '_'; if (sa != NULL) *sa = '_'; } } return match; }
/* ** Matches MIME constructions for content-types and others like ** them, for example "text/html", "text/plain". It can also match ** wild cards like "text/<star>" and "<star>/<star>. We use <star> ** instead of * in order note to make C like comments :-) */ PUBLIC BOOL HTMIMEMatch (HTAtom * tmplate, HTAtom * actual) { const char *t, *a; char *st, *sa; BOOL match = NO; if (tmplate && actual && (t = HTAtom_name(tmplate))) { if (!strcmp(t, "*")) return YES; if (strchr(t, '*') && (a = HTAtom_name(actual)) && (st = strchr(t, '/')) && (sa = strchr(a,'/'))) { *sa = 0; *st = 0; if ((*(st-1)=='*' && (*(st+1)=='*' || !strcasecomp(st+1, sa+1))) || (*(st+1)=='*' && !strcasecomp(t,a))) match = YES; *sa = '/'; *st = '/'; } } return match; }
int dumbterm( char *terminal ) { int dumb = 0; if ( terminal == 0 || strcasecomp( terminal, "network" ) == 0 || strcasecomp( terminal, "unknown" ) == 0 || strcasecomp( terminal, "dialup" ) == 0 || strcasecomp( terminal, "dumb" ) == 0 || strcasecomp( terminal, "switch" ) == 0 || strcasecomp( terminal, "ethernet" ) == 0 ) { dumb = 1; } return dumb; }
PRIVATE int DirCaseSort (const void *a, const void *b) { #if 0 HTDirNode *aa = *(HTDirNode **) a; HTDirNode *bb = *(HTDirNode **) b; return strcasecomp(aa->fname, bb->fname); #else return strcasecomp((*((HTDirNode **) a))->fname, (*((HTDirNode **) b))->fname); #endif }
PUBLIC BOOL BVal_readVal(BVal_t * pBVal, const char * valueStr) { if (!strcasecomp(valueStr, "true") || !strcasecomp(valueStr, "yes")) pBVal->state = BVal_YES; else if (strcasecomp(valueStr, "false") && strcasecomp(valueStr, "no")) return NO;; pBVal->state |= BVal_INITIALIZED; return YES; }
/* PUBLIC HTAAMethod_enum() ** TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE ** ON ENTRY: ** name is the method name to translate. ** ** ON EXIT: ** returns HTAAMethod enumerated value corresponding ** to the given name. */ PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name) { if (!name) return METHOD_UNKNOWN; if (0==strcasecomp(name, "GET")) return METHOD_GET; else if (0==strcasecomp(name, "PUT")) return METHOD_PUT; else return METHOD_UNKNOWN; }
/* PUBLIC HTAAMethod_enum() * TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE * ON ENTRY: * name is the method name to translate. * * ON EXIT: * returns HTAAMethod enumerated value corresponding * to the given name. */ HTAAMethod HTAAMethod_enum(const char *name) { if (!name) return METHOD_UNKNOWN; if (0 == strcasecomp(name, "GET")) return METHOD_GET; else if (0 == strcasecomp(name, "PUT")) return METHOD_PUT; else return METHOD_UNKNOWN; }
/* ** MIME header parser for the Set-Cookie header field. We parse the cookies ** and create HTCookie objects and store them in the cookie holder so that ** the cookie after filter can deal with them accordingly. */ PRIVATE int HTCookie_parseSetCookie (HTRequest * request, HTResponse * response, char * token, char * value) { char * cookie_name = NULL; char * cookie_value = NULL; if (HTCookie_splitPair(HTNextParam(&value), &cookie_name, &cookie_value) != HT_OK) { return HT_ERROR; /* Malformed Cookie */ } if (cookie_name && *cookie_name && cookie_value) { HTCookie * cookie = HTCookie_new(); char * param_pair; HTCookie_setName(cookie, cookie_name); HTCookie_setValue(cookie, cookie_value); /* Add the cookie to our holder */ HTCookieHolder_addCookie(request, cookie); /* Parse cookie parameters */ while ((param_pair = HTNextParam(&value))) { char * tok = NULL; char * val = NULL; if (HTCookie_splitPair(param_pair, &tok, &val) != HT_OK) { return HT_ERROR; /* Malformed Cookie */ } if (tok) { if (!strcasecomp(tok, "expires") && val && *val) { HTTRACE(STREAM_TRACE, "Cookie...... Expires `%s\'\n" _ val); HTCookie_setExpiration(cookie, HTParseTime(val, NULL, YES)); } else if (!strcasecomp(tok, "domain") && val && *val) { HTTRACE(STREAM_TRACE, "Cookie...... Domain `%s\'\n" _ val); HTCookie_setDomain(cookie, val); } else if (!strcasecomp(tok, "path") && val && *val) { HTTRACE(STREAM_TRACE, "Cookie...... Path `%s\'\n" _ val); HTCookie_setPath(cookie, val); } else if (!strcasecomp(tok, "secure")) { HTTRACE(STREAM_TRACE, "Cookie...... Secure `%s\'\n" _ val); HTCookie_setSecure(cookie, YES); } else HTTRACE(STREAM_TRACE, "Cookie...... Unknown `%s\' with value `%s\'\n" _ tok _ val ? val : "<null>"); } } } return HT_OK; }
PUBLIC BOOL FVal_readVal(FVal_t * pFVal, const char * valueStr) { if (!strcasecomp(valueStr, "+INF")) { pFVal->stat = FVal_POSITIVE_INF; return YES; } if (!strcasecomp(valueStr, "-INF")) { pFVal->stat = FVal_NEGATIVE_INF; return YES; } pFVal->stat = FVal_VALUE; sscanf(valueStr, "%f", &pFVal->value); return YES; }
/* * Find the given command-name, accepting an abbreviation if it is unique. */ Kcmd *LYStringToKcmd(const char *name) { size_t need = strlen(name); size_t j; BOOL exact = FALSE; Kcmd *result = 0; Kcmd *maybe = 0; if (non_empty(name)) { for (j = 0; revmap[j].name != 0; j++) { if (!strcasecomp(revmap[j].name, name)) { result = revmap + j; break; } else if (!exact && !strncasecomp(revmap[j].name, name, (int) need)) { if (maybe == 0) { maybe = revmap + j; } else { if (revmap[j].name[need] != 0 && maybe->name[need] != 0) { maybe = 0; exact = TRUE; } } } } } return (result != 0) ? result : maybe; }
/* PUBLIC HTAA_templateCaseMatch() * STRING COMPARISON FUNCTION FOR FILE NAMES * WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive) * NOTE: * This is essentially the same code as in HTAA_templateMatch, but * it compares case insensitive (for VMS). Reason for this routine * is that HTAA_templateMatch gets called from several places, also * there where a case sensitive match is needed, so one cannot just * change the HTAA_templateMatch routine for VMS. * * ON ENTRY: * template is a template string to match the file name * against, may contain a single wildcard * character * which matches zero or more * arbitrary characters. * filename is the filename (or pathname) to be matched * against the template. * * ON EXIT: * returns YES, if filename matches the template. * NO, otherwise. */ BOOL HTAA_templateCaseMatch(const char *ctemplate, const char *filename) { const char *p = ctemplate; const char *q = filename; int m; /* Find first mismatch */ for (; *p && *q && TOUPPER(*p) == TOUPPER(*q); p++, q++) ; /* do nothing else */ if (!*p && !*q) return YES; /* Equally long equal strings */ else if ('*' == *p) { /* Wildcard */ p++; /* Skip wildcard character */ m = (int) (strlen(q) - strlen(p)); /* Amount to match to wildcard */ if (m < 0) return NO; /* No match, filename too short */ else { /* Skip the matched characters and compare */ if (strcasecomp(p, q + m)) return NO; /* Tail mismatch */ else return YES; /* Tail match */ } /* if wildcard */ } else return NO; /* Length or character mismatch */ }
BOOLEAN LYgetEnum( Config_Enum *table, char *name, int *result ) { Config_Enum *found = 0; unsigned int len = strlen( name ); int match = 0; if ( len ) { for ( ; table->name[0]; table++ ) { if ( strncasecomp( &table->name[0], name, (int)len ) == 0 ) { found = table; if ( strcasecomp( &table->name[0], name ) == 0 ) { match = 1; break; } else match++; } // table++; } if ( match == 1 ) { result[0] = found->value; return 0; } table++; } return 0; }
int LYStringToKeycode(char *src) { unsigned n; int key = -1; int len = (int) strlen(src); if (len == 1) { key = *src; } else if (len == 2 && *src == '^') { key = src[1] & 0x1f; } else if (len > 2 && !strncasecomp(src, "0x", 2)) { char *dst = 0; key = (int) strtol(src, &dst, 0); if (non_empty(dst)) key = -1; } else if (len > 6 && !strncasecomp(src, "key-", 4)) { char *dst = 0; key = (int) strtol(src + 4, &dst, 0); if (isEmpty(dst)) key = -1; } if (key < 0) { for (n = 0; n < TABLESIZE(named_keys); n++) { if (!strcasecomp(named_keys[n].name, src)) { key = named_keys[n].key; break; } } } return key; }
/* ** PROPFIND requests */ PRIVATE BOOL propfind_request (Cmdline * arg) { BOOL status = NO; HTDAVHeaders * headers = HTDAVHeaders_new(); HTRequest * request = create_request (); HTAnchor * dst = HTAnchor_findAddress(arg->request_uri); HTParentAnchor *base = NULL; HTParentAnchor *src = NULL; char * xmlbody = NULL; /* chose the func */ HTPrint ("should we set the xml body?\n"); if (arg->arg1 && *(arg->arg1)) { if (!strcasecomp (arg->arg1,"allprop") || !strcasecomp (arg->arg1,"propname")) xmlbody = create_propbody (arg->arg1); else xmlbody = arg->arg1; HTPrint ("xml body %s\n",xmlbody); } if (arg->func==2 && xmlbody && *xmlbody) { src = HTTmpAnchor(NULL); HTAnchor_setDocument(src, xmlbody); HTAnchor_setFormat(src, HTAtom_for ("text/xml")); HTAnchor_setLength(src, strlen(xmlbody)); } if (arg->base_str && *(arg->base_str)) base = (HTParentAnchor *) HTAnchor_findAddress(arg->base_str); HTPrint ("setting headers\n"); if (arg->D) HTDAV_setDepthHeader (headers,arg->D); switch (arg->func) { case 1: status = HTPROPFINDAnchor (request,dst,xmlbody,headers); break; case 2: status = HTPROPFINDDocumentAnchor (request,dst,src,headers); break; case 3: status = HTPROPFINDAbsolute (request,arg->request_uri,xmlbody,headers); break; case 4: status = HTPROPFINDRelative (request,arg->request_uri,base,xmlbody,headers); break; } return status; }
PUBLIC char * CSUserList_findURL(char * username) { HTList * cur = UserList; UserListStruct_t * pUser; while ((pUser = (UserListStruct_t *) HTList_nextObject(cur))) { if (!strcasecomp(username, pUser->name)) return pUser->url; } return 0; }
PUBLIC int tailcasecomp(const char * s1, const char * s2) { int l1 = strlen(s1); int l2 = strlen(s2); if (l1 < l2) s2 += (l2 - l1); return strcasecomp(s1, s2); }
/* NewsPost_start ** -------------- ** NNTP needs two extra headers: "From" and "Newsgroups". ** Take the newsgroups from the Postweb model as destinations for this ** anchor. ** Return YES if OK else NO */ PRIVATE BOOL NewsPost_start (HTStream * me, HTRequest * request) { char linebuf[128]; /* @@@ */ HTChunk *header = me->buffer; HTUserProfile * up = HTRequest_userProfile(request); const char * mailaddress = HTUserProfile_email(up); if (mailaddress) { sprintf(linebuf, "From: %s%c%c", mailaddress, CR, LF); HTChunk_puts(header, linebuf); } /* ** Find all the newsgroups we are posting to by looking at all the ** destinations from the source of this request. ** First the main link and then the sub links */ HTChunk_puts(header, "Newsgroups :"); if (HTRequest_isDestination(request)) { HTRequest *src_req = HTRequest_source(request); HTParentAnchor *src_anchor = HTRequest_anchor(src_req); HTLink *link = HTAnchor_mainLink((HTAnchor *) src_anchor); HTAnchor *dest = HTLink_destination(link); HTMethod method = HTLink_method(link); if (link && method == METHOD_POST && HTLink_result(link) == HT_LINK_NONE) { char *desturl = HTAnchor_physical((HTParentAnchor *) dest); char *access = HTParse(desturl, "", PARSE_ACCESS); if (!strcasecomp(access, "news") || !strcasecomp(access, "nntp")) { char *newsgroup = HTParse(desturl, "", PARSE_PATH); HTUnEscape(newsgroup); HTCleanTelnetString(newsgroup); HTChunk_puts(header, newsgroup); HT_FREE(newsgroup); } HT_FREE(access); } /* DO FOR ALL SUB ANCHOR DESTINATION S AS WELL */ } HTTRACE(PROT_TRACE, "News Tx..... %s" _ HTChunk_data(header)); return YES; }
/* Added by MP. */ PRIVATE HTNewsNode* HTNewsDir_findNodeNamed (HTNewsDir* dir, char* name) { int i; for (i = 0; i < HTArray_size(dir->array); i++) { HTNewsNode* node = (HTNewsNode*)(HTArray_data(dir->array)[i]); if (node->name && strcasecomp(node->name, name) == 0) return node; } return NULL; }
/* Add a AA context to the URL tree ** -------------------------------- ** Each node in the AA URL tree is a list of the modules we must call ** for this particular node. */ PUBLIC void * HTAA_updateNode (BOOL proxy_access, char const * scheme, const char * realm, const char * url, void * context) { HTUTree * tree = NULL; HTAAModule * module = NULL; if (!scheme || !url) { HTTRACE(AUTH_TRACE, "Auth Engine. Bad argument\n"); return NULL; } HTTRACE(AUTH_TRACE, "Auth Engine. Adding 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 NULL; } /* 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 NULL; } } /* Find a matching AA element or create a new one */ { char * path = HTParse(url, "", PARSE_PATH | PARSE_PUNCTUATION); HTAAElement * element = NULL; BOOL status; if ((element = (HTAAElement *) HTUTree_findNode(tree, realm, path)) && element->scheme && !strcasecomp (element->scheme, scheme)) status = HTAA_updateElement(element, scheme, context); else { /* create the new element */ element = HTAA_newElement(scheme, context); status = HTUTree_addNode(tree, realm, path, element); } HT_FREE(path); return status==YES ? element->context : NULL; } }
PUBLIC int HTMIME_connection (HTRequest * request, HTResponse * response, char * token, char * value) { /* ** Walk through the set of connection directives and add them to the ** response association list for connection directives */ char * name_val; while ((name_val = HTNextPair(&value)) != NULL) { char * name = HTNextField(&name_val); char * val = HTNextField(&name_val); /* ** If we have a name then look if it is concerning persistent ** connections. If so, then we handle it here, otherwise we leave it ** to somebody else by simply adding it to the list of connection ** tokens. */ if (name) { HTNet * net = HTRequest_net(request); HTHost * host = HTNet_host(net); if (!strcasecomp(name, "close")) { /* HTTP/1.1 */ HTTRACE(STREAM_TRACE, "MIMEParser.. Close received...\n"); HTHost_setCloseNotification(host, YES); } else if (!strcasecomp(name, "keep-alive")) { /* HTTP/1.0 */ /* ** In case this is an HTTP/1.1 server sending keep-alive then ** ignore it. */ if (HTHost_version(host) < HTTP_11) { HTNet_setPersistent(net, YES, HT_TP_SINGLE); HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive\n"); } else HTTRACE(STREAM_TRACE, "MIMEParser.. HTTP/1.0 Keep Alive ignored\n"); } else HTResponse_addConnection(response, name, val ? val : ""); } } return HT_OK; }
/* Added by MP. */ PRIVATE void HTNewsNode_setRefInfo_pass2 (HTNewsDir* dir, HTNewsNode* node) { HTNewsNode* maxParent = NULL; HTList* ptr = node->refObjects; HTNewsNode* parent = NULL; if (node->fake) return; if (ptr != NULL) parent = (HTNewsNode*) HTList_nextObject(ptr); while (ptr != NULL) { if (!maxParent || maxParent->date < parent->date) maxParent = parent; parent = (HTNewsNode*) HTList_nextObject(ptr); } if (maxParent) { if (!HTNewsNode_isAncestor(node, maxParent)) /* better be careful */ HTNewsNode_linkRef (maxParent, node); } else { char* refSubject; BOOL re; /* Here is the only place we REALLY have to check for circular */ /* references. It is normally possible that a node refers to */ /* orphan node and both have the same subject. In this situation */ /* we can't make the orphan to refer to it's child. Without checking */ /* for circular references this is likely to happen here. */ refSubject = UnReSubject(node->subject); re = (strcasecomp(refSubject, node->subject) != 0); if (re) parent = HTNewsDir_findNodeWithSubject(dir, refSubject, FNWS_MIN | FNWS_NOTFAKE, node); if (!parent || HTNewsNode_isAncestor(node, parent)) parent = HTNewsDir_findNodeWithSubject(dir, refSubject, FNWS_MIN | FNWS_ONLYFAKE, node); if (!parent && re) { parent = HTNewsDir_findNodeWithSubject(dir, node->subject, FNWS_MIN | FNWS_ONLYFAKE, node); } if (!parent) parent = HTNewsDir_addFakeElement (dir, refSubject, NULL); if (parent) { HTNewsNode_linkRef (parent, node); if (parent->refChildren > 1) /* Multi-children fake node visible */ parent->show = YES; } } }
PUBLIC char * HTAssocList_findObjectExact (HTAssocList * list, const char * name) { if (list && name) { HTAssocList * cur = list; HTAssoc * assoc; while ((assoc = (HTAssoc *) HTList_nextObject(cur))) { if (!strcasecomp(assoc->name, name)) return assoc->value; } } return NULL; }
PRIVATE HTAAModule * find_module (const char * scheme) { if (!HTSchemes) HTSchemes = HTList_new(); if (scheme) { HTList * cur = HTSchemes; HTAAModule * pres = NULL; while ((pres = (HTAAModule *) HTList_nextObject(cur))) if (!strcasecomp(pres->scheme, scheme)) return pres; } else HTTRACE(AUTH_TRACE, "Auth Engine. Bad argument\n"); return NULL; }
/* ** Check the response to see if we got a cookie or more. ** If so then figure out what to do with it (prompt user, store, etc.) */ PRIVATE int HTCookie_afterFilter (HTRequest * request, HTResponse * response, void * param, int status) { if ((CookieMode & HT_COOKIE_ACCEPT) && SetCookie) { HTCookieHolder * holder = HTCookieHolder_find(request); if (holder) { HTList * cookies = holder->cookies; HTCookie * pres; while ((pres = (HTCookie *) HTAssocList_nextObject(cookies))) { /* Should we check to see if hosts match? */ if (CookieMode & (HT_COOKIE_SAME_HOST|HT_COOKIE_SAME_DOMAIN)) { char * cookie_host = HTCookie_domain(pres); if (cookie_host) { int res; char * addr = HTAnchor_address((HTAnchor *) HTRequest_anchor(request)); char * host = HTParse(addr, "", PARSE_HOST); if (CookieMode & HT_COOKIE_SAME_DOMAIN) res = tailcasecomp(cookie_host, host); else res = strcasecomp(cookie_host, host); if (res != 0) { HTTRACE(APP_TRACE, "Cookie...... Host `%s\' doesn't match what is sent in cookie `%s\'\n" _ host _ cookie_host); HT_FREE(addr); continue; } HT_FREE(addr); } } /* Should we prompt the user? */ if (CookieMode & HT_COOKIE_PROMPT) { HTAlertCallback * prompt = HTAlert_find(HT_A_CONFIRM); if (prompt) { if ((*prompt)(request, HT_A_CONFIRM, HT_MSG_ACCEPT_COOKIE, NULL, NULL, NULL) != YES) continue; } else continue; } /* Call the application with our new cookie */ (*SetCookie)(request, pres, SetCookieContext); } /* Delete cookie holder */ HTCookieHolder_delete(holder); } } return HT_OK; }
/* ** Do multiformat handling ** ----------------------- ** On entry: ** req->conversions accepted content-types ** req->encodings accepted content-transfer-encodings ** req->languages accepted content-languages ** path absolute pathname of the filename for ** which the match is desired. ** stat_info pointer to result space. ** ** On exit: ** returns a newly allocated absolute filepath of the best ** match, or NULL if no match. ** stat_info will contain inode information as ** returned by stat(). */ PUBLIC char * HTMulti (HTRequest * req, char * path, struct stat * stat_info) { char * new_path = NULL; int stat_status = -1; if (!req || !path || !*path || !stat_info) return NULL; #ifdef HAVE_READDIR if (*(path+strlen(path)-1) == '/') { /* Find welcome page */ new_path = get_best_welcome(path); if (new_path) path = new_path; } else{ char * multi = strrchr(path, MULTI_SUFFIX[0]); if (multi && !strcasecomp(multi, MULTI_SUFFIX)) { HTTRACE(PROT_TRACE, "Multi....... by %s suffix\n" _ MULTI_SUFFIX); if (!(new_path = HTGetBest(req, path))) { HTTRACE(PROT_TRACE, "Multi....... failed -- giving up\n"); return NULL; } path = new_path; } else { stat_status = HT_STAT(path, stat_info); if (stat_status == -1) { HTTRACE(PROT_TRACE, "AutoMulti... can't stat \"%s\"(errno %d)\n" _ path _ errno); if (!(new_path = HTGetBest(req, path))) { HTTRACE(PROT_TRACE, "AutoMulti... failed -- giving up\n"); return NULL; } path = new_path; } } } #endif /* HAVE_READDIR */ if (stat_status == -1) stat_status = HT_STAT(path, stat_info); if (stat_status == -1) { HTTRACE(PROT_TRACE, "Stat fails.. on \"%s\" -- giving up (errno %d)\n" _ path _ errno); return NULL; } else { if (!new_path) { StrAllocCopy(new_path, path); return new_path; } else return path; } }
int string_to_attr( char *name ) { unsigned int i = 0; for ( ; i <= 6; i++ ) { if ( strcasecomp( Mono_Attrs[ i ].name, name ) == 0 ) { return Mono_Attrs[ i ].code; } // i++; } return 0; }
PUBLIC HTStyle * HTStyleSheet_findStyleWithName (HTStyleSheet * me, const char * name) { if (me && name) { HTList * cur = me->styles; HTStyle * pres; while ((pres = (HTStyle *) HTList_nextObject(cur))) { if (!strcasecomp(pres->name, name)) return pres; } HTTRACE(SGML_TRACE, "StyleSheet.. No style named `%s' in stylesheet `%s'\n" _ name _ me->name); } return NULL; }
PUBLIC int SGML_findElementNumber (SGML_dtd * dtd, char * name_element) { if (dtd && name_element) { int i; HTTag *ct; for (i = 0; i< dtd->number_of_tags; i++) { ct = &(dtd->tags[i]); if (!strcasecomp(ct->name,name_element)) return i; } } return -1; }
/* * Three-way compare function */ PRIVATE int compare_anchors ARGS2( void *, l, void *, r) { CONST char* a = ((HTChildAnchor *)l)->tag; CONST char* b = ((HTChildAnchor *)r)->tag; /* both tags are not NULL */ #ifdef CASE_INSENSITIVE_ANCHORS return strcasecomp(a, b); /* Case insensitive */ #else return strcmp(a, b); /* Case sensitive - FM */ #endif /* CASE_INSENSITIVE_ANCHORS */ }
/* Added by MP. */ PUBLIC BOOL HTNewsDir_belongsToSet (HTNewsDir* dir, char* group) { char* p; if (!dir->name || !*(dir->name)) return YES; p = strrchr(dir->name, '*'); if (!p) return strcasecomp(group, dir->name) == 0; else { int len = p - dir->name; return strncasecomp(group, dir->name, len) == 0; } }