• Jump To … +
    server.coffee src/actionknob.coffee src/autosem.coffee src/bitbucket_kba.coffee src/browserlog.coffee src/datareduction.coffee src/dci.coffee src/dciknob.coffee src/deeseeeye.coffee src/dnd.coffee src/doof.coffee src/formurla-mngr.coffee src/fractalpanel.coffee src/fractalpanel_test.coffee src/front.coffee src/ingestor.coffee src/kbabitbucket.coffee src/knobctrl.coffee src/lib_test.coffee src/nanoclock.coffee src/noodb.coffee src/noodbabstract.coffee src/noodbbrowser.coffee src/noodbbrowser_test.coffee src/noodbsec.coffee src/noorauth.coffee src/noorplugin.coffee src/noorquery.coffee src/noorvm.coffee src/noorwrite.coffee src/quadparser.coffee src/quadparsern3.coffee src/rbac.coffee src/reactor.coffee src/rebase.coffee src/rsrcidx.coffee src/sandboxactions.coffee src/screen_ctx.coffee src/spogi.coffee src/tabular_widget.coffee src/visctrl.coffee src/voicesknob.coffee src/whowhen.coffee src/xsd2native.coffee
  • noorvm.coffee

  • ¶
    try
      N3Util = require('n3').Util
    catch e
  • ¶

    console.log(“expost n3 to browser”)

      N3Util = {}
    
    class HardenedNooDB
  • ¶

    HardenedNooDB is a facade over NooDB so the underlying noodb need not be exposed

      constructor: (noodb) ->
        @get_new_id = () -> noodb.synthetic_key_factory_next()
        @uniform_echo = (a) -> return a
        @make_new_kb = (kbName) ->
          noodb.socket.emit("make_new_kb", {kbName: kbName})
    
    NoorVM =
      func_src_predicate: 'http://nooron.com/_/NooronAppArchitecture.ttl#FNC'
      default_prefix: 'http://nooron.com/_/NooronAppArchitecture.ttl#'
  • ¶

    https://regex101.com/#javascript

      func_args_and_body_regex: /^\s*function\(([^\)]*)\)\s*{([\n\s\r\S]*)}\s*$/   # /m means multiline
      make_vm: (settings, self, caching) ->
        self ?= {}
        settings ?= {}
        settings.prefix ?= @default_prefix
        settings.caching ?= false
        settings.expose_noodb_safely ?= true
        settings.expose_n3util ?= true
  • ¶

    https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy

        noodb = @
        if settings.expose_noodb_safely
          @facade = new HardenedNooDB(noodb)
          self.noodb = @facade # FIXME can this be eliminated?
        if settings.expose_n3util
          self.n3util = N3Util
        self._newline = String.fromCharCode(10)
        announce = (msg, more) ->
          console.log(msg, more)
          throw new Error(msg + "()")
          return null
        notImplemented = ->
  • ¶

    sadly this does not work

          console.log("NAME", arguments.callee.name)
          return null
        make_handler = (settings, self) ->
          get: (target, name) ->
            noodb.log.info("Proxy_handler.get(target, '#{name}')")
            if not (name of target)
  • ¶

    console.log(“get(target,’#{name}’)”)

              full_name = settings.prefix + name
              err = null
              try
                retval = noodb.find_func(name)
              catch e
                err = 3
  • ¶

    noodb.log.error(e)

                retval = noodb.find_func(full_name)
              if not retval
                noodb.log.error("failed to find_func('#{name}') or find_func('#{full_name}')")
                if err
                  throw err
              if settings.caching
                target[name] = retval
              return retval
            return target[name]
  • ¶

    get: -> announce “get”, arguments

          someRandomFunction: notImplemented # TODO it wold be great if this worked
          getPrototypeOf: ->
            announce("getPrototypeOf", arguments)
          setPrototypeOf: ->
            announce("setPrototypeOf", arguments)
          isExtensible: ->
            announce("isExtensible", arguments)
          preventExtensions: ->
            announce("preventExtensions", arguments)
          getOwnPropertyDescriptor: ->
            announce("getOwnPropertyDescriptor", arguments)
          defineProperty: ->
            announce("defineProperty", arguments)
          has: ->
            announce("has")
          set: ->
            announce("set")
          deleteProperty: ->
            announce("deleteProperty")
          ownKeys: ->
            announce("ownKeys")
          apply: ->
            announce("apply")
          construct: ->
            announce("construct")
        return @new_Proxy(self, make_handler(settings, self))
    
      new_Proxy: (target, handler) ->
        if not @Proxy?
          if window? and window.Proxy?
            @Proxy = window.Proxy
          else
            try
              @Proxy = require('harmony-proxy')
            catch e
  • ¶

    https://github.com/GoogleChrome/proxy-polyfill

              throw new Error("NoorVM not supported in this context: no Proxy! see 'proxy-polyfill'")
        return new @Proxy(target, handler)
    
      apply_by_name: (func_name, vm, args) ->
  • ¶

    Call a function by name with a list of arguments; return a value. TODO(smurp) Shawn should figure out which version when he’s smarter

    @method call_by_name @param {String} func_name @param {Object} vm The execution context in which the function will be applied. @param {Array} args An array of arguments to the function @return {Object} The return value of the named function.

        @log.info("apply_by_name('#{func_name}',VM,#{args})")
        if typeof func_name is 'undefined'
          throw new Error('VM says apply_by_name() func_name should not be undefined')
        func = vm[func_name]
  • ¶

    if not func throw new Error(“could not find function #{func_name}”)

        @log.debug "func",func
        return func.apply(vm, args)
    
      get_facade_func: (func_name, vm, args) ->
        return @facade? and @facade[func_name] # facade might be disabled
    
      find_func: (func_name) ->
  • ¶

    A function body lives in the KB as an string literal on a predicate like nrn:ADD naa:FNC “””function(p1, p2){return p1 + p2;}””” . So @find_func(‘nrn:ADD’) ==> “function(p1,p2){return p1 + p2;}” @method find_func @param {String} func_name @return {String} Returns the javascript source for the named function or false

        func = @get_facade_func(func_name)
        if func
          return func
        func_src = @get_func_src(func_name) #or ""
        @log.info("func_src:", func_src, typeof func_src , ", func_src[0]:", func_src)
        func_a_and_b = @parse_func_args_and_body(func_src)
        @log.info("func_a_and_b:", func_a_and_b)
        if func_a_and_b
          return @compile_func(func_a_and_b)
        else
          return false
    
      get_func_src: (func_name) ->
        @warn_once("get_func_src() always gets the latest version THIS IS A SECURITY HOLE")
        @log.info("get_func_src(#{func_name})")
        spogi = @query([{s: func_name}, {p: @func_src_predicate}], {which: "last"})
        if spogi
          retval = spogi.o.key()
          return retval
        else
          throw new Error("VM says function #{func_name} can not be found by @get_func_src()")
    
    
      parse_func_args_and_body: (func_src) ->
        m = func_src.match(@func_args_and_body_regex)
        @log.debug("parse_func_args_and_body()")
        if m
          retval =
            args: (t.trim() for t in m[1].split(',')) # remove surrounding spaces
            body: m[2]
          while retval.args[0] is "" # drain [""] to []
            retval.args.pop()
          return retval
        else
          throw new Error("args and body not found in #{func_src}")
          return false
    
      compile_func: (func_args_and_body) ->
  • ¶

    Return a Function specified by args and body on func_args_and_body It is assumed that func_src is already safe because it has been compiled on the server side by a trusted method. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function

    @method compile_func @param func_args_and_body A javascript function equivalent to: “function(p1,p2){return p1 + p2;}” but in the form: args: [‘p1’, ‘p2’] body: ‘return p1 + p2;’ @return {Function} The compiled version of the function.

        args = func_args_and_body.args or []
        body = func_args_and_body.body or "return;"
        @log.debug("func_args_and_body", func_args_and_body)
        return new Function(args, body)
    
    (exports ? this).NoorVM = NoorVM