06620d160679a0d2e77dedbe35b35edeea08c517 chmalee Mon Jun 3 16:17:48 2019 -0700 Add checks to hubCheck and hgTrackUi for incorrect tag=val pairs in a subgroup line, refs #13428 diff --git src/hg/lib/hui.c src/hg/lib/hui.c index 585e876..c0eb9f1 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -2506,37 +2506,30 @@ static char *tagEncode(char *name) // Turns out css classes cannot begin with a number. So prepend 'A' // If this were more widely used, could move to cheapcgi.c. { if (!isdigit(*name)) return name; char *newName = needMem(strlen(name)+2); *newName = 'A'; strcpy(newName+1,name); return newName; } -typedef struct _dimensions - { - int count; - char**names; - char**subgroups; - char* setting; - } dimensions_t; boolean dimensionsExist(struct trackDb *parentTdb) // Does this parent track contain dimensions? { return (trackDbSetting(parentTdb, "dimensions") != NULL); } static dimensions_t *dimensionSettingsGet(struct trackDb *parentTdb) // Parses any dimemnions setting in parent of subtracks { dimensions_t *dimensions = needMem(sizeof(dimensions_t)); dimensions->setting = cloneString(trackDbSetting(parentTdb, "dimensions")); // To be freed later if (dimensions->setting == NULL) { freeMem(dimensions); @@ -2660,30 +2653,34 @@ return NULL; } members->groupTag = words[0]; members->groupTitle = strSwapChar(words[1],'_',' '); // Titles replace '_' with space members->tags = needMem(count*sizeof(char*)); members->titles = needMem(count*sizeof(char*)); for (ix = 2,members->count=0; ix < count; ix++) { char *name,*value; if (parseAssignment(words[ix], &name, &value)) { members->tags[members->count] = tagEncode(name); members->titles[members->count] = strSwapChar(value,'_',' '); members->count++; } + else + { + warn("Subgroup \"%s\" is missing a tag=val pair", words[1]); + } } tdbExtrasMembersSet(parentTdb, groupNameOrTag, members); return members; } static int membersSubGroupIx(members_t* members, char *tag) // Returns the index of the subgroup within the members struct (or -1) { int ix = 0; for (ix=0;ixcount;ix++) { if (members->tags[ix] != NULL && sameString(members->tags[ix],tag)) return ix; } @@ -2777,45 +2774,30 @@ //subgroupMembersFree(&members); // don't bother freeing return NULL; } return members; } enum { dimV=0, // View first dimX=1, // X & Y next dimY=2, dimA=3, // dimA is start of first of the optional non-matrix, non-view dimensions }; -typedef struct _membersForAll - { - int abcCount; - int dimMax; // Arrays of "members" structs will be ordered as - // [view][dimX][dimY][dimA]... with first 3 in fixed spots - // and rest as found (and non-empty) - boolean filters; // ABCs use filterComp boxes (as upposed to check boxes - dimensions_t *dimensions; // One struct describing "deimensions" setting" - // (e.g. dimX:cell dimY:antibody dimA:treatment) - members_t* members[27]; // One struct for each dimension describing groups in dimension - // (e.g. cell: GM12878,K562) - char* checkedTags[27]; // FIXME: Should move checkedTags into - // membersForAll->members[ix]->selected; - char letters[27]; - } membersForAll_t; static char* abcMembersChecked(struct trackDb *parentTdb, struct cart *cart, members_t* members, char letter) // returns a string of subGroup tags which are currently checked { char settingName[SMALLBUF]; int mIx; if (members->selected == NULL) members->selected = needMem(members->count * sizeof(boolean)); safef(settingName, sizeof(settingName), "%s.filterComp.%s",parentTdb->track,members->groupTag); struct slName *options = cartOptionalSlNameList(cart,settingName); if (options != NULL) { if (sameWord(options->name,"All")) // filterComp returns "All" meaning every option selected @@ -2900,31 +2882,31 @@ if (ixOut < ixIn) // Collapse if necessary { // NOTE: Don't I wish I had made these as an slList ages ago! (tim) membersForAll->members[ixOut] = membersForAll->members[ixIn]; membersForAll->checkedTags[ixOut] = membersForAll->checkedTags[ixIn]; membersForAll->letters[ixOut] = membersForAll->letters[ixIn]; } ixOut++; } } membersForAll->dimMax = ixOut; membersForAll->abcCount = membersForAll->dimMax - dimA; return membersForAll; } -static membersForAll_t* membersForAllSubGroupsGet(struct trackDb *parentTdb, struct cart *cart) +membersForAll_t* membersForAllSubGroupsGet(struct trackDb *parentTdb, struct cart *cart) // Returns all the parents subGroups and members { membersForAll_t *membersForAll = tdbExtrasMembersForAll(parentTdb); if (membersForAll != NULL) return membersForAll; // Already retrieved, so don't do it again int ix; membersForAll = needMem(sizeof(membersForAll_t)); if (tdbIsCompositeView(parentTdb->subtracks)) // view must have viewInMidle tdb in tree membersForAll->members[dimV]=subgroupMembersGet(parentTdb,"view"); membersForAll->letters[dimV]='V'; membersForAll->dimMax=dimA; // This can expand, depending upon ABC dimensions membersForAll->dimensions = dimensionSettingsGet(parentTdb); if (membersForAll->dimensions != NULL) {