Пример #1
0
char *test_tst_search_exact()
{
    // tst returns the last one inserted
    void *res = tst_search(node, bdata(test1), blength(test1));
    mu_assert(res == valueA, "Got the wrong value back, should get A not B.");

    // tst does not find if not exact
    res = tst_search(node, "TESTNO", strlen("TESTNO"));
    mu_assert(res == NULL, "Should not find anything.");

    return NULL;
}
Пример #2
0
/**
 * call-seq:
 *    uc.resolve("/someuri") -> "/someuri", "", handler
 *    uc.resolve("/someuri/pathinfo") -> "/someuri", "/pathinfo", handler
 *    uc.resolve("/notfound/orhere") -> nil, nil, nil
 *    uc.resolve("/") -> "/", "/", handler  # if uc.register("/", handler)
 *    uc.resolve("/path/from/root") -> "/", "/path/from/root", handler  # if uc.register("/", handler) 
 * 
 * Attempts to resolve either the whole URI or at the longest prefix, returning
 * the prefix (as script_info), path (as path_info), and registered handler
 * (usually an HttpHandler).  If it doesn't find a handler registered at the longest
 * match then it returns nil,nil,nil.
 *
 * Because the resolver uses a trie you are able to register a handler at *any* character
 * in the URI and it will be handled as long as it's the longest prefix.  So, if you 
 * registered handler #1 at "/something/lik", and #2 at "/something/like/that", then a
 * a search for "/something/like" would give you #1.  A search for "/something/like/that/too"
 * would give you #2.
 * 
 * This is very powerful since it means you can also attach handlers to parts of the ; 
 * (semi-colon) separated path params, any part of the path, use off chars, anything really.
 * It also means that it's very efficient to do this only taking as long as the URI has
 * characters.
 *
 * A slight modification to the CGI 1.2 standard is given for handlers registered to "/".
 * CGI expects all CGI scripts to be at some script path, so it doesn't really say anything
 * about a script that handles the root.  To make this work, the resolver will detect that
 * the requested handler is at "/", and return that for script_name, and then simply return
 * the full URI back as path_info.
 *
 * It expects strings with no embedded '\0' characters.  Don't try other string-like stuff yet.
 */
