<% /*
     $Revision$
     $Id$

     File:    shared/logger.inc
     Context: iframe vanuit appl/fac/Facilitor.asp

     Note:    SESSION must be started like: http://facws002/trunk/?logging=3
              param '&logging=getal'

              geen waarde-->In ieder geval serverside loggen zoals nu ook-->Identiek aan getal==1
              getal is bitwise:
                 &1->serverside loggen
                 &2->serverside logwindow openen op client
                 &8->Bewaar tempfiles van Facilitor Graphics
                &32->Facmgt loggen (deels)
*/

function us_timer()
{
    return hiresTimer?hiresTimer.usTimer:(new Date().getTime()*1000);
}

var __LogfileName = null;
var __LogfileTitle = null;
htmlLogger =
{
    _padout3: function (number) { return (number < 100) ? '0' + padout(number) : number; },
    _lastclose : -1, // when was lastclose?
    // === Public functions ===
    log_tekst: function (safe_s, optionalColor, optionalCaller, leave_open) // de hoofd log functie
    {
        this._us_start = us_timer();
        if (this._script_id == -1)
            this._script_id = this._log_script();

        var now = new Date();
        var sNow = padout(now.getHours())+":"+padout(now.getMinutes())+":"+padout(now.getSeconds());
        if (hiresTimer)
        {
            if (this._startDiff == null)
                this._startDiff = (new Date()).getTime() - (hiresTimer.usTimer / 1000);
            var endDiff = now.getTime() - (hiresTimer.usTimer / 1000);
            var ms = now.getTime()%1000 + (this._startDiff - endDiff);
            sNow += "."+this._padout3(Math.floor(ms));

            if (this._lastclose > 0)
            {
                var tm = (hiresTimer.usTimer - this._lastclose)/1000;
                tm = tm.toFixed(0);
                var style = "";
                if (tm > 30) // te veel tijd met processing bezig geweest
                    style = " style='background-color: #FF0000;'";
                else if (tm > 15)
                    style = " style='background-color: #FFFF00;'";
                if (tm > 5)
                    sNow += " (<span "+style+" title='Vorige statement was " + tm + " ms geleden al klaar.\nTrage processing?'>" + tm + "ms</span>)";
            }
        }
        else
            sNow += "."+this._padout3(now.getMilliseconds());

        var txt = safe_s;
        txt = txt.replace(/^INSERT /i,"<b>INSERT</b> ").replace(/^UPDATE /i,"<b>UPDATE</b> ")
                 .replace(/^DELETE /i,"<b>DELETE</b> ").replace(/^BEGIN /i,"<b>BEGIN</b> ")
                 .replace(/^DECLARE /i,"<b>DECLARE</b> ").replace(/END;$/i,"<b>END;</b> ");
        if (optionalColor)
            txt = "<div style=\"background-color: "+optionalColor+";\">"+txt+"</div>";

        this._do_write("<tr><td valign='top' class='tm'>"+sNow
                     +     "\n<div class='caller'>" + (optionalCaller||"&lt;global code&gt;") + "</div>" + "</td>"
                     + "<td>" +txt +"</td>" + (leave_open?"":"</td></tr>"));
        this._do_close();

        return -1; // geen id
    },

    log_close: function (handle, s_extra, optionalColor) // extra toevoeging aan laatste 'openstaande' regel
    {
        if (this._script_id == -1)
            this._script_id = this._log_script();

        this.us_end = us_timer();

        var us_taken = (this.us_end - this._us_start) / 1000;

        var style = "";
        var txt = "";

        if (us_taken == 0)
            txt = "<1ms"
        else
            txt = us_taken.toFixed(us_taken<10?1:0) + "ms";
        if (us_taken > 250)
            style = " style=\"background-color: #FF0000;\"";
        else
            if (us_taken > 50)
                style = " style='background-color: #FFFF00;'";

        if (optionalColor)
            style = " style='background-color: "+optionalColor+";'";
        if (s_extra && s_extra != "") txt += "<br><b>"+s_extra+"</b>";

        this._do_write("<td " + style + ">" + txt + "</td></tr>");
        this._do_close();
    },

    // === Private functions ===
    _script_id: -1,
    _file_handle: null,
    _us_start: -1,
    _startDiff : null,

    // Na do_write moet je altijd _do_close aanroepen!
    _do_write: function (tekst)
    {
        if (!this._file_handle)
        {
            if (!__LogfileName) // 500_error.asp zet hem zelf
                __LogfileName = Server.MapPath(rooturl + "/temp/log_" + customerId + ".html.log");
            var objFSO = Server.CreateObject("Scripting.FileSystemObject");
            var IsNew = (!objFSO.FileExists(__LogfileName))

            this._file_handle = objFSO.OpenTextFile(__LogfileName, 8, true, 0); // 8 ForAppending, true is create
            objFSO = null;
            if (IsNew)
            {
                 __LogfileTitle = __LogfileTitle ||Session("customerId");
                 this._file_handle.WriteLine("<head>");
                 this._file_handle.WriteLine("<meta http-equiv=\"cache-control\" content=\"no-cache, no-store, must-revalidate\">");
                 this._file_handle.WriteLine("<meta http-equiv=\"pragma\" content=\"no-cache\">");
                 this._file_handle.WriteLine("<meta http-equiv=\"expires\" content=\"-1\">");
                 this._file_handle.WriteLine("<style>");
                 this._file_handle.WriteLine("td {");
                 this._file_handle.WriteLine("  font-family: Verdana;");
                 this._file_handle.WriteLine("  font-size: smaller;");
                 this._file_handle.WriteLine("  padding: 2px;");
                 this._file_handle.WriteLine("  background-color: #D6D8E8;");
                 this._file_handle.WriteLine("}");
                 this._file_handle.WriteLine(".script td { background-color: #C6C8C8; }");
                 this._file_handle.WriteLine("td.source,td.linenr,pre {");
                 this._file_handle.WriteLine("  padding: 0px; margin: 0px; font-size: 8pt; }");
                 this._file_handle.WriteLine(".querystring, .bodysize { color: #666; }");
                 this._file_handle.WriteLine("span.truncated { font-size: 7px; color: #d00; }");
                 this._file_handle.WriteLine(".orgurl { padding-left:6.5em; color: #666; }");
                 this._file_handle.WriteLine("div.caller { font-size:8pt; display: none; position:absolute;");
                 this._file_handle.WriteLine("             border-radius: 5px; padding:5px; min-width: 14em;");
                 this._file_handle.WriteLine("             box-shadow: 8px 8px 5px #a0a0a0;");
                 this._file_handle.WriteLine("             color: #222; background-color:#ffffe0;  }");
                 this._file_handle.WriteLine("div.caller:before {");
                 this._file_handle.WriteLine("  content: ' '; position: absolute;");
                 this._file_handle.WriteLine("  width: 0; height: 0;");
                 this._file_handle.WriteLine("  left: 10px; top: -16px;");
                 this._file_handle.WriteLine("  border: 8px solid;");
                 this._file_handle.WriteLine("  border-color: transparent transparent #ffffe0; transparent");
                 this._file_handle.WriteLine("}");
                 this._file_handle.WriteLine("td.tm:hover div.caller, div.caller:hover { display:block; }");
                 this._file_handle.WriteLine("</style>");
                 this._file_handle.WriteLine("<title>*" + __LogfileTitle + (rooturl?" "+rooturl:"") + " FACILITOR logger</title>");
                 this._file_handle.WriteLine("</head>");
                 this._file_handle.WriteLine("<body>");
                 if (typeof __LogNoClear == "undefined")
                 {
                    this._file_handle.WriteLine("<form action='../shared/wisLog.asp'>")
                    this._file_handle.WriteLine("    <input type='submit' accesskey='X' value='CLEAR this logfile ([Shift+]Alt+x)'>");
                    this._file_handle.WriteLine("</form>");
                }
                 this._file_handle.WriteLine("<table id='tabel'>"); // The closing </table> is never placed. IE doesn't care
                 this._file_handle.WriteLine("<tr><td colspan='3'>" + __LogfileTitle + " logfile " + __LogfileName + "</td></tr>");
            }
        }
        this._file_handle.WriteLine(tekst);
        return;
    },

    _do_close: function ()
    {
        this._file_handle.Close();
        this._file_handle = null;
        if (hiresTimer)
            this._lastclose = hiresTimer.usTimer;
    },

    _log_script: function ()
    {
        var now = new Date();
        var sDat = now.getDate()+"-"+padout(now.getMonth()+1)+"-"+padout(now.getFullYear());

        var pad = String(Request.ServerVariables("PATH_TRANSLATED"));
        var params = String(Request.ServerVariables("QUERY_STRING"));
        if (params!="")
        {
            var sparams = params.split("&");
            for (var i = 0; i < sparams.length; i++)
            {
                if (sparams[i].length > 60)
                    sparams[i] = sparams[i].substr(0, 20) + "<span class='truncated' title='" + Server.HTMLEncode(sparams[i]) + "'>[&hellip;]</span>" + sparams[i].substr(sparams[i].length - 20);
            }
            params = sparams.join("&amp;");
            pad += "<span class='querystring'>?" + params + "</span>";
        }
        var y = String(Request.ServerVariables("APPL_PHYSICAL_PATH")); // Zoveel gaan we er af strippen
        pad = pad.substring(y.length);

        var ip = Request.ServerVariables("REMOTE_ADDR") + " " + Request.ServerVariables("REMOTE_USER");
        var method = Request.ServerVariables("REQUEST_METHOD");

        var orgurl = Request.ServerVariables("HTTP_X_REWRITE_URL");
        if (orgurl.Count)
            pad += "<br><span class='orgurl'>" + method + " " + String(orgurl).substring(rooturl.length + 1) + "</span>";
        else
        {
            var orgurl = Request.ServerVariables("HTTP_X_ORIGINAL_URL"); // Origineel van IIS Rewriter
            if (orgurl.Count)
                pad += "<br><span class='orgurl'>" + method + " " + String(orgurl).substring(rooturl.length + 1) + "</span>";
        }

        var linkdat = "<a href='#tm" + now.getTime() + "' name='tm" + now.getTime() + "'>" + sDat + "</a>";
        var usrtxt = (Session("user_key")||"");
        // Probeer de oslogin er bij te loggen als die al ooit was opgehaald. Vaak is er
        // helaas nog geen _require_prs_perslid geweest als we deze headerregel schrijven
        if (typeof user == "object" && user && "_prs_perslid_oslogin" in user)
            usrtxt += " " + user._prs_perslid_oslogin;
        var txt =("</td></tr><tr class='script'><td colspan=3 valign='top' title='"+ ip + " " + usrtxt + "'>" + linkdat + " " + method + " " + pad);
        if (method == "POST" || Request.TotalBytes > 0)
           txt += " <span class='bodysize'>(body " + Request.TotalBytes + " bytes)</span>";

        this._do_write(txt);
        // _do_close komt wel in log_tekst()
        return 1; // dummy id
    }
};

