Login
Artifact [ac6a62522a]
Login

Artifact ac6a62522af799fa4107b7adc0916d1fecfc425d:


assert api.cgi

scope { /* Set up some extra CGI environment... */
    const CGI = api.cgi
    const R = CGI.request;
    const uri = R.ENV.REQUEST_URI
    if(uri){
      /* Some hackery/normalizing of the root path for creating links... */
      const indexPageName = 'index.cgi' // kludge!
      const lastChar = uri.charAt(uri.length()-1)
      if(uri.indexOf('.cgi') < 0){
        if('/' === lastChar ){
          CGI.cgiRoot = uri + indexPageName + '/'
        }else{
          CGI.cgiRoot = uri // ???
        }
      }else{
        if('/' !== lastChar ){
          CGI.cgiRoot = uri.split('.cgi').0+'.cgi/'
        }else{
          CGI.cgiRoot = uri
        }
      }
    }
    const serverName = R.ENV.SERVER_NAME
    CGI.isLocalServer = ((!serverName) || (0<=serverName.indexOf(".local")))

    if(R.ENV.PATH_INFO && CGI.cgiRoot){
        CGI.pageLinkRoot =  CGI.cgiRoot + R.ENV.PATH_INFO.substr(1/*trim leading slash*/)
    }else{
        CGI.pageLinkRoot = CGI.cgiRoot
    }
}

api.cgi.config = object{
    scrubExceptions: !api.cgi.isLocalServer,//true,
    onlyDeepestException: true,//false
    sessionCookieKey: 'fSession',
    cookiePath: api.cgi.cgiRoot
}

api.cgi.out = api.io.output

/**
    Removes "potentially security-relevant" properties from the
    exception ex, recursively in all 'rethrown' exceptions. If
    ex.rethrown is set and api.cgi.config.onlyDeepestException is
    true, it returns that value, else return ex.
*/
api.cgi.scrubException = proc(ex){
    if(this.config.scrubExceptions){
        unset ex.script, ex.callStack, ex.line, ex.column // security-relevant
    }
    //this.config.onlyDeepestException && return ex
    ex.rethrown && argv.callee.call(this, ex.rethrown)
    return (this.config.onlyDeepestException && ex.rethrown) ? ex.rethrown : ex
}

/**
  Assumes obj is a legal value for the 'J' format specifier for Buffer.appendf()
  and outputs that data using some default, unspecified JSON indentation setting.
*/
api.cgi.printJSON = proc(obj){
    print("%1$2J".applyFormat(obj))
}

/**
  Assumes obj is a legal value for the 'J' format specifier for Buffer.appendf()
  and returns that data's JSON string form, unspecified JSON indentation setting.
*/
api.cgi.toJSONString = proc(obj){
    return "%1$2J".applyFormat(obj)
}

/**
  Returns a variable from the GET, POST, or COOKIES
  data, in that order, or default if none of those
  sets contain the given key.
*/
api.cgi.getVar = proc(name, default = undefined){
    const R = this.request
    var rc = default
    if(R.GET && R.GET.hasOwnProperty(name)){
        rc = R.GET.(name)
        //CGI.setCookie('limit', resultLimit)
    }else if(R.POST && R.POST.hasOwnProperty(name)){
        rc = R.POST.(name)
    }else if(R.COOKIES && R.COOKIES.hasOwnProperty(name)){
        rc = R.COOKIES.(name)
    }
    return rc
}

api.cgi.getCookie = proc(name){
    const c = this.request.COOKIES
    return (c && c.hasOwnProperty(name)) ? c.(name) : undefined
}

/**
  Returns an app-specific session object, for storing _small amounts_
  of persistent data. The session is submitted as a single JSON-encoded
  cookie, so the data should be small.

  The session is loaded or initialized the first time this is called,
  and each time it is called, the session's 'lifetime' property is
  updated.
*/
api.cgi.getSession = proc(){
    var s = argv.callee.session
    if(!s){
        s = this.getCookie(this.config.sessionCookieKey)
        s && catch{
            const x = s
            s = null
            s = api.json.parse(x)
        }
        (s inherits api.Exception) && (s=null)
        s || (s = object{
            sessionId: 1234,
            startTime: time()
        })
        s.startTime || (s.startTime = time())
        s.lifetime = time()-s.startTime
        s.visitCount = 1 + (+s.visitCount)
        argv.callee.session = s
    }
    return s
}

/**
  Don't use this - it turns out that each sub-path sets its own
  cookie, no matter what path we tell it to use.

  Encodes api.cgi.getSession() to JSON and sets it as the
  cookie named by api.cgi.config.sessionCookieKey.
*/
api.cgi.savePathSession = proc(){
    var s = this.getSession()
    this.setCookie(this.config.sessionCookieKey, object{
      path: '/', // this.config.cookiePath,
      value:"%1$J".applyFormat(s)
    })
}