Пример #1
0
static int
rest_get_noit_config(noit_http_rest_closure_t *restc,
                     int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  char *xml = NULL;

  if(npats != 0) {
    noit_http_response_server_error(ctx, "text/xml");
    noit_http_response_end(ctx);
    return 0;
  }

  xml = ingestor->get_noit_config(restc->remote_cn);

  if(xml == NULL) {
    char buff[1024];
    snprintf(buff, sizeof(buff), "<error><remote_cn>%s</remote_cn>"
                                 "<row_count>%d</row_count></error>\n",
             restc->remote_cn, 0);
    noit_http_response_append(ctx, buff, strlen(buff));
    noit_http_response_not_found(ctx, "text/xml");
  }
  else {
    noit_http_response_append(ctx, xml, strlen(xml));
    noit_http_response_ok(ctx, "text/xml");
  }

  if(xml) free(xml);
  noit_http_response_end(ctx);
  return 0;
}
Пример #2
0
static int rest_show_feed(noit_http_rest_closure_t *restc,
                          int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  const char *err = "unknown error";
  const char *jpath_with_sub;
  char jlogpath[PATH_MAX], *cp, **subs = NULL;
  int nsubs, i;
  noit_log_stream_t feed;
  jlog_ctx *jctx = NULL;
  xmlDocPtr doc = NULL;
  xmlNodePtr root = NULL, subnodes;

  feed = noit_log_stream_find("feed");
  if(!feed) { err = "cannot find feed"; goto error; }

  jpath_with_sub = noit_log_stream_get_path(feed);
  strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath));
  cp = strchr(jlogpath, '(');
  if(cp) *cp = '\0';

  jctx = jlog_new(jlogpath);
  if((nsubs = jlog_ctx_list_subscribers(jctx, &subs)) == -1) {
    err = jlog_ctx_err_string(jctx);
    goto error;
  }

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"feed", NULL);
  xmlDocSetRootElement(doc, root);

  subnodes = xmlNewNode(NULL, (xmlChar *)"subscribers");
  for(i=0; i<nsubs; i++) {
    xmlNewChild(subnodes, NULL, (xmlChar *)"subscriber", (xmlChar *)subs[i]);
  }
  xmlAddChild(root, subnodes);

  noit_http_response_ok(restc->http_ctx, "text/xml");
  noit_http_response_xml(restc->http_ctx, doc);
  noit_http_response_end(restc->http_ctx);
  if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs);
  xmlFreeDoc(doc);
  jlog_ctx_close(jctx);
  return 0;

 error:
  if(doc) xmlFreeDoc(doc);
  if(subs) jlog_ctx_list_subscribers_dispose(jctx, subs);
  noit_http_response_server_error(ctx, "text/plain");
  noit_http_response_append(ctx, err, strlen(err));
  noit_http_response_end(ctx);
  if(jctx) jlog_ctx_close(jctx);
  return 0;
}
Пример #3
0
int
noit_rest_request_dispatcher(noit_http_session_ctx *ctx) {
  noit_http_rest_closure_t *restc = noit_http_session_dispatcher_closure(ctx);
  rest_request_handler handler = restc->fastpath;
  if(!handler) handler = noit_http_get_handler(restc);
  if(handler) {
    void *old_closure = restc, *new_closure;
    noit_http_response *res = noit_http_session_response(ctx);
    int rv;
    rv = handler(restc, restc->nparams, restc->params);
    /* If the request is closed, we need to cleanup.  However
     * if the dispatch closure has changed, the callee has done
     * something (presumably freeing the restc in the process)
     * and it would be unsafe for us to free it as well.
     */
    new_closure = noit_http_session_dispatcher_closure(ctx);
    if(old_closure == new_closure &&
       noit_http_response_closed(res)) noit_http_rest_clean_request(restc);
    return rv;
  }
  noit_http_response_status_set(ctx, 404, "NOT FOUND");
  noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED);
  noit_http_rest_clean_request(restc);
  noit_http_response_end(ctx);
  return 0;
}
int
stratcon_realtime_http_postresolve(eventer_t e, int mask, void *closure,
                                   struct timeval *now) {
  noit_http_session_ctx *ctx = closure;
  realtime_context *rc = noit_http_session_dispatcher_closure(ctx);
  struct realtime_tracker *node;

  for(node = rc->checklist; node; node = node->next) {
    if(node->noit) {
      realtime_recv_ctx_t *rrctx;
      rrctx = calloc(1, sizeof(*rrctx));
      rrctx->ctx = ctx;
      rrctx->rt = node;
      stratcon_streamer_connection(NULL, node->noit, "noit",
                                   stratcon_realtime_recv_handler,
                                   NULL, rrctx,
                                   free_realtime_recv_ctx);
    }
    else
      noit_http_session_ref_dec(ctx);
  }
  if(noit_http_session_ref_cnt(ctx) == 1) {
    noit_http_response_end(ctx);
    clear_realtime_context(rc);
    noit_http_session_trigger(ctx, EVENTER_WRITE);
  }
  return 0;
}
Пример #5
0
int
noit_rest_eventer_logs(noit_http_rest_closure_t *restc, int n, char **p) {
  char *endptr = NULL;
  const char *since_s, *last_s;
  const char *jsonstr;
  char errbuf[128];
  unsigned long long since;
  int last = 0;
  struct json_object *doc;
  noit_log_stream_t ls;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);
  since_s = noit_http_request_querystring(req, "since");
  if(since_s) since = strtoull(since_s, &endptr, 10);
  last_s = noit_http_request_querystring(req, "last");
  if(last_s) last = atoi(last_s);

  assert(n==1);
  ls = noit_log_stream_find(p[0]);
  if(!ls || strcmp(noit_log_stream_get_type(ls),"memory"))
    goto not_found;

  doc = json_object_new_array();
  if(endptr != since_s)
    noit_log_memory_lines_since(ls, since, json_spit_log, doc);
  else
    noit_log_memory_lines(ls, last, json_spit_log, doc);

  noit_http_response_ok(restc->http_ctx, "application/json");
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
 not_found:
  doc = json_object_new_object();
  snprintf(errbuf, sizeof(errbuf), "log '%s' not found", p[0]);
  json_object_object_add(doc, "error", json_object_new_string(errbuf));
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_not_found(restc->http_ctx, "application/json");
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
}
Пример #6
0
static int
noit_http_rest_permission_denied(noit_http_rest_closure_t *restc,
                                 int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  noit_http_response_standard(ctx, 403, "DENIED", "text/xml");
  noit_http_response_end(ctx);
  return 0;
}
Пример #7
0
static int rest_delete_feed(noit_http_rest_closure_t *restc,
                            int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  const char *err = "unknown error";
  const char *jpath_with_sub;
  char jlogpath[PATH_MAX], *cp;
  int rv;
  noit_log_stream_t feed;
  jlog_ctx *jctx;

  feed = noit_log_stream_find("feed");
  if(!feed) { err = "cannot find feed"; goto error; }

  jpath_with_sub = noit_log_stream_get_path(feed);
  strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath));
  cp = strchr(jlogpath, '(');
  if(cp) *cp = '\0';

  jctx = jlog_new(jlogpath);
  rv = jlog_ctx_remove_subscriber(jctx, pats[0]);
  jlog_ctx_close(jctx);
  if(rv < 0) {
    err = jlog_ctx_err_string(jctx);
    goto error;
  }

  /* removed or note, we should do a sweeping cleanup */
  jlog_clean(jlogpath);

  if(rv == 0) {
    noit_http_response_not_found(ctx, "text/plain");
    noit_http_response_end(ctx);
    return 0;
  }

  noit_http_response_standard(ctx, 204, "OK", "text/plain");
  noit_http_response_end(ctx);
  return 0;

 error:
  noit_http_response_server_error(ctx, "text/plain");
  noit_http_response_append(ctx, err, strlen(err));
  noit_http_response_end(ctx);
  return 0;
}
Пример #8
0
static int
rest_test_check_err(noit_http_rest_closure_t *restc,
                    int npats, char **pats) {
  noit_http_response *res = noit_http_session_response(restc->http_ctx);
  noit_skiplist_remove(&in_progress, restc,
                       (noit_freefunc_t)rest_test_check_result);
  if(noit_http_response_complete(res) != noit_true) {
    noit_http_response_standard(restc->http_ctx, 500, "ERROR", "text/html");
    noit_http_response_end(restc->http_ctx);
  }
  return 0;
}
static int
noit_capabilities_rest(noit_http_rest_closure_t *restc, int n, char **p) {
  noit_capsvc_closure_t cl = { 0 };
  const char *mtype = "application/xml";
  if(n > 0 && !strcmp(p[0], ".json")) {
    noit_capabilities_tobuff_json(&cl, NULL);
    mtype = "application/json";
  }
  else noit_capabilities_tobuff(&cl, NULL);
  if(!cl.buff) goto error;
  noit_http_response_ok(restc->http_ctx, mtype);
  noit_http_response_append(restc->http_ctx, cl.buff, cl.towrite);
  noit_http_response_end(restc->http_ctx);
  free(cl.buff);
  return 0;

 error:
  noit_http_response_server_error(restc->http_ctx, "text/html");
  noit_http_response_end(restc->http_ctx);
  return 0;
}
Пример #10
0
static int
rest_delete_filter(noit_http_rest_closure_t *restc,
                   int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlNodePtr node;
  char xpath[1024];
  int error_code = 500;

  if(npats != 2) goto error;

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);
  node = noit_conf_get_section(NULL, xpath);
  if(!node) goto not_found;
  if(noit_filter_remove(node) == 0) goto not_found;
  CONF_REMOVE(node);
  xmlUnlinkNode(node);
  xmlFreeNode(node);

  if(noit_conf_write_file(NULL) != 0)
    noitL(noit_error, "local config write failed\n");
  noit_conf_mark_changed();
  noit_http_response_ok(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  return 0;
}
Пример #11
0
static int
rest_show_filter(noit_http_rest_closure_t *restc,
                 int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlDocPtr doc = NULL;
  xmlNodePtr node, root;
  char xpath[1024];
  int error_code = 500;

  if(npats != 2) goto error;

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);

  node = noit_conf_get_section(NULL, xpath);
  if(!node) goto not_found;

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlCopyNode(node, 1);
  xmlDocSetRootElement(doc, root);
  noit_http_response_ok(ctx, "text/xml");
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
Пример #12
0
static void
free_realtime_recv_ctx(void *vctx) {
  realtime_recv_ctx_t *rrctx = vctx;
  noit_http_session_ctx *ctx = rrctx->ctx;
  realtime_context *rc = ctx->dispatcher_closure;

  if(noit_atomic_dec32(&ctx->ref_cnt) == 1) {
    noit_http_response_end(ctx);
    clear_realtime_context(rc);
    if(ctx->conn.e) eventer_trigger(ctx->conn.e, EVENTER_WRITE | EVENTER_EXCEPTION);
  }
  free(rrctx);
}
static void
free_realtime_recv_ctx(void *vctx) {
  realtime_recv_ctx_t *rrctx = vctx;
  noit_http_session_ctx *ctx = rrctx->ctx;
  realtime_context *rc = noit_http_session_dispatcher_closure(ctx);

  if(noit_http_session_ref_dec(ctx) == 1) {
    noit_http_response_end(ctx);
    clear_realtime_context(rc);
    noit_http_session_trigger(ctx, EVENTER_WRITE | EVENTER_EXCEPTION);
  }
  free(rrctx);
}
Пример #14
0
static int
rest_test_check(noit_http_rest_closure_t *restc,
                int npats, char **pats) {
  noit_check_t *tcheck;
  noit_http_session_ctx *ctx = restc->http_ctx;
  int mask, complete = 0;
  int error_code = 500;
  const char *error = "internal error";
  xmlDocPtr indoc, doc = NULL;
  xmlNodePtr attr, config, root;

  indoc = rest_get_xml_upload(restc, &mask, &complete);
  if(!complete) return mask;
  if(indoc == NULL) {
    error = "xml parse error";
    goto error;
  }
  if(!noit_validate_check_rest_post(indoc, &attr, &config, &error))
    goto error;

  tcheck = noit_fire_check(attr, config, &error);
  if(tcheck) {
    /* push the check and the context into a queue to complete on */
    struct check_test_closure *cl;
    cl = calloc(1, sizeof(*cl));
    cl->check = tcheck;
    cl->restc = restc;
    noit_skiplist_insert(&in_progress, cl);
    check_test_schedule_sweeper();
    if(restc->call_closure_free)
      restc->call_closure_free(restc->call_closure);
    restc->call_closure_free = NULL;
    restc->call_closure = NULL;
    restc->fastpath = rest_test_check_err;
    goto cleanup;
  }

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/xml");
  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
  xmlDocSetRootElement(doc, root);
  xmlNodeAddContent(root, (xmlChar *)error);
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
Пример #15
0
static int
noit_rest_eventer_jobq(noit_http_rest_closure_t *restc, int n, char **p) {
  const char *jsonstr;
  struct json_object *doc;
  doc = json_object_new_object();
  eventer_jobq_process_each(json_spit_jobq, doc);

  noit_http_response_ok(restc->http_ctx, "application/json");
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
}
Пример #16
0
static int
noit_rest_eventer_sockets(noit_http_rest_closure_t *restc, int n, char **p) {
  const char *jsonstr;
  struct json_object *doc;
  doc = json_object_new_array();
  eventer_foreach_fdevent(json_spit_event, doc);

  noit_http_response_ok(restc->http_ctx, "application/json");
  jsonstr = json_object_to_json_string(doc);
  noit_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr));
  noit_http_response_append(restc->http_ctx, "\n", 1);
  json_object_put(doc);
  noit_http_response_end(restc->http_ctx);
  return 0;
}
Пример #17
0
static int
rest_cull_filter(noit_http_rest_closure_t *restc,
                 int npats, char **pats) {
  int rv;
  char cnt_str[32];
  noit_http_session_ctx *ctx = restc->http_ctx;

  rv = noit_filtersets_cull_unused();
  if(rv > 0) noit_conf_mark_changed();
  snprintf(cnt_str, sizeof(cnt_str), "%d", rv);
  noit_http_response_ok(ctx, "text/html");
  noit_http_response_header_set(ctx, "X-Filters-Removed", cnt_str);
  noit_http_response_end(ctx);
  return 0;
}
Пример #18
0
static int
handoff_request_dispatcher(noit_http_session_ctx *ctx) {
  char *hello = "message:hello\r\n";
  if(the_one_and_only) {
    hello = "message:already connected\r\n";
    noit_http_response_server_error(ctx, "text/plain");
    noit_http_response_append(ctx, hello, strlen(hello));
    noit_http_response_end(ctx);
    return 0;
  }
  the_one_and_only = ctx;
  noit_http_response_status_set(ctx, 200, "OK");
  noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED);
  noit_http_response_header_set(ctx, "Content-Type", "text/plain");
  noit_http_response_append(ctx, hello, strlen(hello));
  noit_http_response_flush(ctx, noit_false);
  return EVENTER_EXCEPTION;
}
Пример #19
0
static void
rest_test_check_result(struct check_test_closure *cl) {
  xmlDocPtr doc = NULL;
  xmlNodePtr root, state;
  noit_http_session_ctx *ctx = cl->restc->http_ctx;

  noitL(nlerr, "Flushing check test result\n");

  if(cl->restc->call_closure_free)
    cl->restc->call_closure_free(cl->restc->call_closure);
  cl->restc->call_closure_free = NULL;
  cl->restc->call_closure = NULL;
  cl->restc->fastpath = NULL;

  if(ctx) {
    eventer_t conne = noit_http_connection_event(noit_http_session_connection(ctx));

    doc = xmlNewDoc((xmlChar *)"1.0");
    root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL);
    xmlDocSetRootElement(doc, root);
    state = noit_check_state_as_xml(cl->check);
    xmlAddChild(root, state);
    noit_http_response_ok(ctx, "text/xml");
    noit_http_response_xml(ctx, doc);
    noit_http_response_end(ctx);
  
    if(conne) {
      // The event already exists, why re-add it?  Did we want to update it?
      //eventer_add(conne);
      eventer_trigger(conne, EVENTER_READ | EVENTER_WRITE);
    }
  }

  noit_poller_free_check(cl->check);
  xmlFreeDoc(doc);
  free(cl);
}
Пример #20
0
int
noit_rest_simple_file_handler(noit_http_rest_closure_t *restc,
                              int npats, char **pats) {
  int drlen = 0;
  const char *document_root = NULL;
  const char *index_file = NULL;
  noit_http_session_ctx *ctx = restc->http_ctx;
  char file[PATH_MAX], rfile[PATH_MAX];
  struct stat st;
  int fd;
  void *contents = MAP_FAILED;

  if(npats != 1 ||
     !noit_hash_retr_str(restc->ac->config,
                         "document_root", strlen("document_root"),
                         &document_root)) {
    goto not_found;
  }
  if(!noit_hash_retr_str(restc->ac->config,
                         "index_file", strlen("index_file"),
                         &index_file)) {
    index_file = "index.html";
  }
  drlen = strlen(document_root);
  snprintf(file, sizeof(file), "%s/%s", document_root, pats[0]);
  if(file[strlen(file) - 1] == '/') {
    snprintf(file + strlen(file), sizeof(file) - strlen(file),
             "%s", index_file);
  }
  /* resolve */
  if(realpath(file, rfile) == NULL) goto not_found;
  /* restrict */
  if(strncmp(rfile, document_root, drlen)) goto denied;
  if(rfile[drlen] != '/' && rfile[drlen + 1] != '/') goto denied;
  /* stat */
  if(stat(rfile, &st) != 0) {
    switch (errno) {
      case EACCES: goto denied;
      default: goto not_found;
    }
  }
  /* open */
  if(st.st_size > 0) {
    fd = open(rfile, O_RDONLY);
    if(fd < 0) goto not_found;
    contents = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    close(fd);
    if(contents == MAP_FAILED) goto not_found;
  }
  noit_http_response_ok(ctx, "text/html");
  if(st.st_size > 0) {
    noit_http_response_append(ctx, contents, st.st_size);
    munmap(contents, st.st_size);
  }
  noit_http_response_end(ctx);
  return 0;

 denied:
  noit_http_response_denied(ctx, "text/html");
  noit_http_response_end(ctx);
  return 0;
 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  return 0;
}
int
stratcon_request_dispatcher(noit_http_session_ctx *ctx) {
  const char *key, *value;
  realtime_context *rc = noit_http_session_dispatcher_closure(ctx);
  int klen;
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  noit_http_request *req = noit_http_session_request(ctx);

  if(rc->setup == RC_INITIAL) {
    eventer_t completion;
    struct realtime_tracker *node;
    char c[1024];
    int num_interests;
    const char *uri_str = noit_http_request_uri_str(req);
    noit_hash_table *headers = noit_http_request_headers_table(req);

    num_interests = stratcon_realtime_uri_parse(rc, uri_str);
    if(num_interests == 0) {
      noit_http_response_status_set(ctx, 404, "OK");
      noit_http_response_option_set(ctx, NOIT_HTTP_CLOSE);
      noit_http_response_end(ctx);
      return 0;
    }

    noitL(noit_error, "http: %s %s %s\n",
          noit_http_request_method_str(req), uri_str,
          noit_http_request_protocol_str(req));
    while(noit_hash_next_str(headers, &iter, &key, &klen, &value)) {
      noitL(noit_error, "http: [%s: %s]\n", key, value);
    }
    noit_http_response_status_set(ctx, 200, "OK");
    noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED);
    /*noit_http_response_option_set(ctx, NOIT_HTTP_GZIP);*/
    /*noit_http_response_option_set(ctx, NOIT_HTTP_DEFLATE);*/
    noit_http_response_header_set(ctx, "Content-Type", "text/html");

    snprintf(c, sizeof(c),
             "<html><head><script>document.domain='%s';</script></head><body>\n",
             rc->document_domain);
    noit_http_response_append(ctx, c, strlen(c));

    /* this dumb crap is to make some browsers happy (Safari) */
    memset(c, ' ', sizeof(c));
    noit_http_response_append(ctx, c, sizeof(c));
    noit_http_response_flush(ctx, noit_false);

    rc->setup = RC_REQ_RECV;
    /* Each interest references the ctx */
    for(node = rc->checklist; node; node = node->next) {
      char uuid_str[UUID_STR_LEN+1];
      noit_http_session_ref_inc(ctx);
      uuid_unparse_lower(node->checkid, uuid_str);
      noitL(noit_error, "Resolving uuid: %s\n", uuid_str);
    }
    completion = eventer_alloc();
    completion->mask = EVENTER_TIMER;
    completion->callback = stratcon_realtime_http_postresolve;
    completion->closure = ctx;
    gettimeofday(&completion->whence, NULL);
    stratcon_datastore_push(DS_OP_FIND_COMPLETE, NULL, NULL,
                            rc->checklist, completion);
  }
  return EVENTER_EXCEPTION;
}
Пример #22
0
static int
noit_lua_http_flush_and_end(lua_State *L) {
  CCALL_DECL(L, noit_http_session_ctx, http_ctx, 1);
  noit_http_response_end(http_ctx);
  return 0;
}
Пример #23
0
int
noit_rest_simple_file_handler(noit_http_rest_closure_t *restc,
                              int npats, char **pats) {
  int drlen = 0;
  const char *document_root = NULL;
  const char *index_file = NULL;
  noit_http_session_ctx *ctx = restc->http_ctx;
  char file[PATH_MAX], rfile[PATH_MAX];
  struct stat st;
  int fd;
  void *contents = MAP_FAILED;
  const char *dot = NULL, *slash;
  const char *content_type = "application/octet-stream";

  if(npats != 1 ||
     !noit_hash_retr_str(restc->ac->config,
                         "document_root", strlen("document_root"),
                         &document_root)) {
    goto not_found;
  }
  if(!noit_hash_retr_str(restc->ac->config,
                         "index_file", strlen("index_file"),
                         &index_file)) {
    index_file = "index.html";
  }
  drlen = strlen(document_root);
  snprintf(file, sizeof(file), "%s/%s", document_root, pats[0]);
  if(file[strlen(file) - 1] == '/') {
    snprintf(file + strlen(file), sizeof(file) - strlen(file),
             "%s", index_file);
  }
  /* resolve */
  if(realpath(file, rfile) == NULL) goto not_found;
  /* restrict */
  if(strncmp(rfile, document_root, drlen)) goto denied;
  if(rfile[drlen] != '/' && rfile[drlen + 1] != '/') goto denied;
  /* stat */
  /* coverity[fs_check_call] */
  if(stat(rfile, &st) != 0) {
    switch (errno) {
      case EACCES: goto denied;
      default: goto not_found;
    }
  }
  /* open */
  if(st.st_size > 0) {
    /* coverity[toctou] */
    fd = open(rfile, O_RDONLY);
    if(fd < 0) goto not_found;
    contents = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
    close(fd);
    if(contents == MAP_FAILED) goto not_found;
  }
  /* set content type */
  slash = strchr(rfile, '/');
  while(slash) {
    const char *nslash = strchr(slash+1, '/');
    if(!nslash) break;
    slash = nslash;
  }
  if(slash) dot = strchr(slash+1, '.');
  while(dot) {
    const char *ndot = strchr(dot+1, '.');
    if(!ndot) break;
    dot = ndot;
  }
  /* If there is no extention, just use the filename */
  if(!dot) dot = slash+1;
  if(dot) {
    char ext[PATH_MAX];
    strlcpy(ext, "mime_type_", sizeof(ext));
    strlcpy(ext+strlen(ext), dot+1, sizeof(ext)-strlen(ext));
    if(!noit_hash_retr_str(restc->ac->config,
                           ext, strlen(ext),
                           &content_type)) {
      if(!noit_hash_retr_str(&mime_type_defaults, dot+1, strlen(dot+1),
                             &content_type)) {
        content_type = "application/octet-stream";
      }
    }
  }
  
  noit_http_response_ok(ctx, content_type);
  if(st.st_size > 0) {
    noit_http_response_append(ctx, contents, st.st_size);
    munmap(contents, st.st_size);
  }
  noit_http_response_end(ctx);
  return 0;

 denied:
  noit_http_response_denied(ctx, "text/html");
  noit_http_response_end(ctx);
  return 0;
 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  return 0;
}
Пример #24
0
static int
rest_show_check(noit_http_rest_closure_t *restc,
                int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlXPathObjectPtr pobj = NULL;
  xmlXPathContextPtr xpath_ctxt = NULL;
  xmlDocPtr doc = NULL;
  xmlNodePtr node, root, attr, config, state, tmp, anode;
  uuid_t checkid;
  noit_check_t *check;
  char xpath[1024], *uuid_conf, *module, *value;
  int rv, cnt, error_code = 500;
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  const char *k;
  int klen;
  void *data;
  noit_hash_table *configh;

  if(npats != 2) goto error;

  rv = noit_check_xpath(xpath, sizeof(xpath), pats[0], pats[1]);
  if(rv == 0) goto not_found;
  if(rv < 0) goto error;

  noit_conf_xml_xpath(NULL, &xpath_ctxt);
  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
  if(!pobj || pobj->type != XPATH_NODESET ||
     xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto not_found;
  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
  if(cnt != 1) goto error;

  node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
  uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
  if(!uuid_conf || uuid_parse(uuid_conf, checkid)) goto error;

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"check", NULL);
  xmlDocSetRootElement(doc, root);

#define MYATTR(node,a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b))
#define INHERIT(node,a,n,b) \
  _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b))
