<%@language="javascript"%>
<% /*
    $Revision$
    $Id$

    File:           shared/500_error.asp
    Description:    Optioneel in IIS in te stellen als custom 500-error pagina

    Note:           Je zit hier in de context van het *originele* script
                    Request.ServerVariables("PATH_INFO") is het originele bestand

                    Het is heel verleidelijk common.inc te includen. Stel echter dat de database niet bereikbaar is?
                    Dan klapt m_connections.inc er weer opnieuw uit en hebben we nog niets bereikt.
                    Daarom gebruiken we ook geen lcl's in dit bestand maar hardcoded teksten.
                    Logger.inc durf ik nog net aan voor het gemak

                    PF: als deze door een service wordt gegeven wil je (ik) andere info, of althans geen geformatteerde html?
                    JGL: Bij Response Buffer Exceeded ook adviseren kleinere periode te kiezen
*/ %>
<!-- #include file="../Shared/logger.inc" -->
<!-- #include file="../Shared/json2.js" -->
<!-- #include file="../api2/api2_rest.inc" -->
<%
try { Response.Clear; } catch (e) {};

if (Request.QueryString("check500").Count > 0)
{
    Response.Write("OK500"); // voor fac_verify.asp
    Response.End;
}

var objASPError = Server.GetLastError;
var proto = (Request.ServerVariables("SERVER_PORT") == "443")? "https" : "http";
var sitenoroot = proto + "://" + Request.ServerVariables("SERVER_NAME");
// Opgepikt door logger.inc
var hiresTimer = null;
var __LogfileName = LogfileName();
var __LogfileTitle = "AiAi";
var __LogNoClear = true;

// Waarschijnlijk een jQuery ajax
var format = String(Request.QueryString("format")).toLowerCase();
if (String(Request.ServerVariables("HTTP_ACCEPT")).match(/application\/json/) != null ||
    String(Request.ServerVariables("HTTP_X-Requested-With")) == "XMLHttpRequest" ||
    (Request.QueryString("api2").Count > 0 && format != "scf")
    )
{
    switch (objASPError.ASPCode)
    {
        case "ASP 0113": // Script timed out
        {
            var msg = "Opvragen van de pagina duurde te lang.";
            if (String(Request.ServerVariables("SCRIPT_NAME")).match(/list/i) || String(Request.ServerVariables("SCRIPT_NAME")).match(/res_search_plan/i))
            {
                msg += "\nEen mogelijke oplossing kan zijn om uw zoekfilter aan te passen zodat minder resultaten worden opgeleverd.";
            }
            break;
        }
        case "ASP 0251": // Response Buffer Limit Exceeded
        {
            var msg = "Opgevraagde pagina is te groot.";
            if (String(Request.ServerVariables("SCRIPT_NAME")).match(/list/i) || String(Request.ServerVariables("SCRIPT_NAME")).match(/res_search_plan/i))
            {
                msg += "\nEen mogelijke oplossing kan zijn om uw zoekfilter aan te passen zodat minder resultaten worden opgeleverd.";
            }
            break;
        }
        default:
        {
            var msg = "Aiai"
                    + "\nEr is iets fout gegaan, maar dat ligt waarschijnlijk niet aan u."
                    + "\nDeze fout wordt automatisch geregistreerd en onderzocht."
                    + "\nU kunt wellicht het beste uw browser verversen en verder gaan met uw werk."
            break;
        }
    }
    msg += "\n\nFACILITOR " + toDateTimeString(new Date())
        + ", " + sitenoroot;

    if (Session("logging") > 0)
    {
        msg += "\n(Zie " + LogfileName() + ")";
    }
    if ((Application("otap_environment") == "O" || Session("logging") > 0) && objASPError.Description)
        msg += "\n\n(gaat niet naar klanten:)\n" + objASPError.Description + "\n" + objASPError.File + "(" + objASPError.Line + ")";

    if (Request.QueryString("api2").Count > 0)
    {
        var data = { error: { code: 500,
                              message: msg
                            }
                   };
        if (Application("otap_environment") == "O" || Session("logging") > 0)
            data.error.internal = ASPErrorJson();

        if (format == "xml")
        {
            Response.ContentType = "text/xml";
            var xml_antwoord = api2_rest.json2xml([data.error], { records_name: "errors", record_name: "error"}, true);
            Response.Write(xml_antwoord.xml);
        }
        else if (format == 'html')
        {
            Response.ContentType = "text/html";
            var str_antwoord = "<!DOCTYPE html><html><head></head><body><pre>"
                             +      Server.HTMLEncode(JSON.stringify(data, null, 2))
                             + "</pre></body></html>";
            Response.Write(str_antwoord);
        }
        else
        {
            Response.ContentType = "application/json";
            Response.Write(JSON.stringify(data, null, 2));
        }
    }
    else
        Response.Write("FCLTFriendly:" + msg); // FCLTFriendly wordt zo opgepikt door FcltJquery.js ajaxSetup error handler
    LogErrorToFile();
    Response.End;
};