VALUE URIClassifier_resolve(VALUE self, VALUE uri)
{
  void *handler = NULL;
  int pref_len = 0;
  struct tst *tst = NULL;
  VALUE result;
  unsigned char *uri_str = NULL;

  DATA_GET(self, struct tst, tst);
  uri_str = (unsigned char *)StringValueCStr(uri);

  handler = tst_search(uri_str, tst, &pref_len);

  result = rb_ary_new();

  if(handler) {
    rb_ary_push(result, rb_str_substr (uri, 0, pref_len));
    if(pref_len == 1 && uri_str[0] == '/') {
      rb_ary_push(result, uri);
    } else {
      rb_ary_push(result, rb_str_substr(uri, pref_len, RSTRING(uri)->len));
    }

    rb_ary_push(result, (VALUE)handler);
  } else {
    rb_ary_push(result, Qnil);
    rb_ary_push(result, Qnil);
    rb_ary_push(result, Qnil);
  }

  return result;
}
Пример #3
0
void import(Module *state, array_t *params)
{
    size_t length = 0;
    CORD input = NULL;
    Module *target = NULL;
    char in_file[MAX_LIB_NAME];

    ARITY(import, 2);
    REQUIRES(import, 0, STR);
    REQUIRES(import, 1, STR);

    if(tst_search(state->imports, ARG(1)->data)) {
        // already loaded so just skip it
        return;
    }

    if(Token_copy(ARG(0), in_file, MAX_LIB_NAME, TK_STR) == -1) {
        die(state, "requested module name %s is too long, must be less than %d.",
                in_file, MAX_LIB_NAME);
    }

    input = mmap_file(in_file, &length);
    assert(input && "Failed to open the file you requested.");

    // compile the other file using the code size specified by the parent
    target = Module_create(in_file, state->max_code_size);

    // have to add it here to prevent recursive loads from going in a loop
    state->imports = tst_insert(state->imports, ARG(1)->start, ARG(1)->len, target);
    assert(state->imports && "Error importing into the parent namespace.");

    if(!Module_compile(target, input, length)) {
        die(target, "error parsing imported module %s.", in_file);
    }
}
Пример #4
0
int Handler_load(tst_t *settings, tst_t *params)
{
    const char *send_spec = AST_str(settings, params, "send_spec", VAL_QSTRING);
    char *sql = NULL;
    
    sql = sqlite3_mprintf(bdata(&HANDLER_SQL),
            send_spec,
            AST_str(settings, params, "send_ident", VAL_QSTRING),
            AST_str(settings, params, "recv_spec", VAL_QSTRING),
            AST_str(settings, params, "recv_ident", VAL_QSTRING));

    int rc = DB_exec(sql, NULL, NULL);
    check(rc == 0, "Failed to load Handler: %s", send_spec);

    if(tst_search(params, bdata(&RAW_PAYLOAD), blength(&RAW_PAYLOAD))) {
        const char *raw_payload = AST_str(settings, params, "raw_payload", VAL_NUMBER);
        if(raw_payload && raw_payload[0] == '1') {
            DB_exec(bdata(&HANDLER_RAW_SQL), NULL, NULL);
        }
    }

    sqlite3_free(sql);
    return DB_lastid();

error:

    if(sql) sqlite3_free(sql);
    return -1;
}
Пример #5
0
int MIME_add_type(const char *ext, const char *type)
{
    if(!MAX_EXT_LEN) {
        MAX_EXT_LEN = Setting_get_int("limits.mime_ext_len", 128);
        log_info("MAX limits.mime_ext_len=%d", MAX_EXT_LEN);
    }

    bstring ext_rev = bfromcstr(ext);
    bReverse(ext_rev);
    bstring type_str = bfromcstr(type);

    check(blength(ext_rev) > 0, "No zero length MIME extensions allowed: %s:%s", ext, type);
    check(blength(type_str) > 0, "No zero length MIME types allowed: %s:%s", ext, type);
    check(ext[0] == '.', "Extensions must start with a . '%s:%s'", ext, type);

    check(blength(ext_rev) < MAX_EXT_LEN, "MIME extension %s:%s is longer than %d MAX (it's %d)", ext, type, MAX_EXT_LEN, blength(ext_rev));

    check(!tst_search(MIME_MAP, bdata(ext_rev), blength(ext_rev)), 
            "MIME extension %s already exists, can't add %s:%s",
            ext, ext, type);

    MIME_MAP = tst_insert(MIME_MAP, bdata(ext_rev), blength(ext_rev), type_str);

    bdestroy(ext_rev);

    return 0;
error:
    bdestroy(ext_rev);
    bdestroy(type_str);
    return -1;
}
Пример #6
0
int AST_walk_hash(tst_t *settings, Value *data, ast_hash_walk_cb cb)
{
    struct ASTScanData scan = {.settings = settings, .cb = cb, .error = 0};
    tst_traverse(data->as.hash, ast_hash_traverse_cb, &scan);
    return scan.error;
}