#define SHOW_ATTR(parent, node, a) do { \
  xmlNodePtr anode = NULL; \
  char *value = NULL; \
  INHERIT(node, a, anode, value); \
  if(value != NULL) { \
    int clen, plen;\
    const char *cpath, *apath; \
    xmlNodePtr child; \
    cpath = node ? (char *)xmlGetNodePath(node) : ""; \
    apath = anode ? (char *)xmlGetNodePath(anode) : ""; \
    clen = strlen(cpath); \
    plen = strlen("/noit/checks"); \
    child = xmlNewNode(NULL, (xmlChar *)#a); \
    xmlNodeAddContent(child, (xmlChar *)value); \
    if(!strncmp(cpath, apath, clen) && apath[clen] == '/') { \
    } \
    else { \
      xmlSetProp(child, (xmlChar *)"inherited", (xmlChar *)apath+plen); \
    } \
    xmlAddChild(parent, child); \
  } \
} while(0)

  attr = xmlNewNode(NULL, (xmlChar *)"attributes");
  xmlAddChild(root, attr);

  SHOW_ATTR(attr,node,uuid);

  /* Name is odd, it falls back transparently to module */
  if(!INHERIT(node, module, tmp, module)) module = NULL;
  xmlAddChild(attr, (tmp = xmlNewNode(NULL, (xmlChar *)"name")));
  if(MYATTR(node, name, anode, value))
    xmlNodeAddContent(tmp, (xmlChar *)value);
  else if(module)
    xmlNodeAddContent(tmp, (xmlChar *)module);

  SHOW_ATTR(attr,node,module);
  SHOW_ATTR(attr,node,target);
  SHOW_ATTR(attr,node,period);
  SHOW_ATTR(attr,node,timeout);
  SHOW_ATTR(attr,node,oncheck);
  SHOW_ATTR(attr,node,filterset);
  SHOW_ATTR(attr,node,disable);

  /* Add the config */
  config = xmlNewNode(NULL, (xmlChar *)"config");
  configh = noit_conf_get_hash(node, "config");
  while(noit_hash_next(configh, &iter, &k, &klen, &data))
    NODE_CONTENT(config, k, data);
  noit_hash_destroy(configh, free, free);
  free(configh);
  xmlAddChild(root, config);

  /* Add the state */
  check = noit_poller_lookup(checkid);
  if(!check) {
    state = xmlNewNode(NULL, (xmlChar *)"state");
    xmlSetProp(state, (xmlChar *)"error", (xmlChar *)"true");
  }
  else
    state = noit_check_state_as_xml(check);
  xmlAddChild(root, state);
  noit_http_response_ok(ctx, "text/xml");
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(pobj) xmlXPathFreeObject(pobj);
  if(doc) xmlFreeDoc(doc);
  return 0;
}
Пример #25
0
static int
rest_set_filter(noit_http_rest_closure_t *restc,
                int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlDocPtr doc = NULL, indoc = NULL;
  xmlNodePtr node, parent, root, newfilter;
  char xpath[1024];
  int error_code = 500, complete = 0, mask = 0;
  const char *error = "internal error";

  if(npats != 2) goto error;

  indoc = rest_get_xml_upload(restc, &mask, &complete);
  if(!complete) return mask;
  if(indoc == NULL) FAIL("xml parse error");

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);
  node = noit_conf_get_section(NULL, xpath);
  if(!node && noit_filter_exists(pats[1])) {
    /* It's someone else's */
    error_code = 403;
    goto error;
  }

  if((newfilter = validate_filter_post(indoc)) == NULL) goto error;
  xmlSetProp(newfilter, (xmlChar *)"name", (xmlChar *)pats[1]);

  parent = make_conf_path(pats[0]);
  if(!parent) FAIL("invalid path");
  if(node) {
    xmlUnlinkNode(node);
    xmlFreeNode(node);
  }
  xmlUnlinkNode(newfilter);
  xmlAddChild(parent, newfilter);
  CONF_DIRTY(newfilter);

  noit_conf_mark_changed();
  if(noit_conf_write_file(NULL) != 0)
    noitL(noit_error, "local config write failed\n");
  noit_filter_compile_add(newfilter);
  if(restc->call_closure_free) restc->call_closure_free(restc->call_closure);
  restc->call_closure_free = NULL;
  restc->call_closure = NULL;
  restc->fastpath = rest_show_filter;
  return restc->fastpath(restc, restc->nparams, restc->params);

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
  xmlDocSetRootElement(doc, root);
  xmlNodeAddContent(root, (xmlChar *)error);
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}