// Breek heel grof uit eventuele geneste HTML zodat onze tekst duidelijk in beeld komt
Response.Write("</script></table></table></option></select></form>");

// Dit gaat naar de eindgebruiker:

// styling vrij hard omdat we niet op css kunnen rekenen
%>
<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family:Arial,Helvetica;
            font-size: 90%!important;
        }
        div.aiai {
            text-align: left;
            border: 3px solid #FF6F6F;
            padding: 20px 20px 40px 20px;
            width: 450px;
            font-size:1em;
            font-weight: normal;
            color: black;
            background-color: #fff0f0;
        }
        table tbody tr td {
            font-family: Courier;
            font-size:12px;
            padding: 2px;
        }
        table.source {
            background-color: #f8f8f8;
        }
        td.linenr {
            background-color: white;
            text-align: right;
            width: 40px;
            padding-right: 4px;
        }
        pre { margin: 0px;
              background-color: #f8f8f8;
        }
        .important {
            font-weight: bold;
            background-color: #fee;
        }
        .klein {
            font-size: 8px;
        }
    </style>
</head>
<body>
<div class='aiai'>
<h1 style='color:red'>Aiai!</h1>
<%
switch (objASPError.ASPCode)
{
    case "ASP 0113": // Script timed out
    {
        Response.Write("Opvragen van de pagina duurde te lang.");
        if (String(Request.ServerVariables("SCRIPT_NAME")).match(/list/i) || String(Request.ServerVariables("SCRIPT_NAME")).match(/res_search_plan/i))
        {
            Response.Write("<br><br>Een mogelijke oplossing kan zijn om uw zoekfilter aan te passen zodat minder resultaten worden opgeleverd.");
        }
        break;
    }
    case "ASP 0251": // Response Buffer Limit Exceeded
    {
        Response.Write("Opgevraagde pagina is te groot.");
        if (String(Request.ServerVariables("SCRIPT_NAME")).match(/list/i) || String(Request.ServerVariables("SCRIPT_NAME")).match(/res_search_plan/i))
        {
            Response.Write("<br><br>Een mogelijke oplossing kan zijn om uw zoekfilter aan te passen zodat minder resultaten worden opgeleverd.");
        }
        break;
    }
    default:
    {
        Response.Write("Er is iets fout gegaan, maar dat ligt waarschijnlijk niet aan u.");
        Response.Write("\n<br><br><span style='font-size:0.8em'>Deze fout wordt automatisch geregistreerd en onderzocht.");
        Response.Write("\n<br>U kunt wellicht het beste uw browser verversen en verder gaan met uw werk.</span>");
        Response.Write("\n<br><br><span style='font-size:0.8em;'>FACILITOR "+toDateTimeString(new Date())+"</span>");
        Response.Write("\n<br><span style='font-size:0.8em;'>" + sitenoroot + "</span>");
        break;
    }
}

Response.Write("</div></body></html>");

LogErrorToFile();