theLogger = htmlLogger; // ooit geexperimenteerd met sqliteLogger

// Return true als we de logging parameter gevonden hebben in qtstring
function CheckForLogging(qstring)
{
    if (qstring && qstring.Count>0)
    {
        var lg = parseInt(qstring(1), 10)||0;
        if (lg != 0 && Application("otap_environment") != "O")
            user.checkAutorisation("WEB_FACTAB"); // Minimaal

        Session("logging") = lg;
        return true;
    }
    return false;
}

function __LogCloseLine(handle, s_extra, optionalColor)
{
    if (Session("logging")&1)
    {
        __DoLogCloseLine(handle, s_extra, optionalColor)
    }
}

function __DoLogCloseLine(handle, s_extra, optionalColor)
{
    if (typeof Logging_disable != "undefined")
        return;
    try
    {
        theLogger.log_close(handle, s_extra?String(s_extra):null, optionalColor);
    }
    catch(e)
    {  // Waarschijnlijk een permission denied omdat twee processen tegelijk proberen te schrijven
    }
}

// Voor als je HTML wilt gebruiken in s
function __SafeLog(s, optionalCaller, leave_open)
{
    if (Session("logging")&1)
    {
        return __SafeDoLog(s, null, optionalCaller, leave_open)
    }
}

