!7 concept Log { S programID, ip; long count, last; } static ConceptFieldIndexDesc lastAccessIndex; p { dbSaveEvery(60); dbIndexing(Log, 'ip); lastAccessIndex = new ConceptFieldIndexDesc(Log, 'last); makeSalt(); } static File saltFile() { ret secretProgramFile("salt"); } sS salt() { ret trim(loadTextFile(saltFile())); } svoid makeSalt { if (empty(salt())) saveTextFile(saltFile(), aGlobalID()); } html { if (webAuthed(params) && eq(uri, "/logs")) { long since = parseLongOpt(params.get("since")); //L l = unlistedCopies(sortedByFieldDesc(Log, 'last)); Iterator it = lastAccessIndex.objectIterator(); new L l; while (l(l) < 500 && it.hasNext()) { Log log = it.next(); if (log.last < since) break; l.add(unlistedCopy(log)); } S salt = salt(); for (Log log : l) log.ip = md5(log.ip + salt); ret serveText(renderConcepts(l)); //ret serveText(renderConcepts(list(Log))); } S id = fsI(params.get("id")); S ip = clientIP(); Log log = uniq(Log, +ip, programID := id); cset(log, count := log.count+1, last := now()); S md5 = getServerTranspilationMD5(id); // if transpilation is outdated, hasServerDex will be false if (isMD5(md5) && !hasServerDex(id)) md5 = "-"; if (isMD5(md5)) ret md5; else ret "-"; }