if (Application("otap_environment") == "O" || Session("logging") > 0)
{
  Response.Write("\n<p>De rest is niet zichtbaar voor klanten.<br>");
  Response.Write("\n<span class='klein'>\\cust\\custenv.wsc heeft Overrule.APPLICATION(\"otap_environment\", \"O\"); of logging staat aan</span></p>");
  var logfilename = Application(Session("customerId") + "_logfilename");
  var loghtml = "";
  if (logfilename)
  {
    loghtml = " of de <a href='" + rooturl + "/" + Server.HTMLEncode(logfilename) + ".html?" + (new Date).getTime() + "' target='_blank'>gewone logfile </a>";
  }
  Response.Write("\n<hr><p>Zie <a href='" + Server.HTMLEncode(logurl) + "' target='_blank'>AiAi logfile</a> " + loghtml + "voor meer details of klik <a href='javascript:location.reload()'><button>Refresh</button></a> om het opnieuw te proberen.</p>");

  var pad = String(Request.ServerVariables("PATH_TRANSLATED"));
  var params = String(Request.ServerVariables("QUERY_STRING"));
  if (params!="")
  {
      pad += "?" + params;
  }
  var y = String(Request.ServerVariables("APPL_PHYSICAL_PATH")); // Zoveel gaan we er af strippen
  pad = pad.substring(y.length);
  var method = Request.ServerVariables("REQUEST_METHOD");
  var extra = "<tr><td>Customer:</td><td>" + Session("customerId") + (rooturl.length>1?'@'+rooturl.substr(1):"") + "</td></tr>";

  // Lees de UDL tekstueel uit. We zitten al in de problemen dus we hebben geen m_connections.inc
  var ForReading = 1;
  var tsUnicode = -1;

  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var udl = Server.MapPath(rooturl + "/cust/" + Session("customerId") + "/Oracle.udl");
  try
  {
      var f = fso.OpenTextFile(udl, ForReading, true, tsUnicode);
      var s = f.ReadLine();
      s = f.ReadLine();
      s = f.ReadLine(); //3e regel is interessant
      // Provider=OraOLEDB.Oracle.1;Password=xxxxx;Persist Security Info=True;User ID=hcas;Data Source=fclt
      var sa = s.split(";");
      var data = [];
      var uid = "";
      var tns = "";
      for (var i = 0; i < sa.length; i++)
      {
          var itma = sa[i].split("=");
          if (itma.length == 2)
          {
              if (itma[0] == 'User ID')
                uid =  itma[1];
              if (itma[0] == 'Data Source')
                tns =  itma[1];
          }
      }
      f.Close();
  }
  catch (e)
  {
    uid = "Not found";
    tns = udl;
  }
  extra += "<tr><td>Database:</td><td>" + uid + "@" + tns + "</td></tr>";

  var ttl = "?" + params.replace(/\%2C/g, ",").split("&").join("\n&");
  extra += "<tr><td>Url:</td><td title='" + Server.HTMLEncode(ttl) + "'>" + Server.HTMLEncode(method + " " + pad) + "</td></tr>";
  Response.Write(ASPErrorText(extra));

  Response.Write("\n<br>" + ShowSourcecode(-8, +4));
}

Response.End;

function ASPErrorText(extra)
{
    var err = "<table class='error'>";
    err += (extra||"");

    var props = ["Category", "ASPCode", "ASPDescription", "Description", "File", "Line", "Column", "Source", "Number"];
    for (v in props)
    {
      if (objASPError[props[v]])
      {
        var safeprop = Server.HTMLEncode(objASPError[props[v]]).replace(/\n/g,"<br/>");
        if (props[v] == 'Description')
            safeprop = "<span class='important'>" + safeprop + "</span>";
        err += "<tr><td style='vertical-align:top'>"+props[v]+":</td><td>" + safeprop + "</td></tr>";
      }
    }
    err += "</table>";
    return err;
}

function ASPErrorJson()
{
    var err = {};
    var props = ["Category", "ASPCode", "ASPDescription", "Description", "File", "Line", "Column", "Source", "Number"];
    for (v in props)
    {
      if (objASPError[props[v]])
      {
        err[props[v]] = objASPError[props[v]];
      }
    }
    return err;
}

function LogErrorToFile()
{
    __DoLog("Session('customerId'): " + Session("customerId"), "#f00");
    __SafeDoLog(ASPErrorText());
    if (Request.ServerVariables("HTTP_REFERER").Count)
        __DoLog("Referer: " + Request.ServerVariables("HTTP_REFERER"));
    __SafeDoLog(ShowSourcecode(-8, +4));

    if (Request.QueryString.Count>0) // Hele URL is al wel gelogd maar dit is leesbaarder
    {
        __SafeDoLog(__DumpCollection(Request.QueryString, "Request.QueryString"));
    }
    try
    {
         if (Request.Form.Count>0)
            __DoLogForm();
    }
    catch(e)
    {
        __SafeDoLog(Server.HTMLEncode(e.description) + "<br>Loggen form mislukt, er is waarschijnlijk gewoon al een Request.BinaryRead geweest.")
    }
    __SafeDoLog(__DumpCollection(Session.Contents, "Session"));
    __SafeDoLog("IP: " + Request.ServerVariables("REMOTE_ADDR") + "<br>Useragent: " + Server.HTMLEncode(Request.ServerVariables("HTTP_USER_AGENT")));
}