function __Log(s, optionalCallerOrColor, leave_open)
{
    if (Session("logging")&1)
    {
        var optionalColor = optionalCallerOrColor;
        var optionalCaller;
        if (typeof optionalCallerOrColor == "function")
        {
            var optionalColor = null;
            var optionalCaller = optionalCallerOrColor;
        }
        return __DoLog(s, optionalColor, optionalCaller, leave_open)
    }
}

function __callerTekst(clr, nesting)
{
    if (!clr)
        return "";
    var cl = clr.toString().match(/function\s*(\w*)/)[1];
    cl = cl?"{"+cl+"}":"";
    if (!clr.caller)
        return cl;
    nesting = nesting || 0;
    if (nesting > 20)
        return "&lt;Nesting to deep??&gt;"; // Onverklaard. Gezien op GET appl\mgt\prs_perslid.asp?mode=list&model=custom_fields&flexparentkey=55559

    var prnt = __callerTekst(clr.caller, nesting + 1);
    if (prnt != "")
        return (cl||"&lt;anonymous&gt;") + "<br>" + prnt;
    else
        return cl + prnt;
}

// Als de Normale log maar dan geforceerd, onafhankelijk van logging settings
// optionalColor bijvoorbeeld "#FF0000" voor rood
// __DoLog("Very bad situation", "#FF0000")
function __DoLog(s, optionalColor, optionalCaller, leave_open)
{
    if (s !== null && typeof s == "object")
    {
        if (typeof JSON != "undefined")
            s = JSON.stringify(s, null, '&nbsp;&nbsp;').replace(/\n/ig,"<br>");
        else // json2.js in niet included blijkbaar
            s = "<em style='font-size:smaller'>JSON is niet gedefinieerd, fallback naar __Log:</em><br>" + Server.HTMLEncode(String(s))
    }
    else
        s = Server.HTMLEncode(String(s)).replace(/\n/g, "<br>");
    __SafeDoLog(s, optionalColor, optionalCaller, leave_open);
}

