/* remove tags from start and end of a string, for innerHTML */ static void tagStrip(char *line) { char *s = line; if (*s != '<') { /* this shouldn't happen, don't know what to do. */ return; } s = strchr(line, '>'); if (!s) return; ++s; skipWhite2(&s); strmove(line, s); trimWhite(line); s = line + strlen(line); if (s == line || s[-1] != '>') return; /* back up over </foo> */ --s; while (s >= line) { if (*s == '<') { *s = 0; return; } --s; } } /* tagStrip */
void stripWhite(char *s) { const char *t = s; skipWhite(&t); if (t > s) strmove(s, t); trimWhite(s); } /* stripWhite */
//find repeated spaces and trim them down to only //one space in a row. void trimWhite(char* beginning) { char *to = beginning; char *from; bool lastIsSpace = false; while(*to != '\0') { if(isspace(*to)) { if(lastIsSpace) { from = to; char* begin = to + 1; while(isspace(*from)) from++; while(*to) *to++ = *from++; trimWhite(begin); return; } else lastIsSpace = true; if(*to == '\r') *to = '\n'; } else lastIsSpace = false; to++; } }
int nm2tsv(Options* inOptions) /* ** Read all input. ** Output tab seperated value data. ** ** We expect our data to be in a particular format. ** nm --format=bsd --size-sort --print-file-name --demangle */ { int retval = 0; char lineBuffer[4096]; /* yes, the are some very large symbols */ char* module = NULL; char* size = NULL; char* type = NULL; char* symbol = NULL; /* ** Read in the nm file. */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); /* ** Find the various pieces of information we'll be looking for. */ size = strchr(lineBuffer, ':'); if(NULL != size) { *size = '\0'; size++; module = strrchr(lineBuffer, '/'); if(NULL == module) { module = lineBuffer; } else { *module = '\0'; module++; } type = scanWhite(size); *type = '\0'; type++; symbol = type + 1; *symbol = '\0'; symbol++; /* ** Skip certain types. */ switch(*type) { case '-': continue; break; default: break; } /* ** Simply output the data with a little more interpretation. ** First is size. */ fprintf(inOptions->mOutput, "%s\t", size); /* ** Type, CODE or DATA */ switch(toupper(*type)) { case 'T': /* text (code) */ case 'W': /* weak symbol ??? */ fprintf(inOptions->mOutput, "CODE\t"); break; default: fprintf(inOptions->mOutput, "DATA\t"); break; } /* ** Scope, PUBLIC, STATIC, or UNDEF */ if(islower(*type)) { fprintf(inOptions->mOutput, "STATIC\t"); } else { switch(*type) { case '?': fprintf(inOptions->mOutput, "UNDEF\t"); break; default: fprintf(inOptions->mOutput, "PUBLIC\t"); break; } } /* ** Module name, segment. */ fprintf(inOptions->mOutput, "%s\t", module); fprintf(inOptions->mOutput, "%c\t", toupper(*type)); /* ** Origin */ fprintf(inOptions->mOutput, "UNDEF:%s:%c\t", module, toupper(*type)); /* ** Symbol is last. */ fprintf(inOptions->mOutput, "%s\n", symbol); } else { retval = __LINE__; ERROR_REPORT(retval, lineBuffer, "Malformed input line."); } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } return retval; }
int codesighs(Options* inOptions) /* ** Output a simplistic report based on our options. */ { int retval = 0; char lineBuffer[0x1000]; int scanRes = 0; unsigned long size; #define SEGCLASS_CHARS 15 char segClass[SEGCLASS_CHARS + 1]; #define SCOPE_CHARS 15 char scope[SCOPE_CHARS + 1]; #define MODULE_CHARS 255 char module[MODULE_CHARS + 1]; #define SEGMENT_CHARS 63 char segment[SEGMENT_CHARS + 1]; #define OBJECT_CHARS 255 char object[OBJECT_CHARS + 1]; char* symbol; SizeStats overall; ModuleStats* modules = NULL; unsigned moduleCount = 0; memset(&overall, 0, sizeof(overall)); /* ** Read the file line by line, regardless of number of fields. ** We assume tab separated value formatting, at least 7 lead values: ** size class scope module segment object symbol .... */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); #define STRINGIFY(s_) STRINGIFY2(s_) #define STRINGIFY2(s_) #s_ scanRes = sscanf(lineBuffer, "%x\t%" STRINGIFY(SEGCLASS_CHARS) "s\t%" STRINGIFY(SCOPE_CHARS) "s\t%" STRINGIFY(MODULE_CHARS) "s\t%" STRINGIFY(SEGMENT_CHARS) "s\t%" STRINGIFY(OBJECT_CHARS) "s\t", (unsigned*)&size, segClass, scope, module, segment, object); if(6 == scanRes) { SegmentClass segmentClass = CODE; symbol = strchr(lineBuffer, '\t') + 1; /* ** Qualify the segment class. */ if(0 == strcmp(segClass, "DATA")) { segmentClass = DATA; } else if(0 == strcmp(segClass, "CODE")) { segmentClass = CODE; } else { retval = __LINE__; ERROR_REPORT(retval, segClass, "Unable to determine segment class."); } if(0 == retval) { /* ** Match any options required before continuing. ** This is where you would want to add more restrictive totalling. */ /* ** Match size. */ if(size < inOptions->mMinSize) { continue; } if(size > inOptions->mMaxSize) { continue; } /* ** Match class. */ if(0 != inOptions->mMatchClassCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchClassCount; loop++) { if(NULL != strstr(segClass, inOptions->mMatchClasses[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchClassCount) { continue; } } /* ** Match scope. */ if(0 != inOptions->mMatchScopeCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchScopeCount; loop++) { if(NULL != strstr(scope, inOptions->mMatchScopes[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchScopeCount) { continue; } } /* ** Match modules. */ if(0 != inOptions->mMatchModuleCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchModuleCount; loop++) { if(NULL != strstr(module, inOptions->mMatchModules[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchModuleCount) { continue; } } /* ** Match sections. */ if(0 != inOptions->mMatchSectionCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchSectionCount; loop++) { if(NULL != strstr(segment, inOptions->mMatchSections[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchSectionCount) { continue; } } /* ** Match object. */ if(0 != inOptions->mMatchObjectCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchObjectCount; loop++) { if(NULL != strstr(object, inOptions->mMatchObjects[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchObjectCount) { continue; } } /* ** Match symbols. */ if(0 != inOptions->mMatchSymbolCount) { unsigned loop = 0; for(loop = 0; loop < inOptions->mMatchSymbolCount; loop++) { if(NULL != strstr(symbol, inOptions->mMatchSymbols[loop])) { break; } } /* ** If there was no match, we skip the line. */ if(loop == inOptions->mMatchSymbolCount) { continue; } } /* ** Update overall totals. */ if(CODE == segmentClass) { overall.mCode += size; } else if(DATA == segmentClass) { overall.mData += size; } /* ** See what else we should be tracking. */ if(0 == inOptions->mTotalOnly) { if(inOptions->mModules) { unsigned index = 0; /* ** Find the module to modify. */ for(index = 0; index < moduleCount; index++) { if(0 == strcmp(modules[index].mModule, module)) { break; } } /* ** If the index is the same as the count, we need to ** add a new module. */ if(index == moduleCount) { void* moved = NULL; moved = realloc(modules, sizeof(ModuleStats) * (moduleCount + 1)); if(NULL != moved) { modules = (ModuleStats*)moved; moduleCount++; memset(modules + index, 0, sizeof(ModuleStats)); modules[index].mModule = strdup(module); if(NULL == modules[index].mModule) { retval = __LINE__; ERROR_REPORT(retval, module, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate module memory."); } } if(0 == retval) { if(CODE == segmentClass) { modules[index].mSize.mCode += size; } else if(DATA == segmentClass) { modules[index].mSize.mData += size; } } } } } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Problem extracting values from file."); } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } /* ** If all went well, time to report. */ if(0 == retval) { if(inOptions->mTotalOnly) { fprintf(inOptions->mOutput, "%u\n", (unsigned)(overall.mCode + overall.mData)); } else { fprintf(inOptions->mOutput, "Overall Size\n"); fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(overall.mCode + overall.mData)); fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)overall.mCode); fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)overall.mData); } /* ** Check options to see what else we should output. */ if(inOptions->mModules && moduleCount) { unsigned loop = 0; /* ** Sort the modules by their size. */ qsort(modules, (size_t)moduleCount, sizeof(ModuleStats), moduleCompare); /* ** Output each one. ** Might as well clean up while we go too. */ for(loop = 0; loop < moduleCount; loop++) { fprintf(inOptions->mOutput, "\n"); fprintf(inOptions->mOutput, "%s\n", modules[loop].mModule); fprintf(inOptions->mOutput, "\tTotal:\t%10u\n", (unsigned)(modules[loop].mSize.mCode + modules[loop].mSize.mData)); fprintf(inOptions->mOutput, "\tCode:\t%10u\n", (unsigned)modules[loop].mSize.mCode); fprintf(inOptions->mOutput, "\tData:\t%10u\n", (unsigned)modules[loop].mSize.mData); CLEANUP(modules[loop].mModule); } /* ** Done with modules. */ CLEANUP(modules); moduleCount = 0; } } return retval; }
int processChar(char *p_filename, int p_toestand, int p_lastchar, int p_thischar, int p_nextchar) { int toestand = p_toestand; /* entering comment area */ if (p_thischar == '/' && p_nextchar == '*') { insideComment = 1; } if (!insideComment && p_thischar == '@') { insideAt = 1; toestand = AT; } /* if inside at area and not inside comment area */ if (insideAt && !insideComment) { switch(p_thischar) { default: /* token not ready yet */ *tokenPtr++ = p_thischar; break; case ' ': *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); if (strcmp(tokenPtr,"@import") == 0) { tokenPtr = tokenArea; toestand = IMPORT; } break; case '"': /* filename @import */ switch (toestand) { default: fprintf(stderr,"atQuote: Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case IMPORT: /* start of filename */ *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); tokenPtr = tokenArea; toestand = FILENAME; break; case FILENAME: /* end of filename */ *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); fprintf(stderr,"Found FILENAME=%s\n",tokenPtr); tokenPtr = tokenArea; toestand = ATDONE; break; } break; case ';': switch (toestand) { default: fprintf(stderr,"atSemiColon: Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case ATDONE: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); tokenPtr = tokenArea; break; } break; } } /* if not inside comment or at area */ if (!insideComment && !insideAt) { switch(p_thischar) { default: /* token not ready yet */ *tokenPtr++ = p_thischar; break; case ',': /* next selector or next value */ switch (toestand) { default: fprintf(stderr,"Comma Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case SELECTOR: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); add2SelectorList(tokenPtr); tokenPtr = tokenArea; break; case VALUE: *tokenPtr++ = p_thischar; break; } break; case '{': /* selector done, property starts here */ switch(toestand) { default: fprintf(stderr,"AccoladeOpen Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case SELECTOR: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); add2SelectorList(tokenPtr); tokenPtr = tokenArea; toestand = PROPERTY; break; } break; case ':': /* colon can occur in selector. if not then property done, value starts here */ switch(toestand) { default: fprintf(stderr,"Colon Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case SELECTOR: *tokenPtr++ = p_thischar; break; case PROPERTY: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); strcpy(currentPropertyName, tokenPtr); tokenPtr = tokenArea; toestand = VALUE; break; } break; case ';': /* values done */ switch(toestand) { default: fprintf(stderr,"SemiColon Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case VALUE: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); if (*tokenPtr) { int i; for (i = 0; i < nSelectors; i++) { addValue(addProperty(selectorList[i],currentPropertyName),tokenPtr); } } tokenPtr = tokenArea; toestand = PROPERTY; break; } break; case '}': /* selectors done */ switch(toestand) { default: fprintf(stderr,"AccoladeClose Unknown toestand %d near %c%c%c in file %s\n",toestand,p_lastchar,p_thischar,p_nextchar,p_filename); exit(1); case VALUE: /*fprintf(stderr,"%s: Syntax error found ... missing ;\n",p_filename);*/ { /* repair */ /* thischar should have been a semicolon but it is a closing accolade - pretend it's there */ processChar(p_filename, p_toestand, p_lastchar, ';', p_thischar); } /* done repair */ toestand = PROPERTY; /* fall through */ case PROPERTY: *tokenPtr = '\0'; tokenPtr = trimWhite(tokenArea); if (*tokenPtr) { int i; for (i = 0; i < nSelectors; i++) { addValue(addProperty(selectorList[i],currentPropertyName),tokenPtr); } } tokenPtr = tokenArea; resetSelectorList(); toestand = SELECTOR; break; } break; } } /* exiting comment area */ if (insideComment && p_lastchar == '*' && p_thischar == '/') { insideComment = 0; } /* exiting at area */ if (!insideComment && insideAt && toestand == ATDONE && p_lastchar == ';') { insideAt = 0; toestand = SELECTOR; } /* return nieuwe toestand */ return toestand; }
bool AutoBan::printTable( TcpSocket *s , HttpRequest *r ) { SafeBuf sb(512 * 512,"autobbuf"); //read in all of the possible cgi parms off the bat: //long user = g_pages.getUserType( s , r ); char *username = g_users.getUsername(r); //char *pwd = r->getString ("pwd"); char *coll = r->getString ("c"); long banIpsLen; char *banIps = r->getString ("banIps" , &banIpsLen , NULL); long allowIpsLen; char *allowIps = r->getString ("allowIps" , &allowIpsLen , NULL); long clearLen; char *clear = r->getString ("clear" , &clearLen , NULL); bool changed = false; long validCodesLen; char *validCodes = r->getString ("validCodes", &validCodesLen, NULL); long showAllIps = r->getLong("showAllIps", 0); long showLongView = r->getLong("longview", 0); // do it all from parm now //long banRegexLen; //char *banRegex = r->getString("banRegex", &banRegexLen, NULL); // char *ss = sb.getBuf(); // char *ssend = sb.getBufEnd(); g_pages.printAdminTop ( &sb, PAGE_AUTOBAN, username, coll , NULL , s->m_ip ); //sb.incrementLength(sss - ss); // MDW: moved to here long now = getTime(); long days; long hours; long minutes; long secs; long msecs; if(r->getLong("resetcodes", 0)) { setCodesFromConf(); } sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); getCalendarFromMs((now - m_codeResetTime) * 1000, &days, &hours, &minutes, &secs, &msecs); sb.safePrintf("<tr><td colspan=18 bgcolor=#%s>" "<center><b>Code Usage " "(<a href=\"/master/" "autoban?c=%s&resetcodes=1\">reset</a> " "%li days %li hours %li " "minutes %li sec ago)" "</b></center></td></tr>", DARK_BLUE, coll, days, hours, minutes, secs); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>Code</b></center></td>" "<td><center><b>IP</b></center></td>" "<td><center><b>Query Count</b></center></td>" "<td><center><b>Bytes Read</b></center></td>" "<td><center><b>Bytes Sent</b></center></td>" "<td><center><b>Outstanding Count</b></center></td>" "<td><center><b>Most Ever Outstanding</b></center></td>" "<td><center><b>Max Outstanding</b></center></td>" "</tr>", LIGHT_BLUE); for(long i = 0; i < m_ht.getNumSlots(); i++) { if ( m_ht.getKey ( i ) == 0 ) continue; CodeVal *cv = m_ht.getValuePointerFromSlot ( i ); if ( ! cv ) continue; sb.safePrintf("<tr>"); sb.safePrintf("<td>"); sb.copyToken(cv->m_code);//m_codeVals[i].m_code); sb.safePrintf("</td>"); sb.safePrintf("<td><center>%s</center> </td>", iptoa(cv->m_ip)); sb.safePrintf("<td><center>%lli</center></td>", cv->m_count); sb.safePrintf("<td><center>%lli</center></td>", cv->m_bytesRead); sb.safePrintf("<td><center>%lli</center></td>", cv->m_bytesSent); sb.safePrintf("<td><center>%li</center></td>", cv->m_outstanding); sb.safePrintf("<td><center>%li</center></td>", cv->m_maxEver); if ( cv->m_maxOutstanding != 50 ) sb.safePrintf("<td><center><b>%li</b></center></td>", cv->m_maxOutstanding); else sb.safePrintf("<td><center>%li</center></td>", cv->m_maxOutstanding); sb.safePrintf("</tr>"); } sb.safePrintf ("</table><br><br>\n" ); if(clear && clearLen < 64) { long ip = atoip(clear, clearLen); if(ip) { removeIp(ip); char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, clear, clearLen); ipbuf[clearLen] = '\0'; beginning = findToken(g_conf.m_banIps, ipbuf, clearLen); if(beginning) { char *to = beginning; char *from = beginning + clearLen; while(*to) *to++ = *from++; } beginning = findToken(g_conf.m_allowIps, ipbuf, clearLen); if(beginning) { char *to = beginning; char *from = beginning + clearLen; while(*to) *to++ = *from++; } changed = true; } } long allowLen; char *allow = r->getString ( "allow" , &allowLen , NULL ); if(allow && allowLen < 64) { long ip = atoip(allow, allowLen); if(ip) { char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, allow, allowLen); ipbuf[allowLen] = '\0'; beginning = findToken(g_conf.m_allowIps, ipbuf, allowLen); if(!beginning) { //its not present, so add it. char *p = g_conf.m_allowIps; while(*p) p++; if(p - g_conf.m_allowIps + allowLen + 2 < AUTOBAN_TEXT_SIZE) { *p++ = '\n'; memcpy(p, ipbuf,allowLen); *(p + allowLen) = '\0'; } else { sb.safePrintf("<font color=red>" "Not enough stack space " "to fit allowIps. " "Increase " "AUTOBAN_TEXT_SIZE in " "Conf.h. " "Had %i need %li." "</font>", AUTOBAN_TEXT_SIZE, p - g_conf.m_allowIps + allowLen + 2); goto dontRemove1; } } beginning = findToken(g_conf.m_banIps, ipbuf, allowLen); if(beginning) { //remove it from banned if present. char *to = beginning; char *from = beginning + allowLen; while(*to) *to++ = *from++; } changed = true; } } dontRemove1: long denyLen; char *deny = r->getString ( "deny" , &denyLen , NULL ); if(deny && denyLen < 64) { long ip = atoip(deny, denyLen); if(ip) { char *beginning; char ipbuf[64];//gotta NULL terminate for strstr memcpy(ipbuf, deny, denyLen); ipbuf[denyLen] = '\0'; beginning = findToken(g_conf.m_banIps, ipbuf, denyLen); if(!beginning) { //its not present, so add it. char *p =g_conf.m_banIps; while(*p) p++; if(p - g_conf.m_banIps + denyLen + 2 < AUTOBAN_TEXT_SIZE) { *p++ = '\n'; memcpy(p, ipbuf,denyLen); *(p + denyLen) = '\0'; } else { sb.safePrintf("<font color=red>Not " "enough stack space " "to fit bannedIPs. " "Increase " "AUTOBAN_TEXT_SIZE in " "Conf.h. " "Had %i need %li." "</font>", AUTOBAN_TEXT_SIZE, p - g_conf.m_banIps + denyLen + 2); goto dontRemove2; } } beginning = findToken(g_conf.m_allowIps, ipbuf, denyLen); if(beginning) { //remove it from allowed list if present. char *to = beginning; char *from = beginning + denyLen; while(*to) *to++ = *from++; } changed = true; } } dontRemove2: if(!g_conf.m_doAutoBan) { sb.safePrintf("<center><font color=red><b>Autoban is disabled, " "turn it on in Master Controls.</b></font></center><br>"); } if(validCodes) { if(validCodesLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit codes. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, validCodesLen); validCodes = NULL; validCodesLen = 0; } else { memcpy(g_conf.m_validCodes, validCodes, validCodesLen); g_conf.m_validCodes[validCodesLen] = '\0'; trimWhite(g_conf.m_validCodes); setCodesFromConf(); } } //first remove all of the ips in the conf, then add the passed in // ones to the conf parm; if (banIps) { //ack, the browser puts in crlf when this comes back, so //we will have a longer string here than the one we sent //out. trim back all extrainious whitespace before we do //bounds checking. trimWhite(banIps); banIpsLen = gbstrlen(banIps); if(banIpsLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit bannedIps. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, banIpsLen); banIpsLen = AUTOBAN_TEXT_SIZE - 1; } for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; //check the 'set from conf' bit, and clear those. if(m_detectVals[i].m_flags & FROMCONF) { removeIp(m_detectKeys[i]); } } memcpy(g_conf.m_banIps, banIps, banIpsLen); g_conf.m_banIps[banIpsLen] = '\0'; changed = true; } if (allowIps) { trimWhite(allowIps); allowIpsLen = gbstrlen(allowIps); if(allowIpsLen >= AUTOBAN_TEXT_SIZE) { sb.safePrintf("<font color=red>Not enough stack space " "to fit allowIps. " "Increase AUTOBAN_TEXT_SIZE in Conf.h. " "Had %i need %li.</font>", AUTOBAN_TEXT_SIZE, allowIpsLen); allowIpsLen = AUTOBAN_TEXT_SIZE - 1; } for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; //check the 'set from conf' bit, and clear those. if(m_detectVals[i].m_flags & FROMCONF) { removeIp(m_detectKeys[i]); } } memcpy(g_conf.m_allowIps, allowIps, allowIpsLen); g_conf.m_allowIps[allowIpsLen] = '\0'; changed = true; } if(changed) { trimWhite(g_conf.m_allowIps); trimWhite(g_conf.m_banIps); setFromConf(); } sb.safePrintf("\n<table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=2 bgcolor=#%s>" "<center><b>Add IPs</b></center></td></tr>", DARK_BLUE); // ss = sb.getBuf(); // ssend = sb.getBufEnd(); g_parms.printParms (&sb, s, r); // sb.incrementLength(sss - ss); sb.safePrintf ("<tr><td>" "<center>" "<input type=submit value=\"Update\" " "method=\"POST\" border=0>" "</center></td></tr>"); sb.safePrintf ("</table><br><br>\n" ); if(!showLongView) { sb.safePrintf("<b><a href=\"autoban" "?c=%s" "&showAllIps=%li" "&longview=1\">Show watched ips table...</a></b>", coll, showAllIps); return g_httpServer.sendDynamicPage ( s , sb.getBufStart() , sb.length() , -1 , false); } ///////////////////////////////////////////////////////////////////// sb.safePrintf("\n<table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=3 bgcolor=#%s>" "<center><b>Watched Ips</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>IP</b></center></td>" "<td><center><b>Description</b></center></td>" // "<td><center><b>Time Added</b></center></td>" "<td><center><b>Allow/Deny/Clear</b></center></td>" "</tr>", LIGHT_BLUE); long *sortedIndices = (long*)mmalloc(m_tableSize * sizeof(long), "AutoBanH"); if(!sortedIndices) { return g_httpServer.sendErrorReply(s,500,mstrerror(ENOMEM)); } long numEntries = 0; for(long i = 0; i < m_tableSize; i++) { if(m_detectKeys[i] == 0) continue; sortedIndices[numEntries++] = i; } SorterTable = m_detectKeys; gbsort(sortedIndices, numEntries, sizeof(long), ip_cmp); //lets put each class of watched ip in its own safebuf then cat //them together at the end. SafeBuf allowed; SafeBuf banned; SafeBuf feedLeachers; SafeBuf cowBots; SafeBuf *e; for(long j = 0; j < numEntries; j++) { long i = sortedIndices[j]; if(m_detectKeys[i] == 0) continue; //if(!(m_detectVals[i].m_flags & FROMCONF)) continue; bool allow = m_detectVals[i].m_flags & ALLOW && m_detectVals[i].m_flags & FROMCONF; bool deny = m_detectVals[i].m_flags & DENY && m_detectVals[i].m_flags & FROMCONF; bool explicitban = deny && m_detectVals[i].m_flags & FROMCONF; unsigned short dayCount = m_detectVals[i].m_dayCount; unsigned char minuteCount = m_detectVals[i].m_minuteCount; bool day = dayCount >= g_conf.m_numFreeQueriesPerDay; bool minute = minuteCount >= g_conf.m_numFreeQueriesPerMinute; char *description; char *color; if(allow) { color = GREEN; description = "Allowed"; e = &allowed; } else if(explicitban) { color = RED; description = "Banned"; e = &banned; } else if(minute) { color = RED; description = "Cow Bot"; e = &cowBots; } else if(day) { color = RED; description = "Feed Leacher"; e = &feedLeachers; } else { //this can happen when someone was banned due to //exceeding the quota, then the quota was lowered. m_detectVals[i].m_flags &= ~DENY; //log("autoban: ohshit-banning %s",iptoa(s->m_ip)); continue; } e->safePrintf("<tr>"); e->safePrintf("<td bgcolor=#%s><center>%s</center></td><td>" "<center>%s</center></td>" // "<td><center>" // "%li days %li hrs %li min ago" // "</center></td>" "<td><center><a href=\"/master/" "autoban?c=%s&allow=%s&showAllIps=%li\">" "allow/</a>" "<a href=\"/master/" "autoban?c=%s&deny=%s&showAllIps=%li\">" "deny/</a>" "<a href=\"/master/" "autoban?c=%s&clear=%s&showAllIps=%li\">" "clear</a></center>" "</td>",color, iptoa(m_detectKeys[i]), description, // days,hours,minutes, coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps); e->safePrintf("</tr>"); } sb.cat(allowed); sb.cat(banned); sb.cat(feedLeachers); sb.cat(cowBots); sb.safePrintf ("</table><br><br>\n" ); // MDW moved from here sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=5 bgcolor=#%s>" "<center><b>Control Panel</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr>" "<td bgcolor=#%s><center><b>Show Ips by Number of Queries" "</b></center></td>", LIGHT_BLUE); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=0\">" "0 Queries</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=1\">" "1 Query</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=10\">" "10 Queries</a></b>" "</font></center></td>", coll); sb.safePrintf("<td><center><font color=red><b><a href=\"/master/" "autoban?c=%s&showAllIps=100\">" "100 Queries</a></b>" "</font></center></td></tr>", coll); sb.safePrintf ("</table><br><br>\n"); if(!showAllIps) { char* ss = (char*) sb.getBufStart(); long sslen = sb.length(); mfree(sortedIndices, m_tableSize * sizeof(long),"AutoBanH"); return g_httpServer.sendDynamicPage ( s , ss , sslen , -1 , false); } sb.safePrintf("\n<br><br><table width=100%% bgcolor=#%s " "cellpadding=4 border=1>\n", BABY_BLUE); sb.safePrintf("<tr><td colspan=6 bgcolor=#%s>" "<center><b>Queries Today</b></center></td></tr>", DARK_BLUE); sb.safePrintf("<tr bgcolor=#%s>" "<td><center><b>IP</b></center></td>" "<td><center><b>Minute count</b></center></td>" "<td><center><b>Day count</b></center></td>" "<td><center><b>Time Until Reset</b></center></td>" "<td><center><b>Times Banned</b></center></td>" "<td><center><b>Allow/Deny</b></center></td>" "</tr>", LIGHT_BLUE); char minBuf[128]; char dayBuf[128]; unsigned long lastIpGroup = 0; for(long j = 0; j < numEntries; j++) { long i = sortedIndices[j]; long dayCount = m_detectVals[i].m_dayCount; unsigned char minuteCount = m_detectVals[i].m_minuteCount; if(!(m_detectVals[i].m_flags & FROMCONF)) { if(m_detectVals[i].m_minuteExpires < now) minuteCount = 0; if(!(m_detectVals[i].m_flags & DENY) && m_detectVals[i].m_dayExpires < now) dayCount = 0; } //a hack: if( dayCount < showAllIps) continue; char *color = YELLOW; if(m_detectVals[i].m_flags & ALLOW) { color = GREEN; snprintf(minBuf, 128, "--"); snprintf(dayBuf, 128, "%li", dayCount); } else if(m_detectVals[i].m_flags & DENY) { color = RED; snprintf(minBuf, 128, "--"); snprintf(dayBuf, 128, "%li", dayCount); } else { snprintf(minBuf, 128, "%li", (long)minuteCount); snprintf(dayBuf, 128, "%li", (long)dayCount); } unsigned long thisIpGroup = (unsigned long)m_detectKeys[i] & 0x00ffffff; sb.safePrintf("<tr><center>"); if(m_detectVals[i].m_flags & FROMCONF) { sb.safePrintf("<td bgcolor=#%s><center>%s%s%s</center></td>" "<td><center>%s</center> </td>" "<td><center>%s</center></td>" "<td><center><font color=red>" "<b>NEVER</b>" "</font></center></td>" "<td><center>--</center></td>", color, (thisIpGroup == lastIpGroup)?"<b>":"", iptoa(m_detectKeys[i]), (thisIpGroup == lastIpGroup)?"</b>":"", minBuf, dayBuf); } else { //they haven't done a query since being unbanned, //unban them now so we don't get negative resets displayed. /* no, don't unban the bots!!! MDW yippy project if(m_detectVals[i].m_dayExpires < now) { m_detectVals[i].m_flags &= ~DENY; //log("autoban: dayexpire-unbanning %s", // iptoa(ip)); m_detectVals[i].m_dayExpires = now + ONE_DAY; m_detectVals[i].m_minuteExpires = now + 60; m_detectVals[i].m_dayCount = 0; m_detectVals[i].m_minuteCount = 0; sb.safePrintf("</center></tr>"); continue; } */ getCalendarFromMs((m_detectVals[i].m_dayExpires - now)* 1000, &days, &hours, &minutes, &secs, &msecs); sb.safePrintf("<td bgcolor=#%s><center>%s%s%s</center></td>" "<td><center>%s</center> </td>" "<td><center>%s</center></td>" "<td><center><font color=red>" "<b>%li days %li hrs %li min %li sec</b>" "</font></center></td>" "<td><center>%i</center></td>", color, (thisIpGroup == lastIpGroup)?"<b>":"", iptoa(m_detectKeys[i]), (thisIpGroup == lastIpGroup)?"</b>":"", minBuf, dayBuf, days, hours, minutes, secs, m_detectVals[i].m_timesBanned); } sb.safePrintf("<td><center>" "<a href=\"/master/" "autoban?c=%s&allow=%s&showAllIps=%li\">" "allow/</a>" "<a href=\"/master/" "autoban?c=%s&deny=%s&showAllIps=%li\">" "deny</a></center>" "</td>", coll, iptoa(m_detectKeys[i]), showAllIps, coll, iptoa(m_detectKeys[i]), showAllIps); sb.safePrintf("</center></tr>"); lastIpGroup = thisIpGroup; } sb.safePrintf ("</table><br><br>\n" ); char* ss = (char*) sb.getBufStart(); long sslen = sb.length(); mfree(sortedIndices, m_tableSize * sizeof(long),"AutoBanH"); return g_httpServer.sendDynamicPage ( s , ss , sslen , -1 , false); }
bool sendPageThesaurus( TcpSocket *s, HttpRequest *r ) { SafeBuf p; char getBuf[64]; // holds extra values for GET method char formBuf[256]; // holds extra values for forms snprintf(getBuf, 64, "c=%s", r->getString("c", 0, "")); snprintf(formBuf, 256, "<input type=hidden name=\"c\" value=\"%s\">", //"<input type=hidden name=\"pwd\" value=\"%s\">", r->getString("c", 0, "")); g_pages.printAdminTop( &p, s, r); if (r->getLong("cancel", 0) != 0) { g_thesaurus.cancelRebuild(); p.safePrintf("<br><br>\n"); p.safePrintf( "<center><b><font color=#ff0000>" "rebuild canceled" "</font></b></center>"); } if (r->getLong("rebuild", 0) != 0) { bool full = r->getLong("full", 0); p.safePrintf("<br><br>\n"); if (g_thesaurus.rebuild(0, full)) { p.safePrintf( "<center><b><font color=#ff0000>" "error starting rebuild, check log for details" "</font></b></center>"); } else { p.safePrintf( "<center><b><font color=#ff0000>" "rebuild started" "</font></b></center>"); } } if (r->getLong("rebuildaff", 0) != 0) { bool full = r->getLong("full", 0); p.safePrintf("<br><br>\n"); if (g_thesaurus.rebuildAffinity(0, full)) { p.safePrintf( "<center><b><font color=#ff0000>" "error starting rebuild, check log for details" "</font></b></center>"); } else { p.safePrintf( "<center><b><font color=#ff0000>" "rebuild started" "</font></b></center>"); } } if (r->getLong("distribute", 0) != 0) { char cmd[1024]; p.safePrintf("<br><br>\n"); if (g_thesaurus.m_affinityState) { p.safePrintf( "<center><b><font color=#ff0000>" "cannot distribute during rebuild" "</font></b></center>"); } else { for ( long i = 0; i < g_hostdb.getNumHosts() ; i++ ) { Host *h = g_hostdb.getHost(i); snprintf(cmd, 512, "rcp -r " "./dict/thesaurus.* " "%s:%s/dict/ &", iptoa(h->m_ip), h->m_dir); log(LOG_INFO, "admin: %s", cmd); system( cmd ); } p.safePrintf( "<center><b><font color=#ff0000>" "data distributed" "</font></b></center>"); } } if (r->getLong("reload", 0) != 0) { p.safePrintf("<br><br>\n"); if (r->getLong("cast", 0) != 0) { p.safePrintf( "<center><b><font color=#ff0000>" "reload command broadcast" "</font></b></center>"); } else if (g_thesaurus.init()) { p.safePrintf( "<center><b><font color=#ff0000>" "thesaurus data reloaded" "</font></b></center>"); } else { p.safePrintf( "<center><b><font color=#ff0000>" "error reloading thesaurus data" "</font></b></center>"); } } long manualAddLen = 0; char *manualAdd = NULL; SafeBuf manualAddBuf; if ((manualAdd = r->getString("manualadd", &manualAddLen))) { trimWhite(manualAdd); manualAddLen = gbstrlen(manualAdd); File manualFile; manualFile.set(g_hostdb.m_dir, "dict/thesaurus-manual.txt"); if (manualFile.open(O_WRONLY | O_CREAT | O_TRUNC) && (manualFile.write(manualAdd, manualAddLen, 0) == manualAddLen)) { char newl = '\n'; // for write() if (manualAdd[manualAddLen-1] != '\n') manualFile.write(&newl, 1, manualAddLen); p.safePrintf( "<center><b><font color=#ff0000>" "updated manual add file sucessfully" "</font></b></center>"); } else { p.safePrintf( "<center><b><font color=#ff0000>" "error writing manual add file" "</font></b></center>"); } } else { char ff[PATH_MAX]; snprintf(ff, PATH_MAX, "%sdict/thesaurus-manual.txt", g_hostdb.m_dir); if (manualAddBuf.fillFromFile(ff)) { if (*(manualAddBuf.getBuf()-1) != '\n') manualAddBuf.pushChar('\n'); manualAdd = manualAddBuf.getBufStart(); manualAddLen = manualAddBuf.length(); } } long affinityAddLen = 0; char *affinityAdd = NULL; SafeBuf affinityAddBuf; if ((affinityAdd = r->getString("affinityadd", &affinityAddLen))) { trimWhite(affinityAdd); affinityAddLen = gbstrlen(affinityAdd); File affinityFile; affinityFile.set(g_hostdb.m_dir, "dict/thesaurus-affinity.txt"); if (affinityFile.open(O_WRONLY | O_CREAT | O_TRUNC) && (affinityFile.write(affinityAdd, affinityAddLen, 0) == affinityAddLen)) { char newl = '\n'; // for write() if (affinityAdd[affinityAddLen-1] != '\n') affinityFile.write(&newl, 1, affinityAddLen); p.safePrintf( "<center><b><font color=#ff0000>" "updated affinity add file sucessfully" "</font></b></center>"); } else { p.safePrintf( "<center><b><font color=#ff0000>" "error writing affinity add file" "</font></b></center>"); } } else { char ff[PATH_MAX]; snprintf(ff, PATH_MAX, "%sdict/thesaurus-affinity.txt", g_hostdb.m_dir); if (affinityAddBuf.fillFromFile(ff)) { if (*(affinityAddBuf.getBuf()-1) != '\n') affinityAddBuf.pushChar('\n'); affinityAdd = affinityAddBuf.getBufStart(); affinityAddLen = affinityAddBuf.length(); } } char *syn = r->getString("synonym"); long len = 0; if (syn) len = gbstrlen(syn); if (len) { SynonymInfo info; bool r = g_thesaurus.getAllInfo(syn, &info, len, SYNBIT_ALL); p.safePrintf("<br><br>\n"); p.safePrintf ( "<table cellpadding=4 width=100%% bgcolor=#%s border=1>" "<tr>" "<td colspan=2 bgcolor=#%s>" "<center><b>Synonym List (%ld)</b></center>" "</td>" "</tr>\n", LIGHT_BLUE, DARK_BLUE, info.m_numSyns); if (r) { p.safePrintf("<tr>" "<td align=right><tt>%s</tt></td>" "<td align=left>" "<tt>1.000/%08lX (1.000/%08lX)</tt>" "</td>" "</tr>\n", syn, MAX_AFFINITY, MAX_AFFINITY); for (long i = 0; i < info.m_numSyns; i++) { // get the reverse affinity as well long aff = g_thesaurus.getAffinity( info.m_syn[i], syn, info.m_len[i], len); p.safePrintf( "<tr>" "<td width=40%% align=right>" "<tt>"); p.safeMemcpy(info.m_syn[i], info.m_len[i]); p.safePrintf("</tt>" "</td>" "<td width=60%% align=left>" "<tt>"); if (info.m_affinity[i] >= 0) { p.safePrintf("%0.3f/%08lX ", (float)info.m_affinity[i] / MAX_AFFINITY, info.m_affinity[i]); } else { p.safePrintf("u "); } if (aff >= 0) { p.safePrintf("(%0.3f/%08lX) ", (float)aff / MAX_AFFINITY, aff); } else { p.safePrintf("(u) "); } p.safePrintf("(%ld) (%ld) (%ld) (%ld) " "(%lld) (%lld)", (long)info.m_type[i], (long)info.m_sort[i], info.m_firstId[i], info.m_lastId[i], info.m_leftSynHash[i], info.m_rightSynHash[i]); for (int j = info.m_firstId[i]; j <= info.m_lastId[i]; j++) { p.safePrintf(" (%lld)", info.m_termId[j]); } p.safePrintf( "</tt>" "</td>" "</tr>\n"); } p.safePrintf("</table>"); } else { p.safePrintf("<tr>" "<td align=center><font color=#FF0000>" "synonym not found: %s" "</font></td>" "</tr>\n", syn); } } p.safePrintf ( "<br><br>\n" ); p.safePrintf ( "<table cellpadding=4 width=100%% bgcolor=#%s border=1>" "<tr>" "<td colspan=2 bgcolor=#%s>" "<center><b>Thesaurus Controls" "</b></center></td>" "</tr>\n", LIGHT_BLUE, DARK_BLUE); p.safePrintf ( "<tr>" "<td width=37%%><b>rebuild all data</b><br>" "<font size=1>" "rebuilds synonyms and then begins the rebuild process for " "affinity data; this should only be run on one host, as the " "data is copied when the process is finished; full rebuild " "does not use existing affinity data" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b><a href=\"/master/thesaurus?rebuild=1&%s\">" "rebuild all data</a> <a href=\"/master/thesaurus?" "rebuild=1&full=1&%s\">(full)</a></b></center>" "</td>" "</tr>\n", getBuf, getBuf); p.safePrintf ( "<tr>" "<td width=37%%><b>distribute data</b><br>" "<font size=1>" "distributes all thesaurus data to all hosts, this is " "normally done automatically but if there was a problem " "with the copy, this lets you do it manually" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b><a href=\"/master/thesaurus?distribute=1&%s\">" "distribute data</a></b></center>" "</td>" "</tr>\n", getBuf); p.safePrintf ( "<tr>" "<td width=37%%><b>reload data</b><br>" "<font size=1>" "reloads the synonyms and affinity table on this host only" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b>" "<a href=\"/master/thesaurus?reload=1&cast=0&%s\">" "reload data</a></b></center>" "</td>" "</tr>\n", getBuf); p.safePrintf ( "<tr>" "<td width=37%%><b>reload data (all hosts)</b><br>" "<font size=1>" "reloads the synonyms and affinity table on all hosts" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b>" "<a href=\"/master/thesaurus?reload=1&cast=1&%s\">" "reload data (all hosts)</a></b></center>" "</td>" "</tr>\n", getBuf); p.safePrintf ( "<tr>" "<td width=37%%><b>list synonyms</b><br>" "<font size=1>" "enter a word here to list all synonym entries and their " "affinities" "</font>" "</td>" "<td width=12%%>" "<form action=\"/master/thesaurus>\">" "<input type=text name=synonym size=20>" "<input type=submit value=Submit>" "%s" "</form></td>" "</tr>\n", formBuf); p.safePrintf ( "<tr>" "<td colspan=2 bgcolor=#%s>" "<center><b>Affinity Controls" "</b></center></td>" "</tr>\n", DARK_BLUE); p.safePrintf ( "<tr>" "<td width=37%%><b>cancel running rebuild</b><br>" "<font size=1>" "cancels the rebuild and throws all intermediate data away" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b><a href=\"/master/thesaurus?cancel=1&%s\">" "cancel running rebuild</a></b></center>" "</td>" "</tr>\n", getBuf); p.safePrintf ( "<tr>" "<td width=37%%><b>rebuild affinity only</b><br>" "<font size=1>" "begins the rebuild process for affinity data, has no " "effect if a rebuild is already in progress; full rebuild " "does not reuse existing affinity data" "</font>" "</td>" "<td width=12%% bgcolor=#0000ff>" "<center><b><a href=\"/master/thesaurus?rebuildaff=1&%s\">" "rebuild affinity</a> <a href=\"/master/thesaurus?" "rebuildaff=1&full=1&%s\">(full)</a></b></center>" "</td>" "</tr>\n", getBuf, getBuf); p.safePrintf ( "<tr>" "<td colspan=2 bgcolor=#%s>" "<center><b>Manual File Controls" "</b></td>" "</tr>\n", DARK_BLUE); p.safePrintf ( "<tr>" "<td align=center colspan=2>"); p.safePrintf( "<b>manually added pairs</b><br>\n" "<font size=1>place word pairs here that should be linked " "as synonyms, one pair per line, seperated by a pipe '|' " "character, optionally followed by another pipe and a type " "designation; any badly formatted lines will be silently " "ignored</font><br>\n" "<form action=\"/master/thesaurus\" method=post>" "<textarea name=\"manualadd\" rows=20 cols=80>"); if (manualAdd && manualAddLen) { p.htmlEncode(manualAdd, manualAddLen, true); } p.safePrintf ( "</textarea><br>" "<input type=submit value=Submit>" "<input type=reset value=Reset>" "%s" "</form></td>" "</tr>\n", formBuf); p.safePrintf ( "<tr>" "<td align=center colspan=2>" "<b>affinity value overrides</b><br>\n" "<font size=1>place word/phrase pairs here that should have " "there affinity values overridden, format is " "\"word1|word2|value\", where value is a floating point, " "integer (either decimal or hex), or the word \"max\"; " "any badly formatted lines will be silently ignored; note " "that these pairs will only work if the thesaurus otherwise " "has an entry for them, so add them to the manual add file " "above if need be</font><br>\n" "<form action=\"/master/thesaurus\" method=post>" "<textarea name=\"affinityadd\" rows=20 cols=80>"); if (affinityAdd && affinityAddLen) { p.htmlEncode(affinityAdd, affinityAddLen, true); } p.safePrintf ( "</textarea><br>" "<input type=submit value=Submit>" "<input type=reset value=Reset>" "%s" "</form></td>" "</tr>\n", formBuf); p.safePrintf ( "</table>\n" ); p.safePrintf ( "<br><br>\n" ); p.safePrintf ( "<table cellpadding=4 width=100%% bgcolor=#%s border=1>" "<tr>" "<td colspan=2 bgcolor=#%s>" "<center><b>Affinity Builder Status" "</b></td>" "</tr>\n", LIGHT_BLUE, DARK_BLUE); long long a, b, c, d, e, f, g, h, i, j, k; StateAffinity *aff = g_thesaurus.m_affinityState; if (!aff) { p.safePrintf ( "<tr><td colspan=2>" "<center><b>Not running</b></center>" "</td></tr>\n"); a = b = c = d = e = f = g = h = i = j = k = 0; } else { a = aff->m_oldTable->getNumSlotsUsed(); b = aff->m_oldTable->getNumSlotsUsed() - aff->m_n; c = aff->m_n; d = (gettimeofdayInMilliseconds() - aff->m_time) / 1000; if (!d || !(c / d)) { e = 0; } else { e = b / (c / d); } f = aff->m_sent; g = aff->m_recv; h = aff->m_errors; i = aff->m_old; j = aff->m_cache; k = aff->m_hitsTable.getNumSlotsUsed(); } p.safePrintf ( "<tr><td><b># of total pairs</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of pairs remaining</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of pairs processed</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b>elapsed time in seconds</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b>estimated remaining time in seconds</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of requests sent</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of requests received</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of request errors</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of old values reused</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b># of cache hits</b></td>" "<td>%lli</td></tr>\n" "<tr><td><b>cache size</b></td>" "<td>%lli</td></tr>\n", a, b, c, d, e, f, g, h, i, j, k); p.safePrintf ( "</table>\n" ); return g_httpServer.sendDynamicPage ( s, p.getBufStart(), p.length() ); }
int difftool(Options* inOptions) /* ** Read a diff file and spit out relevant information. */ { int retval = 0; char lineBuffer[0x500]; SizeStats overall; ModuleStats* modules = NULL; unsigned moduleCount = 0; unsigned moduleLoop = 0; ModuleStats* theModule = NULL; unsigned segmentLoop = 0; SegmentStats* theSegment = NULL; unsigned objectLoop = 0; ObjectStats* theObject = NULL; unsigned symbolLoop = 0; SymbolStats* theSymbol = NULL; unsigned allSymbolCount = 0; memset(&overall, 0, sizeof(overall)); /* ** Read the entire diff file. ** We're only interested in lines beginning with < or > */ while(0 == retval && NULL != fgets(lineBuffer, sizeof(lineBuffer), inOptions->mInput)) { trimWhite(lineBuffer); if(('<' == lineBuffer[0] || '>' == lineBuffer[0]) && ' ' == lineBuffer[1]) { int additive = 0; char* theLine = &lineBuffer[2]; int scanRes = 0; int size; #define SEGCLASS_CHARS 15 char segClass[SEGCLASS_CHARS + 1]; #define SCOPE_CHARS 15 char scope[SCOPE_CHARS + 1]; #define MODULE_CHARS 255 char module[MODULE_CHARS + 1]; #define SEGMENT_CHARS 63 char segment[SEGMENT_CHARS + 1]; #define OBJECT_CHARS 255 char object[OBJECT_CHARS + 1]; char* symbol = NULL; /* ** Figure out if the line adds or subtracts from something. */ if('>' == lineBuffer[0]) { additive = __LINE__; } /* ** Scan the line for information. */ #define STRINGIFY(s_) STRINGIFY2(s_) #define STRINGIFY2(s_) #s_ scanRes = sscanf(theLine, "%x\t%" STRINGIFY(SEGCLASS_CHARS) "s\t%" STRINGIFY(SCOPE_CHARS) "s\t%" STRINGIFY(MODULE_CHARS) "s\t%" STRINGIFY(SEGMENT_CHARS) "s\t%" STRINGIFY(OBJECT_CHARS) "s\t", (unsigned*)&size, segClass, scope, module, segment, object); if(6 == scanRes) { SegmentClass segmentClass = DATA; symbol = strrchr(theLine, '\t') + 1; if(0 == strcmp(segClass, "CODE")) { segmentClass = CODE; } else if(0 == strcmp(segClass, "DATA")) { segmentClass = DATA; } else { retval = __LINE__; ERROR_REPORT(retval, segClass, "Unable to determine segment class."); } if(0 == retval) { unsigned moduleIndex = 0; /* ** Find, in succession, the following things: ** the module ** the segment ** the object ** the symbol ** Failure to find any one of these means to create it. */ for(moduleIndex = 0; moduleIndex < moduleCount; moduleIndex++) { if(0 == strcmp(modules[moduleIndex].mModule, module)) { break; } } if(moduleIndex == moduleCount) { void* moved = NULL; moved = realloc(modules, sizeof(ModuleStats) * (1 + moduleCount)); if(NULL != moved) { modules = (ModuleStats*)moved; moduleCount++; memset(modules + moduleIndex, 0, sizeof(ModuleStats)); modules[moduleIndex].mModule = strdup(module); if(NULL == modules[moduleIndex].mModule) { retval = __LINE__; ERROR_REPORT(retval, module, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase module array."); } } if(0 == retval) { unsigned segmentIndex = 0; theModule = (modules + moduleIndex); for(segmentIndex = 0; segmentIndex < theModule->mSegmentCount; segmentIndex++) { if(0 == strcmp(segment, theModule->mSegments[segmentIndex].mSegment)) { break; } } if(segmentIndex == theModule->mSegmentCount) { void* moved = NULL; moved = realloc(theModule->mSegments, sizeof(SegmentStats) * (theModule->mSegmentCount + 1)); if(NULL != moved) { theModule->mSegments = (SegmentStats*)moved; theModule->mSegmentCount++; memset(theModule->mSegments + segmentIndex, 0, sizeof(SegmentStats)); theModule->mSegments[segmentIndex].mClass = segmentClass; theModule->mSegments[segmentIndex].mSegment = strdup(segment); if(NULL == theModule->mSegments[segmentIndex].mSegment) { retval = __LINE__; ERROR_REPORT(retval, segment, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase segment array."); } } if(0 == retval) { unsigned objectIndex = 0; theSegment = (theModule->mSegments + segmentIndex); for(objectIndex = 0; objectIndex < theSegment->mObjectCount; objectIndex++) { if(0 == strcmp(object, theSegment->mObjects[objectIndex].mObject)) { break; } } if(objectIndex == theSegment->mObjectCount) { void* moved = NULL; moved = realloc(theSegment->mObjects, sizeof(ObjectStats) * (1 + theSegment->mObjectCount)); if(NULL != moved) { theSegment->mObjects = (ObjectStats*)moved; theSegment->mObjectCount++; memset(theSegment->mObjects + objectIndex, 0, sizeof(ObjectStats)); theSegment->mObjects[objectIndex].mObject = strdup(object); if(NULL == theSegment->mObjects[objectIndex].mObject) { retval = __LINE__; ERROR_REPORT(retval, object, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase object array."); } } if(0 == retval) { unsigned symbolIndex = 0; theObject = (theSegment->mObjects + objectIndex); for(symbolIndex = 0; symbolIndex < theObject->mSymbolCount; symbolIndex++) { if(0 == strcmp(symbol, theObject->mSymbols[symbolIndex].mSymbol)) { break; } } if(symbolIndex == theObject->mSymbolCount) { void* moved = NULL; moved = realloc(theObject->mSymbols, sizeof(SymbolStats) * (1 + theObject->mSymbolCount)); if(NULL != moved) { theObject->mSymbols = (SymbolStats*)moved; theObject->mSymbolCount++; allSymbolCount++; memset(theObject->mSymbols + symbolIndex, 0, sizeof(SymbolStats)); theObject->mSymbols[symbolIndex].mSymbol = strdup(symbol); if(NULL == theObject->mSymbols[symbolIndex].mSymbol) { retval = __LINE__; ERROR_REPORT(retval, symbol, "Unable to duplicate string."); } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to increase symbol array."); } } if(0 == retval) { theSymbol = (theObject->mSymbols + symbolIndex); /* ** Update our various totals. */ if(additive) { if(CODE == segmentClass) { overall.mCode += size; theModule->mSize.mCode += size; } else if(DATA == segmentClass) { overall.mData += size; theModule->mSize.mData += size; } theSegment->mSize += size; theObject->mSize += size; theSymbol->mSize += size; } else { if(CODE == segmentClass) { overall.mCode -= size; theModule->mSize.mCode -= size; } else if(DATA == segmentClass) { overall.mData -= size; theModule->mSize.mData -= size; } theSegment->mSize -= size; theObject->mSize -= size; theSymbol->mSize -= size; } } } } } } } else { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to scan line data."); } } } if(0 == retval && 0 != ferror(inOptions->mInput)) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mInputName, "Unable to read file."); } /* ** Next, it is time to perform revisionist history of sorts. ** If the negation switch is in play, we perfrom the following ** aggressive steps: ** ** For each section, find size changes which have an equal and ** opposite change, and set them both to zero. ** However, you can only do this if the number of negating changes ** is even, as if it is odd, then any one of the many could be ** at fault for the actual change. ** ** This originally exists to make the win32 codesighs reports more ** readable/meaningful. */ if(0 == retval && 0 != inOptions->mNegation) { ObjectStats** objArray = NULL; SymbolStats** symArray = NULL; /* ** Create arrays big enough to hold all symbols. ** As well as an array to keep the owning object at the same index. ** We will keep the object around as we may need to modify the size. */ objArray = (ObjectStats**)malloc(allSymbolCount * sizeof(ObjectStats*)); symArray = (SymbolStats**)malloc(allSymbolCount * sizeof(SymbolStats*)); if(NULL == objArray || NULL == symArray) { retval = __LINE__; ERROR_REPORT(retval, inOptions->mProgramName, "Unable to allocate negation array memory."); } else { unsigned arrayCount = 0; unsigned arrayLoop = 0; /* ** Go through and perform the steps on each section/segment. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Collect all symbols under this section. ** The symbols are spread out between all the objects, ** so keep track of both independently at the ** same index. */ arrayCount = 0; for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; objArray[arrayCount] = theObject; symArray[arrayCount] = theSymbol; arrayCount++; } } /* ** Now that we have a list of symbols, go through each ** and see if there is a chance of negation. */ for(arrayLoop = 0; arrayLoop < arrayCount; arrayLoop++) { /* ** If the item is NULL, it was already negated. ** Don't do this for items with a zero size. */ if(NULL != symArray[arrayLoop] && 0 != symArray[arrayLoop]->mSize) { unsigned identicalValues = 0; unsigned oppositeValues = 0; unsigned lookLoop = 0; const int lookingFor = symArray[arrayLoop]->mSize; /* ** Count the number of items with this value. ** Count the number of items with the opposite equal value. ** If they are equal, go through and negate all sizes. */ for(lookLoop = arrayLoop; lookLoop < arrayCount; lookLoop++) { /* ** Skip negated items. ** Skip zero length items. */ if(NULL == symArray[lookLoop] || 0 == symArray[lookLoop]->mSize) { continue; } if(lookingFor == symArray[lookLoop]->mSize) { identicalValues++; } else if((-1 * lookingFor) == symArray[lookLoop]->mSize) { oppositeValues++; } } if(0 != identicalValues && identicalValues == oppositeValues) { unsigned negationLoop = 0; for(negationLoop = arrayLoop; 0 != identicalValues || 0 != oppositeValues; negationLoop++) { /* ** Skip negated items. ** Skip zero length items. */ if(NULL == symArray[negationLoop] || 0 == symArray[negationLoop]->mSize) { continue; } /* ** Negate any size matches. ** Reflect the change in the object as well. ** Clear the symbol. */ if(lookingFor == symArray[negationLoop]->mSize) { objArray[negationLoop]->mSize -= lookingFor; symArray[negationLoop]->mSize = 0; symArray[negationLoop] = NULL; identicalValues--; } else if((-1 * lookingFor) == symArray[negationLoop]->mSize) { objArray[negationLoop]->mSize += lookingFor; symArray[negationLoop]->mSize = 0; symArray[negationLoop] = NULL; oppositeValues--; } } } } } } } } CLEANUP(objArray); CLEANUP(symArray); } /* ** If all went well, time to report. */ if(0 == retval) { /* ** Loop through our data once more, so that the symbols can ** propigate their changes upwards in a positive/negative ** fashion. ** This will help give the composite change more meaning. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData)) { continue; } for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize) { continue; } for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize) { continue; } for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; /* ** Propagate the composition all the way to the top. ** Sizes of zero change are skipped. */ if(0 < theSymbol->mSize) { theObject->mComposition.mPositive += theSymbol->mSize; theSegment->mComposition.mPositive += theSymbol->mSize; if(CODE == theSegment->mClass) { overall.mCodeComposition.mPositive += theSymbol->mSize; theModule->mSize.mCodeComposition.mPositive += theSymbol->mSize; } else if(DATA == theSegment->mClass) { overall.mDataComposition.mPositive += theSymbol->mSize; theModule->mSize.mDataComposition.mPositive += theSymbol->mSize; } } else if(0 > theSymbol->mSize) { theObject->mComposition.mNegative += theSymbol->mSize; theSegment->mComposition.mNegative += theSymbol->mSize; if(CODE == theSegment->mClass) { overall.mCodeComposition.mNegative += theSymbol->mSize; theModule->mSize.mCodeComposition.mNegative += theSymbol->mSize; } else if(DATA == theSegment->mClass) { overall.mDataComposition.mNegative += theSymbol->mSize; theModule->mSize.mDataComposition.mNegative += theSymbol->mSize; } } } } } } if(inOptions->mSummaryOnly) { fprintf(inOptions->mOutput, "%+d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative); } else { fprintf(inOptions->mOutput, "Overall Change in Size\n"); fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", overall.mCode + overall.mData, overall.mCodeComposition.mPositive + overall.mDataComposition.mPositive, overall.mCodeComposition.mNegative + overall.mDataComposition.mNegative); fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", overall.mCode, overall.mCodeComposition.mPositive, overall.mCodeComposition.mNegative); fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", overall.mData, overall.mDataComposition.mPositive, overall.mDataComposition.mNegative); } /* ** Check what else we should output. */ if(0 == inOptions->mSummaryOnly && NULL != modules && moduleCount) { const char* segmentType = NULL; /* ** We're going to sort everything. */ qsort(modules, moduleCount, sizeof(ModuleStats), moduleCompare); for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; qsort(theModule->mSegments, theModule->mSegmentCount, sizeof(SegmentStats), segmentCompare); for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; qsort(theSegment->mObjects, theSegment->mObjectCount, sizeof(ObjectStats), objectCompare); for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; qsort(theObject->mSymbols, theObject->mSymbolCount, sizeof(SymbolStats), symbolCompare); } } } /* ** Loop through for output. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == (theModule->mSize.mCode + theModule->mSize.mData)) { continue; } fprintf(inOptions->mOutput, "\n"); fprintf(inOptions->mOutput, "%s\n", theModule->mModule); fprintf(inOptions->mOutput, "\tTotal:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode + theModule->mSize.mData, theModule->mSize.mCodeComposition.mPositive + theModule->mSize.mDataComposition.mPositive, theModule->mSize.mCodeComposition.mNegative + theModule->mSize.mDataComposition.mNegative); fprintf(inOptions->mOutput, "\tCode:\t%+11d (%+d/%+d)\n", theModule->mSize.mCode, theModule->mSize.mCodeComposition.mPositive, theModule->mSize.mCodeComposition.mNegative); fprintf(inOptions->mOutput, "\tData:\t%+11d (%+d/%+d)\n", theModule->mSize.mData, theModule->mSize.mDataComposition.mPositive, theModule->mSize.mDataComposition.mNegative); for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSegment->mSize) { continue; } if(CODE == theSegment->mClass) { segmentType = "CODE"; } else if(DATA == theSegment->mClass) { segmentType = "DATA"; } fprintf(inOptions->mOutput, "\t%+11d (%+d/%+d)\t%s (%s)\n", theSegment->mSize, theSegment->mComposition.mPositive, theSegment->mComposition.mNegative, theSegment->mSegment, segmentType); for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theObject->mSize) { continue; } fprintf(inOptions->mOutput, "\t\t%+11d (%+d/%+d)\t%s\n", theObject->mSize, theObject->mComposition.mPositive, theObject->mComposition.mNegative, theObject->mObject); for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; /* ** Skip if there is zero drift, or no net change. */ if(0 == inOptions->mZeroDrift && 0 == theSymbol->mSize) { continue; } fprintf(inOptions->mOutput, "\t\t\t%+11d\t%s\n", theSymbol->mSize, theSymbol->mSymbol); } } } } } } /* ** Cleanup time. */ for(moduleLoop = 0; moduleLoop < moduleCount; moduleLoop++) { theModule = modules + moduleLoop; for(segmentLoop = 0; segmentLoop < theModule->mSegmentCount; segmentLoop++) { theSegment = theModule->mSegments + segmentLoop; for(objectLoop = 0; objectLoop < theSegment->mObjectCount; objectLoop++) { theObject = theSegment->mObjects + objectLoop; for(symbolLoop = 0; symbolLoop < theObject->mSymbolCount; symbolLoop++) { theSymbol = theObject->mSymbols + symbolLoop; CLEANUP(theSymbol->mSymbol); } CLEANUP(theObject->mSymbols); CLEANUP(theObject->mObject); } CLEANUP(theSegment->mObjects); CLEANUP(theSegment->mSegment); } CLEANUP(theModule->mSegments); CLEANUP(theModule->mModule); } CLEANUP(modules); return retval; }