var rooturl;
var logurl;
function LogfileName()
{
// autodetect rooturl. Al onze pagina's beginnen met /cust of met /appl
    var pad = String(Request.ServerVariables("PATH_INFO"));
    var lowerpad = pad.toLowerCase();
    var i1 = lowerpad.indexOf("/cust/");
    if (i1 < 0)
        i1 = lowerpad.indexOf("/appl/");
    if (i1 < 0)
        i1 = lowerpad.indexOf("/default.asp"); // API's
    /* global */ rooturl = pad.substr(0, i1);

    // Zoek de TempFolder, de enige folder met 'gegarandeerd' schrijfrechten
    var fso = Server.CreateObject("Scripting.FileSystemObject");
    var sPath = Server.MapPath("./");

    while (fso.FolderExists(sPath) && !fso.FolderExists(sPath + "/temp"))
    {
        sPath = fso.GetParentFolderName(sPath);
    }
    if (!fso.FolderExists(sPath + "/temp") || !fso.FolderExists(sPath + "/appl") || !fso.FolderExists(sPath + "/cust"))
        return null; // Het moet wel de TEMP folder zijn naast APPL, niet toevallig eentje in de root

    // Naam van de AiAi folder bepalen. Kijk daartoe of er al een folder is van de vorm /temp/500_error_xxxxx
    var f = fso.GetFolder(sPath + "/temp/");
    var fname = "500_error_" + Math.floor(Math.random() * 1e16);
    for (var ff = new Enumerator(f.SubFolders); !ff.atEnd(); ff.moveNext())
    {
        if (ff.item().Name.match(/^500_error_[0-9]*/))
        {
            fname = ff.item().Name;
            break;
        }
    }

    var nowtxt = toDateString(new Date());
    var folder = sPath + "/temp/" + fname;
    /* global */ logurl = rooturl + "/temp/" + fname + "/log_" + nowtxt + ".html";
    if (!fso.FolderExists(folder))
        fso.CreateFolder(folder);
    return folder + "/log_" + nowtxt + ".html";
}

function ShowSourcecode(minregel, plusregel)
{
    if (!objASPError.File)
    {
        return "<span style='background-color:magenta'><p>Vreemd genoeg geen objASPError.File?</span>";
    }
    var fso = Server.CreateObject("Scripting.FileSystemObject");
    var result = "Source:"+objASPError.File + "<br>";
    var myFile = fso.OpenTextFile(Server.MapPath(objASPError.File));
    var ll =0;
    while (!myFile.AtEndOfStream && ll < objASPError.Line + minregel)
    {
        ll ++;
        myFile.SkipLine();
    }
    result += "<table class='source'>";
    while (!myFile.AtEndOfStream && ll < objASPError.Line + plusregel)
    {
        ll++;
        var stl = "";
        var txt = myFile.ReadLine();
        if (ll==objASPError.Line)
        {
            stl = "style='background-color:#e0fafa'";
            if (objASPError.Column > 0)
            {
                txt = Server.HTMLEncode(txt.substr(0, objASPError.Column))
                    + "<span style='background-color:#f88;'>"
                    +       Server.HTMLEncode(txt.substr(objASPError.Column, 1))
                    + "</span>"
                    + Server.HTMLEncode(txt.substr(objASPError.Column + 1));
            }
            else
                txt = Server.HTMLEncode(txt);
        }
        else
            txt = Server.HTMLEncode(txt);
        result += "<tr><td class='linenr'>" + ll + "</td><td class='source'><pre "+stl+">" + txt + "</pre></td></tr>";
    }
    myFile.Close()
    result += "</table>";
    return result;
}

// Dit bestand moet geheel zelfvoorzienend worden dus sommige handige functies maar herhalen
function padout(number) { return (number < 10) ? "0" + number : number; }
// Noot: altijd jaar vooraan, goed voor logfiles, niet bedoeld voor presentatie
function toDateString(jsDate)
{
    return padout(jsDate.getFullYear())  + "-" + padout(jsDate.getMonth() + 1) + "-" + padout(jsDate.getDate());
}
function toDateTimeString(jsDate)
{
    return toDateString(jsDate) + " "
         + padout(jsDate.getHours()) + ":" + padout(jsDate.getMinutes())   + ":" + padout(jsDate.getSeconds());
}
%>