// Veronderstel dat s HTML-safe is
function __SafeDoLog(s, optionalColor, optionalCaller, leave_open)
{
    if (typeof Logging_disable != "undefined")
        return;
    try
    {
        return theLogger.log_tekst(String(s), optionalColor, __callerTekst(optionalCaller||__Log.caller), leave_open)
    }
    catch(e)
    {  // Waarschijnlijk een permission denied omdat twee processen tegelijk proberen te schrijven
        //throw(e);
        debugger;
    }
}

function __DumpCollection(pCollection, title, optionalColor)
{
    var sLog = title + " ("+pCollection.Count+" items):";
    if (optionalColor)
    {
        sLog = "<div style=\"background-color: "+optionalColor+";\">"+sLog+"</div>";
    }
    sLog += "<table class='inside'>";
    var i;
    for (i=1; i<=pCollection.Count; i++)
    {
        sLog += "<tr><td>" + Server.HTMLEncode(pCollection.key(i)); // + " type: " + typeof pCollection(i) + " cons: " + pCollection(i).constructor
        if (String(pCollection.key(i)).match(/password|pwd|pswd/i))
        {
            sLog += "</td><td><em>hidden</em>"
        }
        else if (typeof pCollection(i) != "object" || pCollection(i) === null)
        {
            sLog += "</td><td>" + Server.HTMLEncode(pCollection(i));
            var v = pCollection.item(i);
            var numv = parseInt(v);
            if (!isNaN(numv))// Als de keynaam een datum lijkt dan datum parsen. Leest gemakkelijker
            {
                if (String(pCollection.key(i)).match(/(^date|van$|tot$|datum)/)
                    || (numv > 946684800000 && numv < 2145916800000)) // 2000-2038
                    sLog += "&nbsp;<em style='font-size:smaller'>" + toISODateTimeString(new Date(parseInt(v)), true) + "</em>";
            }
        }
        else
        {
            if (pCollection(i).Count>1)
                sLog += "("+pCollection(i).Count+"x)"
            sLog += "</td><td>"
            var j;
            for (j=1; j<=pCollection(i).Count; j++)
            {
                if (j>1)
                    sLog += "<br>"
                if (typeof pCollection(i).key == "object")
                    sLog += Server.HTMLEncode(pCollection.item(i).key(j)) + ": ";
                sLog += Server.HTMLEncode(pCollection.item(i)(j));
                var v = pCollection.item(i)(j);
                var numv = parseInt(v);
                if (!isNaN(numv))// Als de keynaam een datum lijkt dan datum parsen. Leest gemakkelijker
                {
                    if (String(pCollection.key(i)).match(/(^date|date$|van$|tot$|datum)/)
                        || (numv > 946684800000 && numv < 2145916800000)) // 2000-2038
                        sLog += "&nbsp;<em style='font-size:smaller'>" + toISODateTimeString(new Date(parseInt(v)), true) + "</em>";
                }
            }
        }
        sLog += "</td></tr>";
    }
    sLog += "</table>";
    return (sLog);
}