Value *AST_get(tst_t *settings, tst_t *fr, bstring name, ValueType type)
{
    Pair *pair = tst_search(fr, bdata(name), blength(name));
    check_debug(pair, "Couldn't find variable %s of type %s", bdata(name), Value_type_name(type));

    Value *val = Pair_value(pair);

    if(Value_is(val, REF)) {
        val = Value_resolve(settings, val);
        check(val, "Couldn't find variable %s of type %s",
            bdata(name), Value_type_name(type));
    }

    check(val->type == type, "Invalid type for %s, should be %s not %s",
            bdata(name), Value_type_name(type), Value_type_name(val->type));

    return val;

error:
    return NULL;
}
Пример #7
0
void Action_dependency_assign(void *value, void *data)
{
    Action *action = (Action *)value;
    Action *target = NULL;
    tst_t *targets = (tst_t *)data;
    int i = 0;

    if(!action->depends) return;

    debug("Processed %s action depending on: %s", bdata(action->name), bdata(action->depends));

    if(action->depends) {
        struct bstrList *dep_list = bsplit(action->depends, ' ');

        for(i = 0; i < dep_list->qty; i++) {
            bstring dep = dep_list->entry[i];

            target = (Action *)tst_search(targets, bdata(dep), blength(dep));

            if(target) {
                Action_depends(action, target);
            } else {
                log_err("Could not find dependency %s has on %s.",
                        bdata(action->name), bdata(dep));
            }
        }

        bstrListDestroy(dep_list);
    }
}
Пример #8
0
char *co_cmd_description(char *name, int mask) {
  co_cmd_t *cmd = tst_search(commands, name, strlen(name));
  CHECK((cmd != NULL), "No such command!");
  CHECK((cmd->mask & mask) == mask, "Permissions denied for command %s from this access type.", name);
  return cmd->description;
error:
  return 0;
}
Пример #9
0
int Setting_get_int(const char *key, int def)
{
    bstring value = tst_search(SETTINGS_MAP, key, strlen(key));

    if(value) {
        return atoi((const char *)value->data);
    } else {
        return def;
    }
}
Пример #10
0
char *co_cmd_exec(char *name, char *argv[], int argc, int mask) {
  DEBUG("Command name: %s", name);
  co_cmd_t *cmd = tst_search(commands, name, strlen(name));
  CHECK((cmd != NULL), "No such command!");
  CHECK((cmd->mask & mask) == mask, "Permissions denied for command %s from this access type.", name);
  DEBUG("Executing command %s", name);
  return cmd->exec((void *)cmd, argv, argc);
error:
  return NULL;
}
Пример #11
0
Value *Value_resolve(tst_t *settings, Value *val)
{
    if(Value_is(val, REF)) {
        Pair *pair = tst_search(settings, bdata(val->as.ref->data), blength(val->as.ref->data));
        check(pair != NULL, "Couldn't find variable named: %s", bdata(val->as.ref->data));
        return Pair_value(pair);
    } else {
        return val;
    }

error:
    return NULL;
}
Пример #12
0
int AST_walk(tst_t *settings, ast_walk_cb cb)
{
    Pair *n = tst_search(settings, bdata(&DEFAULT_ROOT), blength(&DEFAULT_ROOT));
    check(n, "You didn't set a %s variable to say what servers you want.", 
            bdata(&DEFAULT_ROOT));

    Value *val = Pair_value(n);
    check(val->type == VAL_LIST, "servers variable should be a list of server configs to load.");

    return AST_walk_list(settings, val->as.list, cb);

error:
    return -1;
}
Пример #13
0
int Server_load(tst_t *settings, Value *val)
{
    CONFIRM_TYPE("Server");
    Class *cls = val->as.cls;
    int rc = 0;
    char *sql = NULL;
    struct tagbstring HOSTS_VAR = bsStatic("hosts");
    const char *bind_addr = NULL;

    if(tst_search(cls->params, bdata(&BIND_ADDR), blength(&BIND_ADDR))) {
        bind_addr = AST_str(settings, cls->params, "bind_addr", VAL_QSTRING);
    } else {
        bind_addr = "0.0.0.0";
    }

    sql = sqlite3_mprintf(bdata(&SERVER_SQL),
            AST_str(settings, cls->params, "uuid", VAL_QSTRING),
            AST_str(settings, cls->params, "access_log", VAL_QSTRING),
            AST_str(settings, cls->params, "error_log", VAL_QSTRING),
            AST_str(settings, cls->params, "pid_file", VAL_QSTRING),
            AST_str(settings, cls->params, "chroot", VAL_QSTRING),
            AST_str(settings, cls->params, "default_host", VAL_QSTRING),
            AST_str(settings, cls->params, "name", VAL_QSTRING),
            bind_addr,
            AST_str(settings, cls->params, "port", VAL_NUMBER));

    rc = DB_exec(sql, NULL, NULL);
    check(rc == 0, "Failed to exec SQL: %s", sql);

    cls->id = SERVER_ID = DB_lastid();

    Value *hosts = AST_get(settings, cls->params, &HOSTS_VAR, VAL_LIST);
    check(hosts != NULL, "Could not find Server.hosts setting in host %s:%s", 
            AST_str(settings, cls->params, "uuid", VAL_QSTRING),
            AST_str(settings, cls->params, "name", VAL_QSTRING));

    AST_walk_list(settings, hosts->as.list, Host_load);


    sqlite3_free(sql);
    return 0;

error:
    if(sql) sqlite3_free(sql);
    return -1;
}
Пример #14
0
void*
dict_get(dict* d, char *key)
{
#ifdef TSTC
    dict_entry *e = 0;
    int r = tstc_find(d->dict, key, (void*)&e);
    if (r)
    {
	    return e->v;
    }
    return e;
#elif defined (HASHMAP)
    return hash_map_find(d->dict, key, strlen(key));
#else
    return (void*) tst_search(d->dict, key);
#endif
}
Пример #15
0
void run_function(Module *state, const char *named) 
{
    Function *func = NULL;

    func = tst_search(state->functions, named, strlen(named));

    if(!func) {
        printf("Undefined function: '%s'\n", named);
    } else {
        if(list_isempty(func->params)) {
            printf("Sorry, this function takes parameters so it's not supported to call it yet.\n");
            return;
        }

        switch(func->type) {
            case OpType_v:
                printf(">>\n"); func->fp.vptr(); break;
            case OpType_c:
                printf(">> %c\n", func->fp.cptr()); break;
            case OpType_uc:
                printf(">> %c\n", func->fp.ucptr()); break;
            case OpType_s:
                printf(">>  %i\n", func->fp.sptr()); break;
            case OpType_us:
                printf(">>  %i\n", func->fp.usptr()); break;
            case OpType_i:
                printf(">>  %d\n", func->fp.iptr()); break;
            case OpType_ui:
                printf(">>  %u\n", func->fp.uiptr()); break;
            case OpType_l:
                printf(">>  %ld\n", func->fp.lptr()); break;
            case OpType_ul:
                printf(">>  %lu\n", func->fp.ulptr()); break;
            case OpType_p:
                printf(">>  %p\n", func->fp.pptr()); break;
            case OpType_f:
                printf(">>  %f\n", func->fp.fptr()); break;
            case OpType_d:
                printf(">>  %f\n", func->fp.dptr()); break;
        }
    }
}
Пример #16
0
int Setting_add(const char *key, const char *value)
{
    bstring key_str = bfromcstr(key);
    bstring value_str = bfromcstr(value);

    check(!tst_search(SETTINGS_MAP, bdata(key_str), blength(value_str)), 
            "Setting key %s already exists, can't add %s:%s",
            key, key, value);

    SETTINGS_MAP = tst_insert(SETTINGS_MAP, bdata(key_str),
            blength(key_str), value_str);

    bdestroy(key_str);

    return 0;
error:
    bdestroy(key_str);
    bdestroy(value_str);
    return -1;
}
Пример #17
0
/** Finds a FUNCTION that is in a library which has been loaded. */
void *Library_search(Module *state, Token *module, Token *name)
{
    Library *lib = tst_search(state->libraries, module->start, module->len);
    if(lib) {
        // found it try to find the method
        char fname[MAX_LIB_NAME];
        if(Token_copy(name, fname, MAX_LIB_NAME, TK_IDENT) == -1) {
            die(state, "Library file name %.*s is too long.", name->len, name->start);
            return NULL;
        }
        void *ptr = dlsym(lib->handle, fname);

        if(ptr) {
            return ptr;
        } else {
            die(state, "module %.*s, error loading library '%.*s': %s.", 
                    module->len, module->start, name->len, name->start, dlerror());
            return NULL;
        }
    } else {
        // not loaded yet, error
        return NULL;
    }
}
Пример #18
0
bstring Setting_get_str(const char *key, bstring def)
{
    bstring value = tst_search(SETTINGS_MAP, key, strlen(key));

    return value == NULL ? def : value;
}