// Log alle Request.Form variabelen in een tabel onvoorwaardelijk
function __DoLogForm(optionalColor)
{
    __SafeDoLog(__DumpCollection(Request.Form, "Request.Form", optionalColor));
}

function __LogForm()
{
    if (!(Session("logging")&1)) return; // Don't bother
    __DoLogForm();
}

// Noot: altijd jaar vooraan, goed voor logfiles, niet bedoeld voor presentatie
// padout herhalen voor 500_error.asp
function padout(number) { return (number < 10) ? "0" + number : number; }
function toISODateString(jsDate)
{
    return padout(jsDate.getFullYear())  + "-" + padout(jsDate.getMonth() + 1) + "-" + padout(jsDate.getDate());
}

function toISODateTimeString(jsDate)
{
    return toISODateString(jsDate) + " "
         + padout(jsDate.getHours()) + ":" + padout(jsDate.getMinutes())   + ":" + padout(jsDate.getSeconds());
}

function __Log2FileName(postfix)
{
    var fso = Server.CreateObject("Scripting.FileSystemObject");
    var folder = Server.MapPath(rooturl + "/temp/" + customerId + "_files");
    if (!fso.FolderExists(folder))
        fso.CreateFolder(folder);
    var log_file = folder + "/" + postfix + "_";
    var jsDate = new Date();
    var s = String(jsDate.getFullYear()) + padout(jsDate.getMonth() + 1) + padout(jsDate.getDate())
          + padout(jsDate.getHours()) + padout(jsDate.getMinutes()) + padout(jsDate.getSeconds())
    log_file = log_file + s + ".xml";
    return log_file;
}

function __Log2File(data, postfix)
{
    var log_file = __Log2FileName(postfix);
    var fs  = Server.CreateObject("Scripting.FileSystemObject");
    var ts  = fs.CreateTextFile(log_file, true);
    ts.WriteLine (data);
    ts.Close();
}
%>